欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > Redis的集群-详细操作及理论

Redis的集群-详细操作及理论

2024/10/24 15:21:16 来源:https://blog.csdn.net/2301_79450337/article/details/141219415  浏览:    关键词:Redis的集群-详细操作及理论

集群的基本介绍

广义的集群:只要是多个机器,构成了分布式系统,都可以称为是一个”集群“,前面博客所讲的哨兵模式,也可以称为是”广义的集群“

狭义的集群:redis提供的集群模式,这个集群模式之下,主要是要解决,存储空间不足的问题(拓展存储空间)

哨兵模式提高了系统的可用性:哨兵模式中,本质还是redis主从节点存储数据,其中就要求一个主节点/从节点,就得存储整个数据的”全集“

此处关键问题,就是引入多台机器,每台机器存储一部分数据,设由1TB的数据需要存储,拿两台机器来存,每个机器只需要存512G即可;拿三台机器来存,每个机器只需要存300G即可;拿四台机器来存,每个机器只需要存256G即可;随着及其数目的增加,每个机器存储的数据量就减少了;只要机器的规模足够多,就可以存储任意大小的数据了

不是说光搞3个机器就够了,每个存储数据的机器还要搞从节点

哈希求余

把数据分成多份来存,那么如何分呢?

  • 每个 Slave 都是对应 Master 的备份(当 Master 挂了, 对应的 Slave 会补位成 Master)
  • 每个红框部分都可以称为是⼀个 分⽚ (Sharding).

三种主流的分片方式

  • 哈希求余:借鉴了哈希表的基本思想,借助哈希函数,把一个key映射到一个数组下标上

比如有三个分片,编号0 1 2

此时就可以针对要插入的数据的key(redis都是键值对结构的数据)计算哈希值(md5,sha1)再把这个hash值余上分片个数,就得到了一个下标,此时就可以把这个数据放到该下标对应的分片中了,例如hash(key) % N = 0,此时这个key就存储在0号分片中,后续查询key的时候,也是同样的算法,key是一样的,hash函数是一样的,得到的分片值就是一样的

md5特点:

  • md5计算结果是定长的,不论输入的原字符串多长,最终输出的字符串是一样长的
  • 计算结果是分散的,两个原字符串,哪怕大部分相同,只有一个小的地方不同,算出来的md5值也会差别很大
  • md5计算结果是不可逆的,原字符串可以到加密后的字符串,但是加密后的字符串无法还原到原字符串(网上的md5破解均是一些彩虹表中的内容)

一旦服务器集群需要扩容,就需要更高的成本了,分片主要目的就是为了提高存储能力,分片越多,能存的数据越多,成本也更高

引入新的分片,N就改变了,hash(key) % N,那么很多数据所存储的位置都要改变,需要重新进行分配数据(搬运)

上述级别的扩容,开销是极大的,只能通过”替换“来搬运数据,但是依赖的机器更多了,操作步骤也变复杂了

  • 一致性哈希算法:key 映射到分⽚序号的过程不再是简单求余了

  • 把 0 -> 2^32-1 这个数据空间, 映射到⼀个圆环上. 数据按照顺时针⽅向增⻓.

  • 假设当前存在三个分⽚, 就把分⽚放到圆环的某个位置上

  • 假定有⼀个 key, 计算得到 hash 值 H, 那么这个 key 映射到哪个分⽚呢? 规则很简单, 就是从 H 所在位置, 顺时针往下找, 找到的第⼀个分⽚, 即为该 key 所从属的分⽚

这就相当于, N 个分⽚的位置, 把整个圆环分成了 N 个管辖区间. Key 的 hash 值落在某个区间内, 就归对应区间管理

在哈希求余中,因为交替出现,导致搬运成本变大了;在一致性哈希中,把交替出现改为了连续出现,就减少了搬运成本

上述⼀致性哈希算法的过程, 类似于去⾼铁站取票. 现在的⾼铁站都可以直接刷⾝份证了. 但是以前的时候需要⽹上先购票, 然后再去⾼铁站的取 票机上把票取出来. 想象下列场景:

假设, ⼀个⼈每次来⾼铁站, 都会停⻋在同⼀个位置. (不同的⼈停⻋位置不同)

每个⼈下⻋之后, 都往右⼿⽅向⾛, 遇到第⼀个取票机就进⾏取票

Question:在这个情况下, 如果扩容⼀个分⽚, 如何处理呢?


Answer:原有分⽚在环上的位置不动, 只要在环上新安排⼀个分⽚位置即可.

此时, 只需要把 0 号分⽚上的部分数据, 搬运给 3 号分⽚即可. 1 号分⽚和 2 号分⽚管理的区间都是不变 的

  • 优点: ⼤⼤降低了扩容时数据搬运的规模, 提⾼了扩容操作的效率
  • 缺点: 数据分配不均匀 (有的多有的少, 数据倾斜)

如果一次扩容搞多个分片,可以避免数据倾斜的情况,总的搬运数据量仍然是比最初的hash求余的方式更少的

  • 哈希槽分区算法-Redis真正采用的算法

为了解决上述问题 (搬运成本⾼ 和 数据分配不均匀), Redis cluster 引⼊了哈希槽 (hash slots) 算法

hash_slot = crc16(key) % 16384
//16384 = 16 * 1024 = 2 ^ 14
//hash_slot-哈希槽

把上述的哈希槽,分配到不同的分片上

假设当前有三个分⽚, ⼀种可能的分配⽅式,虽然不是严格意义的”均匀“,但是差异非常小

  • 0号分⽚: [0, 5461], 共 5462 个槽位
  • 1号分⽚: [5462, 10923], 共 5462 个槽位
  • 2号分⽚: [10924, 16383], 共 5460 个槽位

此时这三个分片上的数据就是比较均匀的了,这里只是一种可能的分配方式,实际上分片是非常灵活的,每个分片持有的槽位号,可以是连续,也可以是不连续;此处,每个分片都会使用”位图“这样的数据结构,表示出当前有多少个槽位号,16384个bit位(2KB),用每一位0/1来区分自己这个分片是否持有该槽位号;这这算法就是把哈希求余和一致性哈希结合起来

如果需要进⾏扩容, ⽐如新增⼀个 3 号分⽚, 就可以针对原有的槽位进⾏重新分配,⽐如可以把之前每个分⽚持有的槽位, 各拿出⼀点, 分给新分⽚. ⼀种可能的分配⽅式:

  • 0 号分⽚: [0, 4095], 共 4096 个槽位
  • 1 号分⽚: [5462, 9557], 共 4096 个槽位
  • 2 号分⽚: [10924, 15019], 共 4096 个槽位
  • 3 号分⽚: [4096, 5461] + [9558, 10923] + [15019, 16383], 共 4096 个槽位,针对某个分片,不一定非得是连续的区间

在上述过程中,只有被移动的槽位,对应的数据才需要搬运

我们在实际使用Redis 集群分片的时候, 不需要⼿动指定哪些槽位分配给某个分⽚, 只需要告 诉某个分⽚应该持有多少个槽位即可, Redis 会⾃动完成后续的槽位分配, 以及对应的 key 搬 运的⼯作.

Question:

  1. Redis 集群是最多有 16384 个分⽚吗?
  2. 为什么是 16384 个槽位?

Answer:

  1. 并⾮如此. 如果⼀个分⽚只有⼀个槽位, 这对于集群的数据均匀其实是难以保证的;实际上 Redis 的作者建议集群分⽚数不应该超过 1000;⽽且,16000 这么⼤规模的集群, 本⾝的可⽤性也是⼀个⼤问题. ⼀个系统越复杂, 出现故障的概率是越⾼的
  2. Redis 作者的答案: https://github.com/antirez/redis/issues/2576
  3. 翻译过来⼤概意思是:
  • 节点之间通过⼼跳包通信. ⼼跳包中包含了该节点持有哪些 slots. 这个是使⽤位图这样的数据结构 表⽰的. 表⽰ 16384 (16k) 个 slots, 需要的位图⼤⼩是 2KB. 如果给定的 slots 数更多了, ⽐如 65536 个了, 此时就需要消耗更多的空间, 8 KB 位图表⽰了. 8 KB, 对于内存来说不算什么, 但是在频繁的⽹ 络⼼跳包中, 还是⼀个不⼩的开销的
  • 另⼀⽅⾯, Redis 集群⼀般不建议超过 1000 个分⽚. 所以 16k 对于最⼤ 1000 个分⽚来说是⾜够⽤ 的, 同时也会使对应的槽位配置位图体积不⾄于很⼤

基于docker搭建集群环境

生成配置文件

此处我们先创建出 11 个 redis 节点. 其中前 9 个⽤来演⽰集群的搭建,后两个⽤来演⽰集群扩容

创建目录和配置

创建 redis-cluster ⽬录. 内部创建两个⽂件;记得把之前启动的redis容器,停止掉

redis-cluster/
├── docker-compose.yml
└── generate.sh

generate.sh 内容如下(使用Linux的时候,都是通过一些命令来进行操作的,使用命令操作,就非常适合把命令给写到一个文件中,批量化执行,同时,还能加入条件循环函数等机制,因此就可以基于这些来完成更复杂的操作)->需要创建11个redis节点,这些redis的配置文件内容,大同小异,此时就可以使用脚本来批量生成

#for循环,基于范围的循环,Java中的foreach,seq是一个Linux命令,生成一个[1,9]
for port in $(seq 1 9); \
#从do-done表示范围,{}表示变量,不表示代码块
#\表示续行符,把下一行和当前行,合并成一行,shell默认情况下,要求把所有的代码都写到一行里的,使用#续行符来换行
do \
#创建目录,并且拼接字符串不需要使用+
mkdir -p redis${port}/
#在该目录下创建配置文件
touch redis${port}/redis.conf
#写内容,写EOF,内容是下面的内容
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
#开启AOF
appendonly yes
#开启集群
cluster-enabled yes
#nodes.conf不需要手动来写,而是redis自动生成,自动配置一些redis集群信息
cluster-config-file nodes.conf
#多个节点之间进行交互,保持联络,心跳包超时时间
cluster-node-timeout 5000
#announce,该redis节点自己所在的主机ip地址(docker容器模拟的主机,此处写的应该是docker容器的#ip)
cluster-announce-ip 172.30.0.10${port}
#port就是redis节点自身绑定的端口(容器内的端口),不同的容器内部可以由相同的端口,后续进行端口映#射,再把这些容器内的端口映射到容器外的不同端口即可
cluster-announce-port 6379
#业务端口:用来进行业务数据通信的,响应redis客户端的请求的
#管理端口:为了完成一些管理上的任务进行通信的,如果某个分片中的redis主节点挂了,就需要让从节点成##为主节点,就需要通过管理端口来完成对于的操作,例如Tomcat的8080是业务端口,8005是管理端口
cluster-announce-bus-port 16379
EOF
done
# 注意 cluster-announce-ip 的值有变化.
for port in $(seq 10 11); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done

预期效果,得到11个目录,每个目录都有一个配置文件,配置文件中,IP各不相同

执⾏命令

bash generate.sh

⽣成⽬录如下:

redis-cluster/
├── docker-compose.yml
├── generate.sh
├── redis1
│   └── redis.conf
├── redis10
│   └── redis.conf
├── redis11
│   └── redis.conf
├── redis2
│   └── redis.conf
├── redis3
│   └── redis.conf
├── redis4
│   └── redis.conf
├── redis5
│   └── redis.conf
├── redis6
│   └── redis.conf
├── redis7
│   └── redis.conf
├── redis8
│   └── redis.conf
└── redis9└── redis.conf

搭建集群环境-创建容器

version: '3.7'
#此处为了后续创建静态IP,此时先手动创建网络,同时给这个网段也分配IP,IP地址=网络号+主机号
#使用子网掩码方式来区分网络号和主机号,子网掩码就是左边24位是1,右边8位是0
#172.30.0网络号 IP是内网IP:10.* 172.16-172.31.* 192.168.*;不能和其他机器上的IP地址相同
networks:mynet:ipam:config:- subnet: 172.30.0.0/24
services:redis1:image: 'redis:5.0.9'container_name: redis1restart: always
#shell脚本创建的目录,这里就包含配置文件,此处不进行端口映射也是可以的;映射一下目的是为了在容器
#外面通过客户端直接进行访问
#静态IP,网络号要和·前面的网段一致,主机号部分可以随便配置(0-255,保证不重复,就是按照之前的配置#文件中写的)volumes:- ./redis1/:/etc/redis/ports:- 6371:6379- 16371:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.101
#redis2和redis1不同的地方redis2:image: 'redis:5.0.9'
#container_name: redis2restart: alwaysvolumes:- ./redis2/:/etc/redis/ports:
#- 6372:6379- 16372:16379command:redis-server /etc/redis/redis.confnetworks:mynet:
#ipv4_address: 172.30.0.102redis3:image: 'redis:5.0.9'container_name: redis3restart: alwaysvolumes:- ./redis3/:/etc/redis/ports:- 6373:6379- 16373:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.103redis4:image: 'redis:5.0.9'container_name: redis4restart: alwaysvolumes:- ./redis4/:/etc/redis/ports:- 6374:6379- 16374:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.104redis5:image: 'redis:5.0.9'container_name: redis5restart: alwaysvolumes:- ./redis5/:/etc/redis/ports:- 6375:6379- 16375:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.105redis6:image: 'redis:5.0.9'container_name: redis6restart: alwaysvolumes:- ./redis6/:/etc/redis/ports:- 6376:6379- 16376:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.106redis7:image: 'redis:5.0.9'container_name: redis7restart: alwaysvolumes:- ./redis7/:/etc/redis/ports:- 6377:6379- 16377:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.107redis8:image: 'redis:5.0.9'container_name: redis8restart: alwaysvolumes:- ./redis8/:/etc/redis/ports:- 6378:6379- 16378:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.108redis9:image: 'redis:5.0.9'container_name: redis9restart: alwaysvolumes:- ./redis9/:/etc/redis/ports:- 6379:6379- 16379:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.109redis10:image: 'redis:5.0.9'container_name: redis10restart: alwaysvolumes:- ./redis10/:/etc/redis/ports:- 6380:6379- 16380:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.110redis11:image: 'redis:5.0.9'container_name: redis11restart: alwaysvolumes:- ./redis11/:/etc/redis/ports:- 6381:6379- 16381:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.111

保证两个配置文件中的IP地址是一样的

启动容器

一定要关闭之前的容器!!!!!

docker-compose up -d

搭建集群环境-配置集群关系

把上述redis容器构建成集群

redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379
172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379
172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2
#--cluster-replicas 2 描述集群的每个节点,应该是有两个从节点
#配置这个之后,redis就知道了,3个节点是一伙的,一共9个节点,一共是3个分片了
#redis在构建集群的时候,谁是主节点,谁是从节点,是不确定的
#从集群的角度看,提供的这些节点之间本身就应该是等价的
--cluster create 表⽰建⽴集群. 后⾯填写每个节点的 ip 和地址
--cluster-replicas 2 表⽰每个主节点需要两个从节点备份

列出每个参与构建集群的IP和端口,端口都是写容器内部的端口号

  • 此时, 使⽤客⼾端连上集群中的任何⼀个节点, 都相当于连上了整个集群
  • 客⼾端后⾯要加上 -c 选项, 否则如果 key 没有落到当前节点上, 是不能操作的. -c 会⾃动把请求 重定向到对应节点
  • 使⽤ cluster nodes 可以查看到整个集群的情况.

使用集群

从101-109 9个节点,现在是一个整体,使用客户端连上任意一个,都相当于连上了集群

使用集群来存储数据,之前redis操作的命令都是适用的(不够严谨),有些指令,是能够操作多个key的,此时如果key是存在多个服务器上,则无法获取,但是可以使用(hash tag)

设置成集群模式之后,当前数据就分片了,k1通过hash计算之后,得到了slot为12706,属于103这个分片,可以在启动redis-cli的时候,加上-c选项

重新设置,客户端变成了103,-c选项添加之后,redis客户端就会根据当前key实际计算出来的槽位号,自动找到匹配的分片主机,进一步的就可以完成操作

故障处理

Question:如果集群中,有节点挂了,怎么办


Answer:如果挂了的节点是从节点,没事!如果挂了的节点是主节点,主节点才可以操作写操作,此处集群做的工作和哨兵做的类似,会自动把该主节点旗下从节点给挑出来,提拔成主节点!

关闭一个redis服务器

提拔主节点

重新启动redis1

集群机制,也能处理故障转移,但是和哨兵模式并不一样

处理流程

  • 故障判定

集群中的所有节点, 都会周期性的使⽤⼼跳包进⾏通信

  1. 节点 A 给 节点 B 发送 ping 包, B 就会给 A 返回⼀个 pong 包. ping 和 pong 除了 message type 属性之外, 其他部分都是⼀样的. 这⾥包含了集群的配置信息(该节点的id, 该节点从属于哪个分⽚, 是主节点还是从节点, 从属于谁, 持有哪些 slots 的位图...)
  2. 每个节点, 每秒钟, 都会给⼀些随机的节点发起 ping 包, ⽽不是全发⼀遍. 这样设定是为了避免在节 点很多的时候, ⼼跳包也⾮常多(⽐如有 9 个节点, 如果全发, 就是 9 * 8 有 72 组⼼跳了, ⽽且这是按 照 N^2 这样的级别增⻓的)
  3. 当节点 A 给节点 B 发起 ping 包, B 不能如期回应的时候, 此时 A 就会尝试重置和 B 的 tcp 连接, 看能 否连接成功. 如果仍然连接失败, A 就会把 B 设为 PFAIL 状态(相当于主观下线)
  4. A 判定 B 为 PFAIL 之后, 会通过 redis 内置的 Gossip 协议, 和其他节点进⾏沟通, 向其他节点确认 B 的状态. (每个节点都会维护⼀个⾃⼰的 "下线列表", 由于视⻆不同, 每个节点的下线列表也不⼀定相 同)
  5. 此时 A 发现其他很多节点, 也认为 B 为 PFAIL, 并且数⽬超过总集群个数的⼀半, 那么 A 就会把 B 标 记成 FAIL (相当于客观下线), 并且把这个消息同步给其他节点(其他节点收到之后, 也会把 B 标记成 FAIL). ⾄此, B 就彻底被判定为故障节点了
  • 故障迁移

上述例⼦中, B 故障, 并且 A 把 B FAIL 的消息告知集群中的其他节点

如果 B 是从节点, 那么不需要进⾏故障迁移

如果 B 是主节点, 那么就会由 B 的从节点 (⽐如 C 和 D) 触发故障迁移了

所谓故障迁移, 就是指把从节点提拔成主节点, 继续给整个 redis 集群提供⽀持. 具体流程如下:

  1. 从节点判定⾃⼰是否具有参选资格. 如果从节点和主节点已经太久没通信(此时认为从节点的数据和 主节点差异太⼤了), 时间超过阈值, 就失去竞选资格
  2. 具有资格的节点, ⽐如 C 和 D, 就会先休眠⼀定时间. 休眠时间 = 500ms 基础时间 + [0, 500ms] 随机 时间 + 排名 * 1000ms. offset 的值越⼤, 则排名越靠前(越⼩)
  3. ⽐如 C 的休眠时间到了, C 就会给其他所有集群中的节点, 进⾏拉票操作. 但是只有主节点才有投票资格
  4. 主节点就会把⾃⼰的票投给 C (每个主节点只有 1 票). 当 C 收到的票数超过主节点数⽬的⼀半, C 就 会晋升成主节点. (C ⾃⼰负责执⾏ slaveof no one, 并且让 D 执⾏ slaveof C)
  5. 同时, C 还会把⾃⼰成为主节点的消息, 同步给其他集群的节点. ⼤家也都会更新⾃⼰保存的集群结构 信息
  • 哨兵是先竞选出leader,再找一个从节点升级为主节点;这里是直接投票选出新的主节点
  • 谁休眠时间短,谁就是新的主节点了

上述选举的过程, 称为 Raft 算法, 是⼀种在分布式系统中⼴泛使⽤的算法. 在随机休眠时间的加持下, 基本上就是谁先唤醒, 谁就能竞选成功

某个或者某些节点宕机, 有的时候会引起整个集群都宕机 (称为 fail 状态),以下三种情况会出现集群宕机:

  • 某个分⽚, 所有的主节点和从节点都挂了
  • 某个分⽚, 主节点挂了, 但是没有从节点.
  • 超过半数的 master 节点都挂

核⼼原则是保证每个 slots 都能正常⼯作(存取数据)

集群扩容

101-109 9个主机,构成了3主,6从结构的集群了,110和111也加入到集群中,以110为master,111为slave,把数据分片3->4,集群扩容操作,是一件风险较高,成本较大的操作

  • 新的主节点(110)加入到集群中
redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
#                            被新增的节点       集群上的任意一个节点,表示加入哪个集群

4个master,新增加的master没有新的slots

  • 重新分配slots,把之前三组master上面的slots拎出来一些,分配给新的master
redis-cli --cluster reshard 172.30.0.101:6379
# reshard 后的地址是集群中的任意节点地址.
#另外, 注意单词拼写, 是 reshard (重新切分), 不是 reshared (重新分享) , 不要多写个 e.

执⾏之后, 会进⼊交互式操作, redis 会提⽰⽤⼾输⼊以下内容:

  • 多少个 slots 要进⾏ reshard ? (此处我们填写 4096)
  • 哪个节点来接收这些 slots ? (此处我们填写 172.30.0.110 这个节点的集群节点 id)
  • 这些 slots 从哪些节点搬运过来? (此处我们填写 all, 表⽰从其他所有的节点都进⾏搬运)

可以看到slots中多了很多

如果在搬运slots/key的过程中,此时客户端能否访问咱们redis集群呢?

搬运key,大部分的key是不用搬运的,针对这些未搬运的key,此时是可以正常访问的,针对这些正在搬运中的key,是有可能会出现访问出错的情况的

假设客户端访问k1,集群通过分片算法,得到k1是第一个分片的数据,就会重定向第一个分片的节点,就可能在重定向过去之后,正好被k1被搬走了,自然就无法访问了

  • 把从节点也添加到集群中

111填进来,作为110的从节点

redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --clusterslave --cluster-master-id [172.30.1.110 节点的 nodeId]

代码连接集群

详细请看Redis和Java之间的爱恨情仇之连接Redis服务器-CSDN博客

这里只要使用JedisCluster 类代替 Jedis 类即可,使用的库,得能够支持集群模式

public static void main(String[] args) {Set<HostAndPort> nodes = new HashSet<>();nodes.add(new HostAndPort("172.30.0.101", 6379));nodes.add(new HostAndPort("172.30.0.102", 6379));nodes.add(new HostAndPort("172.30.0.103", 6379));nodes.add(new HostAndPort("172.30.0.104", 6379));nodes.add(new HostAndPort("172.30.0.105", 6379));nodes.add(new HostAndPort("172.30.0.106", 6379));nodes.add(new HostAndPort("172.30.0.107", 6379));nodes.add(new HostAndPort("172.30.0.108", 6379));nodes.add(new HostAndPort("172.30.0.109", 6379));try (JedisCluster jedisCluster = new JedisCluster(nodes)) {jedisCluster.set("k1", "111");String value = jedisCluster.get("k1");System.out.println(value);}
}

注意! 由于此处我们的代码是需要访问整个 redis 集群, 因此不能直接在 windows 上运⾏程序了. (上述 docker 容器的 ip 都是 windows 主机上⽆法直接访问的). 需要把整个程序打成 jar 包, 上传到 Linux 中, 并通过下列⽅式运⾏

 java -jar [jar包名]

小结:

  1. 集群是什么?解决了什么问题
  2. 数据分片算法
  3. 搭建redis集群
  4. 集群容灾,故障转移
  5. 集群扩容
  6. 代码连接集群
  • 哈希求余
  • 一致性哈希
  • 哈希槽分区

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com