redis cluster 是Redis官方退出的集群方案,采用主从加选举方案保证高可用,采用类似一致性哈希(哈希槽)的方式保证数据容量可以横向拓展,只移动部分元素就可以实现动态添加删除节点,是比较常用的redis集群方案。
这里总结一些使用过程中容易忽视的的问题,或者是比较有用的技巧。
1. redis cluster 每个节点都需要开启两个TCP端口
一个是redis服务端和客户端通信的端口,比如配置端口6379,响应的redis会使用 6379+10000=16379端口,作为集群总线,用于集群间数据交互。10000 这个数字是固定的。所以搭建redis集群的时候要确保防火墙放开了客户端端口和集群总线端口。否则客户端功能或者集群功能将无法正常使用。
2. hash Tag
hash Tag是redis集群比较好用的特性。当然这个功能我们也可以再客户端这边自己去实现。简单来讲hash tag就是可以标记key中用hash算法生成hash槽的部分。从而控制特定的key被分配到特定的hash槽中,从而可使用redis的批量命令(mget,mset等),这个功能的问题也比较明显,就是有可能会导致数据分配不均。使用方式就是把key中需要用来做hash的部分用{}括起来,比如 {englishClass}_zhangsan, {englishClass}_lisi。 这两个key会被分配到一个hash槽中,从而可以用mget批量获取一个班级的所有学生。
3. redis集群数据一致性问题。redis集群不保证数据强一致性,有两种会导致丢失数据的情况。
(1)主节点同步数据到从节点之前宕机,从节点升级为主节点,导致数据丢失。
例如主节点A, 有一个从节点B, 主节点A收到set name zhangsan的命令后,处理结束后返回客户端成功,然后再异步去通知从节点B set命令。如果主节点A在返回客户端之后,通知从节点之前宕机,过一段时间之后会由集群的选举机制选举从节点B为新的主节点,但是B节点是没有name zhangsan这条数据的,即便过一会主节点A恢复,也会同步节点B的数据,name 这条数据就丢失了。
解决方案:wait命令,将客户端阻塞,异步变同步。wait命令使用方式:wait 1 意思是等待主节点之前的所有写操作成功通知一个从节点之后返回。也可以加上超时时间,wait 1 1000 最长不能超过1秒返回,1秒后超时返回成功同步的从节点个数。
(2)脑裂
比如有集群:A a B b C c 主节点:A B C 从节点 a1 b1 c1 。 如果出现网络问题,集群脑裂成两个子集群 A B a1 b1 c1和 C, 在多数节点的集群中,检测到C主节点宕机,c1从节点升级为主节点,网络恢复之后,C节点加入成为c1的从节点。就会导致网络分裂时期对C节点的数据写入丢失。
解决方案:节点超时时间(node timeout)。主节点宕机超过node timeout后,从节点C1升级为主节点。如果主节点C在超过node timeout后,还是无法感知大多数的主节点,则变为error状态并拒绝写入操作。
4. manual failover
因为redis集群不保证强一致性,存在数据丢失风险,所以如果想要主动下掉某个主节点的话,其实是有数据丢失风险的。这个时候,manual failover 就可以起到作用。如果某个主节点出现问题,想要重启,或者迁移之类的操作的话,可以使用redis 的CLUSTER FAILOVER 命令。从想要下线的主节点的从节点发起命令,主节点和从节点会调换身份。期间会阻塞客户端请求一段时间,保证数据一致后,开始转换,从而保证数据一致性。
5. 转换到cluster模式。
该功能支持从单主节点redis数据转换成redis cluster模式(例如5个主节点),主要复制数据到5个主节点就行,从节点可以待后期添加,从节点不会影响数据分布。
1). 停掉客户端
2). 使用BGREWRITEAOF命令,保证数据都同步到AOF文件。
3). 把AOF文件保存5份。
4). 创建5个主节点,确定是AOF的持久化方式,后期再添加从节点
5). 停掉所有节点,配置他们的AOF文件为刚才创建的AOF文件,每个节点一份。
6). 重启所有节点,让其加载对应的配置文件。
7). 用redis-cli --cluster fix
命令让数据在各节点之前迁移。
用redis-cli --cluster check 命令检查集群状态
8). 重启客户端。