rediscluser集群
redis-cluser集群
接上一篇redis集群模式还有一种模式叫做集群模式(redis-cluser).
Redis Cluster是一种服务器 Sharding 技术,3.0版本开始正式提供。Redis 的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台 Redis 服务器都存储相同的数据,很浪费内存,所以在 redis3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的内容。 原理 优缺点 搭建 扩容、缩容 redis-cluserRedis 集群的数据分片
Redis 集群没有使用一致性hash, 而是引入了 哈希槽 的概念.
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么: 节点 A 包含 0 到 5500号哈希槽. 节点 B 包含5501 到 11000 号哈希槽. 节点 C 包含11001 到 16384号哈希槽.
这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中的部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.
每个redis节点负责 0 ~ 16383的某一段,这样在数据进来的时候经过CRC16 的算法的结果对16383取余数就可以定位到对应的redis节点数据的读取和写入和对应的节点交互。本质上这个是属于hash环的hash寻址算法。 hash环寻址方式
整体步骤如下:
1、节点加入环:将节点通过hash(节点的信息如ip端口等) 获取节点在环上位置。
2、数据读写: 读写数据时对key进行同样的hash操作获取在换上的位置,然后顺时针寻找最近的节点进行读写。 当 新增和删除节点 的时候hash环的寻址方式也只会影响部分数据,而不是全部数据。 还有一种可能性,redis节点在hash后在 hash环节点分布不均匀 ,那么大部分数据都打在同一个节点上,导致请求和数据倾斜,这样就不能很好的保证负载均衡。这个时候可以采用增加虚拟节点对每一个节点计算多个hash,尽量保证环上的节点是均匀的。(当然数据倾斜也有其他的原因)
Redis-cluser的优缺点
优点: 更好的水平扩展支持,因为根据槽位进行均匀分配,当新增或者减少redis实例的时候自动将槽位均匀迁移到其他可用的redis实例上去。 redis的每个节点的利用率更好,节点存储数据压力也不是很大
缺点: 键的批量操作支持有限 键事务支持有限,当多个键分布在不同节点时无法使用事务,同一节点是支持事务 键是数据分区的最小粒度,不能将一个很大的键值对映射到不同的节点 不支持多数据库,只有0,select 0 复制结构只支持单层结构,不支持树型结构 Gossip协议(流行病协议)
戏称狗屎协议
Gossip协议又被称为流行病协议(Epidemic Protocol),也有人叫它反熵(Anti-Entropy)。Gossip协议于1987年在ACM上发表的论文 《Epidemic Algorithms for Replicated Database Maintenance》中被提出,主要用在分布式数据库系统中各个副本节点间的数据同步,这种场景的一个最大特点就是组成网络的节点都是对等的(去中心化P2P),网络中即使有的节点因宕机而重启,或有新节点加入,但经过一段时间后,这些节点的状态也会与其他节点达成一致,也就是说,Gossip天然具有分布式容错的优点(容错性)。(一致性收敛)这个主要从信息同步的速度来讲的。假设网络中有N个节点,那信息同步到全网络的速度理论上仅需为O(log(N))次(具体每个节点一次同步的节点数由fanout参数决定)。还记得高数吗?这种对数函数的收敛速度是很快的。它是一个带冗余的容错算法,是一个最终一致性算法。虽然无法保证在某个时刻所有节点状态一致,但可以保证在"最终"所有节点一致,"最终"是一个现实中存在,但理论上无法证明的时间点。大名鼎鼎的 Bitcoin 则是使用了 Gossip 协议来传播交易和区块信息,实际上Gossip可以用于众多能接受"最终一致性"的领域:失败检测、路由同步、Pub/Sub、动态负载均衡。但Gossip的缺点也很明显,冗余通信会对网路带宽、CPU资源造成很大的负载,而这些负载又受限于通信频率,该频率又影响着算法收敛的速度,因此,针对不同的应用场景,也有很多的优化方法。
Gossip协议的主要职责就是信息交换,信息交换的载体就是节点之间彼此发送的Gossip消息,常用的Gossip消息有ping消息、pong消息、meet消息、fail消息 meet消息:用于通知新节点加入,消息发送者通知接收者加入到当前集群,meet消息通信完后,接收节点会加入到集群中,并进行周期性ping pong交换 ping消息:集群内交换最频繁的消息,集群内每个节点每秒向其它节点发ping消息,用于检测节点是在在线和状态信息,ping消息发送封装自身节点和其他节点的状态数据; pong消息,当接收到ping meet消息时,作为响应消息返回给发送方,用来确认正常通信,pong消息也封闭了自身状态数据; fail消息:当节点判定集群内的另一节点下线时,会向集群内广播一个fail消息 集群搭建cluser搭建
每个节点的配置文件如下(其他节点就是改一改端口和文件名称即可), # 主从配置 # 端口 port 6379 # 开启集群模式 cluster-enabled yes # 节点超时时间 cluster-node-timeout 15000 # 集群内部配置文件 cluster-config-file /usr/local/bin/clustercon/data/nodes-6379.conf # 启动集群 ./redis-server clusterconf/redis6379.conf & ./redis-server clusterconf/redis6380.conf & ./redis-server clusterconf/redis6381.conf & ./redis-server clusterconf/redis6389.conf & ./redis-server clusterconf/redis6390.conf & ./redis-server clusterconf/redis6391.conf & # 自动指定 redis-cli --cluster create 主1 主2 主3 从1 从2 从3 --cluster-replicas 1 # 健康检查(这里要对所有节点进行检查) ./redis-trib.rb check 192.168.42.111:6379 # 如此出现了这个问题,将对应的槽位号打开 cluster setslot 1180 stable; # 查看集群信息 cluster info # 查看集群节点 cluster nodes新增/删除节点
准备好配置文件 # 新增主节点 6379是原存在的主节点,6382是新的主节点 redis-cli add-node 192.168.42.111:6382 192.168.42.111:6379 # 添加集群从节点 redis-cli add-node --slave --master-id 062464bc7590400441fafb63f2 192.168.42.111:6392 192.168.42.111:6379 # 重新分配solt redis-trib.rb reshard 192.168.42.111:6382 # 删除节点 ## 从节点删除 redis-cli --cluster reshard 172.17.0.4:6379 --cluster-from "46623a0b2ec8abb8a0688769337e91268df3c73f" --cluster-to "14d129294d95867777a91d29b708413baa8a276c" --cluster-slots 2500 --cluster-yes # 参数说明: # host:port:必传参数,集群内任意节点地址,用来获取整个集群信息。 # --cluster-from:制定源节点的id,如果有多个源节点,使用逗号分隔,如果是all源节点变为集群内所有主节点,在迁移过程中提示用户输入。 # --cluster-to:需要迁移的目标节点的id,目标节点只能填写一个,在迁移过程中提示用户输入。 # --cluster-slots:需要迁移槽的总数量,在迁移过程中提示用户输入。 # --cluster-yes:当打印出reshard执行计划时,是否需要用户输入yes确认后再执行reshard。 # --cluster-timeout:控制每次migrate操作的超时时间,默认为60000毫秒。 # --cluster-pipeline:控制每次批量迁移键的数量,默认为10。 redis-cli --cluster reshard host:port --cluster-from --cluster-to --cluster-slots --cluster-yes --cluster-timeout --cluster-pipeline redis-cli --cluster reshard 172.17.0.4:6379 --cluster-from "46623a0b2ec8abb8a0688769337e91268df3c73f" --cluster-to "8a7b1a4cf2980c031c0e5e912cf366981588e3c9" --cluster-slots 2962 --cluster-yes # 待转移slot完毕后删除节点 redis-cli --cluster del-node 172.17.0.7:6379 "f9e78f563314a1d88796ec0ca2b13e4ac3cae75f"
封面图侵权删