《Redis设计与实现》读书笔记(二十九) ——Redis集群执行命令与重新分片

《Redis设计与实现》读书笔记(二十九) ——Redis集群执行命令与重新分片

(原创内容,转载请注明来源,谢谢)

一、集群中执行命令

1、节点对命令的判断

当对集群的16384个槽都完成指派后,集群就上线,可以对集群进行操作。当客户端向节点发送数据库键有关的命令,接收命令的节点,会计算命令属于哪个槽,并检查槽是否指派给自己。

如果槽是该节点负责,则执行命令;如果不是,返回一个moved错误,指引客户端对正确的节点执行命令,客户端根据返回结果,会自动连接上相应的节点,再次执行命令。

2、计算键属于哪个槽

假设键名为key,计算方法如下:

crc16(key) & 16383

其中,crc16是一种算法,将key用crc16算法获取的结果,在与16383进行比较,获取一个介于0~16383的整数。

可以采用cluster keyslotkey,查看键属于哪个槽。

3、判断槽是否由当前节点处理

根据上述算法计算出键所述的槽后,节点会与clusterState的slots相应下标的指针比对:

如果指针指向自身则表示该槽由自身负责;

如果指针不是指向自身,而是指向某个节点的clusterNode结构,则从该结构获取ip和端口号,并将ip、端口号、moved错误一并返回给客户端。

4、moved错误介绍

move命令为:moved<slot> <ip> <port>

当客户端收到moved命令,就会解析里面的ip和端口号,并重新连上相应的节点,再执行命令。

不过,由于moved错误的时候,处于集群状态下的redis-cli客户端会自动重定向,显示的也是redirect,因此客户端上看不到报错信息。

但是,如果是单机模式下的redis-cli客户端,则会直接报错,因为其并不知道moved命令的含义,也不会自动连接上新的节点。

5、节点数据的实现

集群节点有个限制,只能用0号数据库。键值对的保存方式和单机一样。另外,节点的clusterState结构,还会保存槽和键的关系。

         typedef structclusterState{
         //….其他内容
         zskiplist*slots_to_keys;

}clusterState;

节点保存槽和键的关系,用的是zskiplist,其分值(score)是槽的编号,每个阶节点成员(member)是数据库的键。如下:

将键这样保存,便于批量操作。例如cluster getkeysinslot <slot> <count>命令(重新分片相关命令),可以返回最多count个,槽是slot的键。

二、重新分片

1、概述

redis集群的重新分片功能,可以将任意数量已经指派给某个节点的槽,修改为指派给另一个节点,且相关槽对应的数据库的键值对数据也迁移到另一个节点。

重新分片工作可以在线进行,集群不需要下线,并且源节点和目标节点都可以正常处理客户端的其他命令。

2、原理

redis重新分片,是由redis集群管理软件redis-trib负责执行的,redis提供了进行重新分配所需的所有命令。而redis-trib软件通过向源节点和目标节点发送命令,来完成重新分片的工作。

对单个槽进行重新分片,步骤如下:

1)redis-trib对目标节点发送命令clustersetslot <slot> importing <source_id>命令,让目标节点准备好从源节点导入编号是slot的槽的键值对。

2)redis-trib对源节点发送命令clustersetslot <slot> migrating <target_id>命令,让源节点准备好将编号是slot的槽的键值对导入到目标节点。

3)redis-trib向源节点发送命令clustergetkeysinslot <slot> <count>命令,获取最多count个属于槽slot的键值对的键。

4)对于第3步的每个键,redis-trib都向源节点发送命令migrate<target_ip> <target_port> <key_name> 0 <timeout>命令,将被选中的键迁移到目标节点。

5)重复3、4步骤,直到所有属于编号slot的槽都完成迁移。

6)redis-trib将命令clustersetsslot <slot> node <target_id>发送给集群中的任一节点,然后命令会在集群中广播,所有节点都会知道槽slot已经归目标节点负责。

如果是多个槽重新分片,则每个槽都会经历上述的步骤进行重新分片。

—written by linhxx 2017.09.15

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP技术

高性能网站架构方案

主从复制功能通过在主服务器和从服务器之间切分处理客户查询的负荷,可以得到更好的客户响应时间SELECT查询可以发送到从服务器,以降低主服务器的查询处理负荷。修改...

2028
来自专栏简单聊聊Spark

Spark内核分析之Scheduler资源调度机制

        上一篇我们阐述了Driver,Application,Worker的注册实现原理,本篇我们来接着聊聊Driver,Application在注册之...

1082
来自专栏顶级程序员

Linux吃掉我的内存

在Windows下资源管理器查看内存使用的情况,如果使用率达到80%以上,再运行大程序就能感觉到系统不流畅了,因为在内存紧缺的情况下使用交换分区,频繁地从磁盘...

3135
来自专栏「3306 Pai」社区

nginx+php-fpm故障排查

小明初到一家公司做运维的工作,刚来的第一天就开始部署LNMP(Linux+Nginx+MySQL+PHP)环境,结果出现了问题。 他来向我请教。

811
来自专栏同步博客

Redis构建分布式锁

  为什么要构建锁呢?因为构建合适的锁可以在高并发下能够保持数据的一致性,即客户端在执行连贯的命令时上锁的数据不会被别的客户端的更改而发生错误。同时还能够保证命...

812
来自专栏个人分享

Redis应用配置项说明

# 默认情况下 redis 不是作为守护进程运行的,如果你想让它在后台运行,你就把它改成 yes。

491
来自专栏性能与架构

Redis 优化执行命令的延时

Redis 是单线程的,客户端的命令请求在server中会被排队,按照顺序处理,如果队列长,命令执行结果的响应时间便会长 ? 如果客户端想要快点得到执行结果,可...

4406
来自专栏个人分享

Hadoop 2.6 MapReduce运行原理详解

  市面上的hadoop权威指南一类的都是老版本的书籍了,索性学习并翻译了下最新版的Hadoop:The Definitive Guide, 4th Editi...

631
来自专栏用户画像

流水时空图

指令流水线有“取指”IF、“译码”ID、“执行”EX、“访存”MEM、“写回”WB五个过程段,共有20条指令连续输入此流水线。

552
来自专栏我是攻城师

如何管理Spark Streaming消费Kafka的偏移量(二)

3254

扫码关注云+社区