前言
随着时间的推移redis保存的键值也越多,rdb快照也越大,因此会产生这样一个问题:
因为fork出bgsave进程来保存rdb时,会拷贝一份自己的内存,fork操作用时和redis数据量呈正相关,因此redis的响应有时会变的非常慢(info latest_fork_usec命令查看最近一次fork耗时)
此时我们就需要利用切片技术,将数据平均分到多个实例中保存
快速利用docker搭建(3主0从)
- 准备
1.redis5.0以上镜像(5.0以上搭建切片集群不需要ruby)
2.redis.conf -
文件夹的创建
文件夹准备
相同的redis.conf,data文件里的东西忽略是运行后生成的
- 修改各自的redis.conf
三个docker容器分别开放8004-8006和18004-18005两个端口
这里以实例redis8004为例,修改配置(其他改端口就好):
//这里我没设置,要设置自己修改
port 8004
#bind 127.0.0.1 //注释掉,允许外部连接
protected-mode no //关闭保护模式
cluster-enabled yes //开启集群
cluster-config-file nodes.conf //集群节点配置
cluster-node-timeout 5000 //超时
cluster-announce-ip x.x.x.x //宿主机IP,不是容器的虚拟IP!!
cluster-announce-port 8004
cluster-announce-bus-port 18004
编写3个脚本redis.sh(也一样修改文件夹名称和容器名称就好)
#! /bin/bash
docker run -d --name redis8006 --net host --privileged=true -v /home/docker/redis/cluster/8006/conf:/etc/redis/conf -v /home/docker/redis/cluster/8006/data:/data redis:5.0.5 redis-server /etc/redis/conf/redis.conf
运行各自的docker容器
./redis.sh
进入其中一个节点
docker exec -it redis8004 /bin/bash
//配置集群
redis-cli --cluster create 192.168.x.x:8004 192.168.x.x:8005 192.168.x.x:8006 --cluster-replicas 0
// --cluster-replicas 0 是因为每个主实例没有从实例
记得云服务器安全组开放8004-8006和18004-18006端口,否则会一直处于等待状态
测试节点
docker exec -it redis8004 redis-cli -c -p 8004
>cluster nodes
>cluster info
> set name
>get name
完成!!
Redis Cluter
集群切片是一种保存大量数据的通用机制,从3.0开始Redis官方提供了一个Redis Cluster的方案来实现集群切片。
该方案采用哈希槽(hash slot)来处理数据和实例之间的映射。哈希槽类似数据分区,每个键值会根据它的key,被映射到一个哈希槽中(该方案中一个切片集群共有16384个哈希槽)
哈希槽如何被映射到Redis实例中
我们如上使用cluster create命令创建集群,此时Redis会把这些槽平均分配到集群中,每个实例上槽个数为16384/实例个数N。
不同机子内存不同,可不可以不平均分配
利用cluster meet手动创建实例连接,再用cluster addslots手动分配哈希槽(需要全部分配完16384个槽否则集群无法工作)
分配完了客户端如何定位数据
1.Redis会把自己的哈希槽信息发给和他相连的其他实例,这样每个哈希槽就有所有的哈希槽映射关系了。
2.客户端和集群连接后实例会把哈希槽信息发给客户端
3.客户端缓存于本地,请求键值对时先计算对应的哈希槽,再给实例发送请求
哈希槽在分配后是否不变
不是的,常见的有
- 实例的新增或删除,重新分配
- 负载均衡
Redis Cluster也提供了一种重定向机制,当客户端发送的实例上因为哈希槽的重新分配导致访问不到时,实例会给客户端发送MOVED命令响应结果(包含了新实例的访问地址),客户端只要拿着这个地址重新访问即可(更新缓存)。若此时数据正在迁移则返回ASK命令(表示自己正在迁移,包含新实例的信息),客户端给新势力发送ASKING命令,再发送操作命令。
ASK命令并不会更新客户端的哈希槽信息缓存
网友评论