2.2 常用数据分布办法之顺序分布
比如:1到100个数字,要保存在3个节点上,按照顺序分区,把数据均匀分配三个节点上1号到33号数据保存到节点1上,34号到66号数据保存到节点2上,67号到100号数据保存到节点3上
顺序分区常用在关系型数据库的设计
例如1到100个数字,对每个数字进行哈希运算,然后对每个数的哈希结果除以节点数进行取余,余数为1则保存在第1个节点上,余数为2则保存在第2个节点上,余数为0则保存在第3个节点,这样可以担保数据被打散,同时担保数据分布的比较均匀。

哈希分布办法分为三个分区办法:
2.3.1 节点取余分区比如有100个数据,对每个数据进行hash运算之后,与节点数进行取余运算,根据余数不同保存在不同的节点上
节点取余办法是非常大略的一种分区办法
节点取余分区办法有一个问题:即当增加或减少节点时,原来节点中的80%的数据会进行迁移操作,对所有数据重新进行分布
节点取余分区办法建议利用多倍扩容的办法,例如以前用3个节点保存数据,扩容为比以前多一倍的节点即6个节点来保存数据,这样只须要适移50%的数据。数据迁移之后,第一次无法从缓存中读取数据,必须先从数据库中读取数据,然后回写到缓存中,然后才能从缓存中读取迁移之后的数据
节点取余办法优点:
1.主从复制不能实现高可用2.随着公司发展,用户数量增多,并发越来越多,业务须要更高的QPS,而主从复制中单机的QPS可能无法知足业务需求3.数据量的考虑,现有做事器内存不能知足业务数据的须要时,纯挚向做事器添加内存不能达到哀求,此时须要考虑分布式需求,把数据分布到不同做事器上4.网络流量需求:业务的流量已经超过做事器的网卡的上限值,可以考虑利用分布式来进行分流5.离线打算,须要中间环节缓冲等别的需求
节点取余办法缺陷:
数据节点伸缩时,导致数据迁移迁移数量和添加节点数据有关,建议翻倍扩容
2.3.2 同等性哈希分区
同等性哈希事理:
将所有的数据当做一个token环,token环中的数据范围是0到2的32次方。然后为每一个数据节点分配一个token范围值,这个节点就卖力保存这个范围内的数据。
对每一个key进行hash运算,被哈希后的结果在哪个token的范围内,则按顺时针去找最近的节点,这个key将会被保存在这个节点上。
在上面的图中,有4个key被hash之后的值在在n1节点和n2节点之间,按照顺时针规则,这4个key都会被保存在n2节点上,如果在n1节点和n2节点之间添加n5节点,当下次有key被hash之后的值在n1节点和n5节点之间,这些key就会被保存在n5节点上面了。
在上面的例子里,添加n5节点之后,数据迁移会在n1节点和n2节点之间进行,n3节点和n4节点不受影响,数据迁移范围被缩小很多。
同理,如果有1000个节点,此时添加一个节点,受影响的节点范围最多只有千分之2。
同等性哈希一样平常用在节点比较多的时候。
同等性哈希分区优点:
采取客户端分片办法:哈希 + 顺时针(优化取余)节点伸缩时,只影响临近节点,但是还是有数据迁移
同等性哈希分区缺陷:
翻倍伸缩,担保最小迁移数据和负载均衡
2.3.3 虚拟槽分区
虚拟槽分区是Redis Cluster采取的分区办法
预设虚拟槽,每个槽就相称于一个数字,有一定范围。每个槽映射一个数据子集,一样平常比节点数大
Redis Cluster中预设虚拟槽的范围为0到16383
步骤:
把16384槽按照节点数量进行均匀分配,由节点进行管理对每个key按照CRC16规则进行hash运算把hash结果对16383进行取余把余数发送给Redis节点节点吸收到数据,验证是否在自己管理的槽编号的范围,如果在自己管理的槽编号范围内,则把数据保存到数据槽中,然后返回实行结果,如果在自己管理的槽编号范围外,则会把数据发送给精确的节点,由精确的节点来把数据保存在对应的槽中。须要把稳的是:Redis Cluster的节点之间会共享,每个节点都会知道是哪个节点卖力哪个范围内的数据槽
虚拟槽分布办法中,由于每个节点管理一部分数据槽,数据保存到数据槽中。当节点扩容或者缩容时,对数据槽进行重新分配迁移即可,数据不会丢失。虚拟槽分区特点:
利用做事端管理节点,槽,数据:例如Redis Cluster
可以对数据打散,又可以担保数据分布均匀
2.3 顺序分布与哈希分布的比拟3.Redis Cluster基本架构3.1 节点Redis Cluster是分布式架构:即Redis Cluster中有多个节点,每个节点都卖力进行数据读写操作
每个节点之间会进行通信。
3.2 meet操作节点之间会相互通信
meet操作是节点之间完成相互通信的根本,meet操作有一定的频率和规则
3.3 分配槽
把16384个槽均匀分配给节点进行管理,每个节点只能对自己卖力的槽进行读写操作
由于每个节点之间都彼此通信,每个节点都知作别的节点卖力管理的槽范围
客户端访问任意节点时,对数据key按照CRC16规则进行hash运算,然后对运算结果对16383进行取作,如果余数在当前访问的节点管理的槽范围内,则直接返回对应的数据如果不在当前节点卖力管理的槽范围内,则会见告客户端去哪个节点获取数据,由客户端去精确的节点获取数据
3.4 复制
担保高可用,每个主节点都有一个从节点,当主节点故障,Cluster会按照规则实现主备的高可用性
对付节点来说,有一个配置项:cluster-enabled,即是否以集群模式启动
3.5 客户端路由3.5.1 moved重定向每个节点通过通信都会共享Redis Cluster中槽和集群中对应节点的关系客户端向Redis Cluster的任意节点发送命令,吸收命令的节点会根据CRC16规则进行hash运算与16383取余,打算自己的槽和对应节点如果保存数据的槽被分配给当前节点,则去槽中实行命令,并把命令实行结果返回给客户端如果保存数据的槽不在当前节点的管理范围内,则向客户端返回moved重定向非常客户端吸收到节点返回的结果,如果是moved非常,则从moved非常中获取目标节点的信息客户端向目标节点发送命令,获取命令实行结果须要把稳的是:客户端不会自动找到目标节点实行命令
槽命中:直接返回
[root@mysql ~]# redis-cli -p 9002 cluster keyslot hello(integer) 866
槽不命中:moved非常
[root@mysql ~]# redis-cli -p 9002 cluster keyslot php(integer) 9244
[root@mysql ~]# redis-cli -c -p 9002127.0.0.1:9002> cluster keyslot hello(integer) 866127.0.0.1:9002> set hello world-> Redirected to slot [866] located at 192.168.81.100:9003OK192.168.81.100:9003> cluster keyslot python(integer) 7252192.168.81.100:9003> set python best-> Redirected to slot [7252] located at 192.168.81.101:9002OK192.168.81.101:9002> get python"best"192.168.81.101:9002> get hello-> Redirected to slot [866] located at 192.168.81.100:9003"world"192.168.81.100:9003> exit[root@mysql ~]# redis-cli -p 9002127.0.0.1:9002> cluster keyslot python(integer) 7252127.0.0.1:9002> set python bestOK127.0.0.1:9002> set hello world(error) MOVED 866 192.168.81.100:9003127.0.0.1:9002> exit[root@mysql ~]#
3.5.2 ask重定向
在对集群进行扩容和缩容时,须要对槽及槽中数据进行迁移
当客户端向某个节点发送命令,节点向客户端返回moved非常,见告客户端数据对应的槽的节点信息
如果此时正在进行集群扩展或者缩空操作,当客户端向精确的节点发送命令时,槽及槽中数据已经被迁移到别的节点了,就会返回ask,这便是ask重定向机制
步骤:
客户端向目标节点发送命令,目标节点中的槽已经迁移支别的节点上了,此时目标节点会返回ask转向给客户端客户端向新的节点发送Asking命令给新的节点,然后再次向新节点发送命令新节点实行命令,把命令实行结果返回给客户端moved非常与ask非常的相同点和不同点
两者都是客户端重定向
moved非常:槽已经确定迁移,即槽已经不在当前节点
ask非常:槽还在迁移中
3.5.3 smart智能客户端利用智能客户真个紧张目标:追求性能
从集群中选一个可运行节点,利用Cluster slots初始化槽和节点映射
将Cluster slots的结果映射在本地,为每个节点创建JedisPool,相称于为每个redis节点都设置一个JedisPool,然后就可以进行数据读写操作
读写数据时的把稳事变:
每个JedisPool中缓存了slot和节点node的关系key和slot的关系:对key进行CRC16规则进行hash后与16383取余得到的结果便是槽JedisCluster启动时,已经知道key,slot和node之间的关系,可以找到目标节点JedisCluster对目标节点发送命令,目标节点直接相应给JedisCluster如果JedisCluster与目标节点连接出错,则JedisCluster会知道连接的节点是一个缺点的节点此时JedisCluster会随机节点发送命令,随机节点返回moved非常给JedisClusterJedisCluster会重新初始化slot与node节点的缓存关系,然后向新的目标节点发送命令,目标命令实行命令并向JedisCluster相应如果命令发送次数超过5次,则抛出非常"Too many cluster redirection!"
Redis Cluster不支持利用scan命令扫描所有节点多节点命令便是在在所有节点上都实行一条命令批量操作优化
3.6.1 串行mget定义for循环,遍历所有的key,分别去所有的Redis节点中获取值并进行汇总,大略,但是效率不高,须要n次网络韶光
3.6.2 串行IO
对串行mget进行优化,在客户端本地做内聚,对每个key进行CRC16hash,然后与16383取余,就可以知道哪个key对应的是哪个槽
本地已经缓存了槽与节点的对应关系,然后对key按节点进行分组,成立子集,然后利用pipeline把命令发送到对应的node,须要nodes次网络韶光,大大减少了网络韶光开销
3.6.3 并行IO
并行IO是对串行IO的一个优化,把key分组之后,根据节点数量启动对应的线程数,根据多线程模式并行向node节点要求数据,只须要1次网络韶光
3.6.4 hash_tag
将key进行hash_tag的包装,然后把tag用大括号括起来,担保所有的key只向一个node要求数据,这样实行类似mget命令只须要去一个节点获取数据即可,效率更高
3.6.5 四种优化方案优缺陷剖析
3.7 故障创造Redis Cluster通过ping/pong实现故障创造:不须要sentinel
ping/pong不仅能通报节点与槽的对应,也能通报其他状态,比如:节点主从状态,节点故障等
故障创造便是通过这种模式来实现,分为主不雅观下线和客不雅观下线
3.7.1 主不雅观下线某个节点认为另一个节点不可用,'偏见',只代表一个节点对另一个节点的判断,不代表所有节点的认知
主不雅观下线流程:
节点1定期发送ping给节点2。如果发送成功,代表节点2正常运行,节点2会相应PONG给节点1,节点1更新与节点2的末了通信韶光。如果发送失落败,则节点1与节点2之间的通信非常判断连接,不才一个定时任务周期时,仍旧会与节点2发送ping。如果节点1创造与节点2末了通信韶光超过node-timeout,则把节点2标识为pfail状态。3.7.2 客不雅观下线当半数以上持有槽的主节点都标记某节点主不雅观下线时,可以担保判断的公正性
集群模式下,只有主节点(master)才有读写权限和集群槽的掩护权限,从节点(slave)只有复制的权限
客不雅观下线流程:
1.某个节点吸收到其他节点发送的ping,如果吸收到的ping中包含了其他pfail节点,这个节点会将主不雅观下线的内容添加到自身的故障列表中,故障列表中包含了当前节点吸收到的每一个节点对其他节点的状态信息
2.当前节点把主不雅观下线的内容添加到自身的故障列表之后,会考试测验对故障节点进行客不雅观下线操作
故障列表的周期为:集群的node-timeout 2,担保以前的故障不会对周期内的故障造成影响,担保客不雅观下线的公正性和有效性
3.8 故障规复3.8.1 资格检讨对从节点的资格进行检讨,只有难过检讨的从节点才可以开始进行故障规复每个从节点检讨与故障主节点的断线韶光超过cluster-node-timeout cluster-slave-validity-factor数字,则取消资格cluster-node-timeout默认为15秒,cluster-slave-validity-factor默认值为10如果这两个参数都利用默认值,则每个节点都检讨与故障主节点的断线韶光,如果超过150秒,则这个节点就没有成为更换主节点的可能性3.9.2 准备选举韶光
使偏移量最大的从节点具备优先级成为主节点的条件
对选举出来的多个从节点进行投票,选出新的主节点
当前从节点取消复制变成离节点(slaveof no one)实行cluster del slot撤销故障主节点卖力的槽,并实行cluster add slot把这些槽分配给自己向集群广播自己的pong,表明已经更换了故障从节点
3.8.5 故障转移演习训练
对某一个主节点实行kill -9 {pid}来仿照宕机的情形
3.9 Redis Cluster的缺陷
当节点数量很多时,性能不会很高
办理办法:利用智能客户端。智能客户端知道由哪个节点卖力管理哪个槽,而且当节点与槽的映射关系发生改变时,客户端也会知道这个改变,这是一种非常高效的方当节点数量很多时,性能不会很高办理办法:利用智能客户端。智能客户端知道由哪个节点卖力管理哪个槽,而且当节点与槽的映射关系发生改变时,客户端也会知道这个改变,这是一种非常高效的办法
4.搭建Redis Cluster搭建Redis Cluster有两种安装办法
1.原生命令安装2.官方工具安装5.开拓运维常见的问题5.1 集群完全性cluster-require-full-coverage默认为yes,即是否集群中的所有节点都是在线状态且16384个槽都处于做事状态时,集群才会供应做事
集群中16384个槽全部处于做事状态,担保集群完全性
当某个节点故障或者正在故障转移时获取数据会提示:(error)CLUSTERDOWN The cluster is down
建议把cluster-require-full-coverage设置为no
5.2 带宽花费Redis Cluster节点之间会定期交流Gossip,以及做一些心跳检测
官方建议Redis Cluster节点数量不要超过1000个,当集群中节点数量过多时,会产生不容忽略的带宽花费
发送频率:节点创造与其他节点末了通信韶光超过cluster-node-timeout /2时,会直接发送PING
数据量:slots槽数组(2kb空间)和全体集群1/10的状态数据(10个节点状态数据约为1kb)
节点支配的机器规模:集群分布的机器越多且每台机器划分的节点数越均匀,则集群内整体的可用带宽越高
带宽优化:
避免利用'大'集群:避免多业务利用一个集群,大业务可以多集群cluster-node-timeout:带宽和故障转移速率的均衡只管即便均匀分配到多机器上:担保高可用和带宽
5.3 Pub/Sub广播
在任意一个cluster节点实行publish,则发布的会在集群中传播,集群中的其他节点都会订阅到,这样节点的带宽的开销会很大
publish在集群每个节点广播,加重带宽
办理办法:须要利用Pub/Sub时,为了担保高可用,可以单独开启一套Redis Sentinel
5.4 集群倾斜对付分布式数据库来说,存在倾斜问题是比较常见的
集群倾斜也便是各个节点利用的内存不一致
5.4.1 数据倾斜缘故原由1.节点和槽分配不均,如果利用redis-trib.rb工具构建集群,则涌现这种情形的机会不多
redis-trib.rb info ip:port查看节点,槽,键值分布redis-trib.rb rebalance ip:port进行均衡(谨慎利用)
2.不同槽对应键值数量差异比较大
CRC16算法正常情形下比较均匀可能存在hash_tagcluster countkeysinslot {slot}获取槽对应键值个数
3.包含bigkey:例如大字符串,几百万的元素的hash,set等
在从节点:redis-cli --bigkeys优化:优化数据构造
4.内存干系配置不一致
hash-max-ziplist-value:知足一定条件情形下,hash可以利用ziplistset-max-intset-entries:知足一定条件情形下,set可以利用intset在一个集群内有多少个节点,当个中一些节点配置上面两项优化,其余一部分节点没有配置上面两项优化当集群中保存hash或者set时,就会造成节点数据不屈均优化:定期检讨配置同等性
5.要求倾斜:热点key
主要的key或者bigkeyRedis Cluster某个节点有一个非常主要的key,就会存在热点问题
5.4.2 集群倾斜优化:
避免bigkey热键不要用hash_tag当同等性不高时,可以用本地缓存+ MQ(行列步队)
5.5 集群读写分离
只读连接:集群模式下,从节点不接管任何读写要求
当向从节点实行读要求时,重定向到卖力槽的主节点
readonly命令可以读:连接级别命令,当连接断开之后,须要再次实行readonly命令
读写分离:
同样的问题:复制延迟,读取过期数据,从节点故障修正客户端:cluster slaves {nodeId}
5.6 数据迁移
官方迁移工具:redis-trib.rb和import
只能从单机迁移到集群
不支持在线迁移:source须要停写
不支持断点续传
单线程迁移:影响深度
在线迁移:
唯品会:redis-migrate-tool豌豆荚:redis-port
5.7 集群VS单机
集群的限定:
key批量操作支持有限:例如mget,mset必须在一个slotkey事务和Lua支持有限:操作的key必须在一个节点key是数据分区的最小粒度:不支持bigkey分区不支持多个数据库:集群模式下只有一个db0复制只支持一层:不支持树形复制构造Redis Cluster知足容量和性能的扩展性,很多业务'不须要'大多数时客户端性能会'降落'命令无法跨节点利用:mget,keys,scan,flush,sinter等Lua和事务无法跨节点利用客户端掩护更繁芜:SDK和运用本身花费(例如更多的连接池)
很多场景Redis Sentinel已经够用了
6.Redis Cluster总结:1.Redis Cluster数据分区规则采取虚拟槽办法(16384个槽),每个节点卖力一部分槽和干系数据,实现数据和要求的负载均衡2.搭建Redis Cluster划分四个步骤:准备节点,meet操作,分配槽,复制数据。3.Redis官方推举利用redis-trib.rb工具快速搭建Redis Cluster4.集群伸缩通过在节点之间移动槽和干系数据实现 扩容时根据槽迁移操持把槽从源节点迁移到新节点 紧缩时如果下线的节点有卖力的槽须要迁移到其他节点,再通过cluster forget命令让集群内所有节点忘却被下线节点5.利用smart客户端操作集群过到通信效率最大化,客户端内部卖力打算掩护键,槽以及节点的映射,用于快速定位到目标节点6.集群自动故障转移过程分为故障创造和节点规复。节点下线分为主不雅观下线和客不雅观下线,当超过半数节点认为故障节点为主不雅观下线时,标记这个节点为客不雅观下线状态。从节点卖力对客不雅观下线的主节点触发故障规复流程,担保集群的可用性7.开拓运维常见问题包括:超大规模集群带席花费,