搭建redis 集群

创建一个网桥

docker network create -d bridge --subnet=192.168.148.0/24 --gateway=192.168.148.1 -o parent=eno1 redis-net

通过docker 文件创建redis 集群, 这里注意要不要使用redis 7以上的版本,不然会出问题

version: "3"

services:

redis7001:

image: redis:6.2.14 # 指定redis镜像,可以是name:tag/id

container_name: redis7001 # 启动后的镜像名称,可有可无

ports:

- "7001:7001" # 指定对外端口

- "17001:17001" # 指定集群端口,根据官网一般为对外端口+10000

volumes:

# 挂载主机中的配置文件

- /home/duron/docker/redis_cluster/redis.conf:/conf/redis.conf

# 将数据保存在主机上, 防止丢失

- /home/duron/docker/redis_cluster/7001:/data

command:

# 默认的redis启动命令

- "redis-server"

# 加载指定的配置文件,这里是镜像内的路径

- "/conf/redis.conf"

# 对外端口号,也可以在redistribution.conf中配置

- "--port 7001"

# 开启redis集群模式,也可以在redistribution.conf中配置

- "--cluster-enabled yes"

# 集群节点配置文件名,也可以在redistribution.conf中配置

- "--cluster-config-file nodes-7001.conf"

networks:

extnetwork:

ipv4_address: 192.168.148.71 # 向桥接网络申请ip地址

redis7002:

image: redis:6.2.14

container_name: redis7002

ports:

- "7002:7002"

- "17002:17002"

volumes:

- /home/duron/docker/redis_cluster/redis.conf:/conf/redis.conf

- /home/duron/docker/redis_cluster/7002:/data

command:

- "redis-server"

- "/conf/redis.conf"

- "--port 7002"

- "--cluster-enabled yes"

- "--cluster-config-file nodes-7002.conf"

networks:

extnetwork:

ipv4_address: 192.168.148.72

redis7003:

image: redis:6.2.14

container_name: redis7003

ports:

- "7003:7003"

- "17003:17003"

volumes:

- /home/duron/docker/redis_cluster/redis.conf:/conf/redis.conf

- /home/duron/docker/redis_cluster/7003:/data

command:

- "redis-server"

- "/conf/redis.conf"

- "--port 7003"

- "--cluster-enabled yes"

- "--cluster-config-file nodes-7003.conf"

networks:

extnetwork:

ipv4_address: 192.168.148.73

redis7004:

image: redis:6.2.14

container_name: redis7004

ports:

- "7004:7004"

- "17004:17004"

volumes:

- /home/duron/docker/redis_cluster/redis.conf:/conf/redis.conf

- /home/duron/docker/redis_cluster/7004:/data

command:

- "redis-server"

- "/conf/redis.conf"

- "--port 7004"

- "--cluster-enabled yes"

- "--cluster-config-file nodes-7004.conf"

networks:

extnetwork:

ipv4_address: 192.168.148.74

redis7005:

image: redis:6.2.14

container_name: redis7005

ports:

- "7005:7005"

- "17005:17005"

volumes:

- /home/duron/docker/redis_cluster/redis.conf:/conf/redis.conf

- /home/duron/docker/redis_cluster/7005:/data

command:

- "redis-server"

- "/conf/redis.conf"

- "--port 7005"

- "--cluster-enabled yes"

- "--cluster-config-file nodes-7005.conf"

networks:

extnetwork:

ipv4_address: 192.168.148.75

redis7006:

image: redis:6.2.14

container_name: redis7006

ports:

- "7006:7006"

- "17006:17006"

volumes:

- /home/duron/docker/redis_cluster/redis.conf:/conf/redis.conf

- /home/duron/docker/redis_cluster/7006:/data

command:

- "redis-server"

- "/conf/redis.conf"

- "--port 7006"

- "--cluster-enabled yes"

- "--cluster-config-file nodes-7006.conf"

networks:

extnetwork:

ipv4_address: 192.168.148.76

networks:

extnetwork: # 定义外部桥接网络

external:

name: redis-net

什么是redis cluster的hash slot

redis的hash槽在redis集群中的作用是用来将数据分配到不同的slot,来降低单个节点的压力,来保证redis的工作效率。

redis 是如何将key分配到不同的槽里的呢

redis 是同过CRC16 算法对数据进行hash取值然后在和16384 进行去模的到的slot的结果,我们在查询/存储key的时候会更具slot去获取数据或写入数据。

为什么要分配16384个

Redis 集群使用哈希槽(hash slot)来决定一个给定的键应该被分配到哪个节点。总共有 16384 个哈希槽,这个数字是一个折中的选择。

如果哈希槽的数量太少,例如只有 100 个,那么在大规模集群中,每个节点将需要处理大量的哈希槽,这可能会导致负载分布不均。另一方面,如果哈希槽的数量太多,例如 1 亿,那么管理这些哈希槽的开销将会非常大,尤其是在节点添加或删除时。

因此,16384 是一个在分布均匀性和管理开销之间取得平衡的数字。它足够大,可以在大规模集群中实现均匀的负载分布,同时又足够小,可以在节点变动时快速重新分配哈希槽。

为什么redis hash 槽要选择CRC16算法

计算速度快:CRC16 是一种非常简单的算法,计算速度非常快。这对于 Redis 这种需要处理大量键值对的数据库系统来说非常重要。 分布均匀:虽然 CRC16 是一种简单的算法,但它生成的哈希值在 0 到 16383 之间的分布是相当均匀的。这意味着键值对在 Redis 集群的各个节点之间的分布也会比较均匀。

redis 是如何获取slot的

1.) 在我们进行查询和写入操作的时候,代码在构建玩cmd的时候我们就进入了process函数,该函数的第一步就是先获取slot,红框中的代码就是获取到hash槽中的slot的值 2.)我们进入到cmdSlot 函数里面我们就会发现,我们马上要开始获取slot了,在进入cmdFirstKeyPos获取到pos值以后我们就可以进入slot函数获取hash slot的值了(keyPos 字段是用来帮助 go-redis 库正确地处理 Redis 集群的一个重要字段。) 3.)我们从这里就看到了hash slot的算法了,他正如我说的那样通过crc16算出hash值和16384 进行取模来获取我们需要通过那个slot来获取/写入数据

获取到slot后我们如何获取连接呢?

1.) 我们通过代码可以看到在获取到slot后,我们会进入一个cmdNode的一个函数里面,我们就是通过slot值在这个函数里面获取到node 节点的。 2.)我们进入cmdNode 可以看出来,这个函数给我们做了读写分离,因为我们没有开启读写分离,所以我们默认会进入slotMasterNode里面 3.) 我们进入这个函数可以看到,我们通过sloaNodes来获取slot 如果nodes获取失败 = 0的情况下 我们默认走了random模式 默认随机了 4. )该函数我们可以看出来,这个函数判断了我们的slot是否在这些nodes 里面,如果在并获取这个节点的节点信息。

注意:

以上代码是在"github.com/redis/go-redis/v9" v9版本的支持下进行的,如果我们使用的是v6版本,我们会发现在我们进行slot 获取的时候会报错,报错会存储到firstErr的一个字段里面,这时候系统监测到该字段有错误,就会默认进行 随机获取slot的一个操作。

redis: got 7 elements in COMMAND reply, wanted 6

所以我们如果想使用hash slot 就需要升级到高一些的版本。

精彩内容

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。