学习docker第六天之redis集群(3主3从)

问题:1~2亿条数据需要做缓存,请设计一个落地方案。

对于亿级数据的存储来说,单机肯定不可能实现,需要使用到分布式缓存,对于分布式缓存来说,redis集群是一个很好的方案。但是对于集群,又引入一个新的问题,数据需要存和取都在同一台机器,那么如何实现存和取都在同一台机器呢?

方案一:

哈希取余算法:

比如需要搭建3台redis集群,通过hash(key)/3来确定数据落在那台机器上,同样取数据也是通过hash(key)/3落在那台机器上取数据。

优点:粗暴简单,直接有效

缺点:一般来说,对于集群环境,都需要集群的扩缩,所以当机器数量变化时候(扩缩容时,或者某台机器挂了),取余数量为机器数量,这样就会导致 /机器数的改变,从而导致取数据落点机器错误,导致无法取出。

方案二:

一致性哈希算法:

为了在节点数目发生变化的时候尽可能少迁移数据,将所有的存储节点(节点例如通过ip地址hash)排列在首尾相接的hash环上,每个key在计算hash后会顺时针找到临近的存储节点存放。而当有节点加入或退出时仅仅影响的是hash环上顺时针相邻的后续节点。

优点:加入或者删除节点只影响相邻的节点,对其他节点无影响

缺点:因为这些节点在哈希环上是不均匀分布,所以在数据存储时候达不到均匀分布的效果,导致数据倾斜。

方案三:

哈希槽算法:

关于哈希槽,实质就是一个大小为[0,2^14-1]的数组,形成的hash slot空间。这样就解决了均匀分配的问题,在数据和节点之间加一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放得是槽,数据放在槽里面。槽解决的是粒度问题,相当于把粒度变大了,便于数据的移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据的分配。

一个集群只能有16384个槽,编号0-16383(0-2^14-1)。注:关于为什么是16384个,可以参考redis之父对于槽的回答https://github.com/redis/redis/issues/2576https://github.com/redis/redis/issues/2576
这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot = CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

3主3从集群搭建

首先启动6个redis容器。

docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381

docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382

docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383

docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384

docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385

docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386

参数说明

 随便进入一个redis容器,使用命令搭建集群环境

#你的ip+端口
redis-cli --cluster create 192.168.111.147:6381 192.168.111.147:6382 192.168.111.147:6383 192.168.111.147:6384 192.168.111.147:6385 192.168.111.147:6386 --cluster-replicas 1

注:这里笔者踩了两个坑,因为笔者用的是腾讯云,没有开发相关端口,导致这行命令连接超时,只需要开启端口后,再次执行这个命令即可进入下一步。

 到了这一步只需要执行yes即可完成redis节点的3主3从搭配,但是这一步笔者又超时了,具体原因在于redis的集群搭建中,一个端口是客户端连接使用,即我们docker run的时候设置的端口,还有一个是redis节点间相互通信的内部总线端口,此端口比我们设置的大10000,所以再开发这些端口就成功了。

 查看集群状态

 集群搭建完毕后,尝试在集群中写入数据,发现有些可以写入有些不可以。(原因在于目前环境是集群环境,而我是通过 redis-cli -p 6381进入的第一台机器,因为第3台主机器存入的key值为0-5460,5461-10922,10923-16383,而当slot=CRC16(key)%16384不在这一台机器范围时,存入就失败)

进入redis cli端命令修改,增加-c 防止路由失效

 查看集群情况

redis-cli --cluster check ip:端口

 

 注意:当master 故障后,对应的slave会成为新的master。当故障的master恢复后,会成为新的slave。这里就不演示了

集群的扩容

新建两台redis容器,具体指定看上面的redis容器操作。然后将第一台redis容器加入集群后,检查集群情况

//第一个ip端口为新容器的,后一个为集群环境的
redis-cli --cluster add-node ip:端口 ip:端口
//检查集群情况
redis-cli --cluster check ip:端口

 将新的容器加入集群后,发现槽位为0,所以需要分配槽位。redis-cli --cluster reshard IP地址:端口号

 重新检查集群情况

redis-cli --cluster check 真实ip地址:6381

发现分配的槽位并非是重新平均分配,而是从之前的3个master上分配过来。这样就可以避免重新分配导致成本过高。槽位分配后,再将slave绑定到第四个master即可。然后检查集群状况

redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID

redis-cli --cluster check ip:端口

绑定成功 

集群的缩容

首先缩容涉及节点的删除,所以需要先删除从节点再删除主节点,当节点删除后,需要再重新分配槽位。

//第一步检查集群状态,获取6388的node id
redis-cli --cluster check ip:端口
//第二步删除6388 node节点
redis-cli --cluster del-node ip:端口 node id
//第三步再次检查集群状态,查看是否删除成功
redis-cli --cluster check ip:端口

 

 只剩下7台机器,4个master,3个slave。然后将第四个master槽位分配给第一个master。

redis-cli --cluster reshard ip:端口

 

 删除6387

redis-cli --cluster del-node ip:端口 6387节点ID

再次检查后,节点缩容为3主3从

 至此docker之redis集群3主3从完结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值