Redis分片集群 - 解决高并发写的问题

分片集群与哨兵集群的区别

  • 主从和哨兵集群:解决了高可用、高并发读问题,但无法解决海量存储和高并发写的问题

  • 分片集群:可以解决高并发写的问题,同时也可以解决高并发读的问题

.
.

分片集群特征

  • 集群中有多个master,每个master保存不同数据

  • 每个master都可以由多个slave节点

  • master之间通过ping监测彼此监控状态,多个master认为某个master主观下线则会将该master变为客观下线,然后从slave中选举新的master, master选举同哨兵模式

  • 客户端请求可以访问集群任意节点,最终都会被转发到正确的节点

.
.

如何判断某个key应该存储在哪个实例?

Redis会将16384(0-16383)个插槽(hash slot)分配到不同的master实例,存储时会根据key的有效部分计算插槽值,根据插槽值将其存储到相应的实例

key的插槽值计算法方式:是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值

key的有效部分有两种情况:

  • key中包含"{}",且"{}"中至少包含1个字符,"{}"中的部分就是有效部分

  • key中不包含"{}",整个key就是有效部分

.
.

分片集群搭建

1. 创建6个文件夹

2. 复制redis.conf文件到文件夹目录

3. 修改配置文件内容,将端口和目录分别修改为各实例的端口和目录如下:

# 端口号
port 7001
# 开启集群功能
cluster-enabled yes
# 指定集群配置文件名称,redis自己会创建该文件并维护其内容,不需要我们创建
cluster-config-file /home/s7001/nodes.conf
# 节点心跳超时时间
cluster-node-timeout 5000
# 持久化文件存储目录
dir /home/s7001
# 绑定地址
bind 0.0.0.0
# 守护进程,让redis后台运行
daemonize yes
# 日志,因其后台运行所以记录下日志
logfile /home/s7001/run.log
# 实列的ip
replica-announce-ip 192.168.128.128
# 取消保护模式,
protected-mode no
# 数据库数量,默认是16,我们只需要1个就够了
databases 1

4. 启动所有实例

一个命令启动所有实例,s7001 s7002等参数会替换{}/redis.conf中前面的{},实际执行的命令相当于redis-server s7002/redis.conf
printf '%s\n' s7001 s7002 s7003 s8001 s8002 s8003 | xargs -I{} -t redis-server {}/redis.conf

5. 查看启动状态

执行命令: ps ax|grep redis

6. 创建集群

注:我们使用的Redis版本是6.0.16

执行命令: redis-cli --cluster create --cluster-replicas 1 192.168.128.128:7001 192.168.128.128:7002 192.168.128.128:7003 192.168.128.128:8001 192.168.128.128:8002 192.168.128.128:8003

解读:
redis-cli --cluster: 代表集群操作命令

create: 代表创建集群

--replicas 1:指定集群中每个master字节点个数为1, 1后面的节点前面的3个是master节点,后面的3个事slave节点, slave随机分配到不同的master

7. 连接到集群

执行命令:redis-cli -c -p 7001
连接到集群之后就可以执行set,get等命令,可以看到key指存储到哪个master和key的插槽指

注:-c不能少, 端口可以是集群中任意的

8. 查看节点信息

执行命令: redis-cli -p cluster nodes

或者连接上集群后执行cluster nodes

.
.

添加和删除节点

添加节点

执行命令:redis-cli --cluster add-node 192.168.128.128:7004 192.168.128.128:7001

new_host:new_port 新节点Ip和端口

existing_host:existing_port 已经存在的集群中的节点ip和端口,标识着将新节点添加到哪个集群中

--cluster-slave 缺省表示新增节点是master,否则为slave

--cluster-master-id master节点Id表示新增的slave归属于哪个master

注:新增的master节点需要为其分配slot值

分配slot值

  1. 启动新增实例
    redis-server s7004/redis.config

  2. 将实例添加到集群
    redis-cli --cluster add-node 192.168.128.128:7004 192.168.128.128:7001

  3. 执行命令,任意一个实例即可
    redis-cli --cluster reshard 192.168.128.128:7001



插槽0-3000的数据会转移到7004实例

删除节点:

执行命令: redis-cli --cluster del-node 192.168.128.128:7001 b9fdb1cebc54dbf5afdff5e5042dfe0d6b15e881

host:prot 要删除节点的ip和端口号

node_id 要删除节点的id,通过cluster nodes命令查看

.
.

故障转移

当集群中某个master宕机后会发生什么呢?

  1. 首先该实例与其他master实例失去连接

  2. 被认定为疑似宕机

  3. 最后确定下线

  4. 自动提升一个slave为新的master

.
.

手动数据迁移

  1. 连接到slave节点,

  2. 执行命令 cluster failover
    可以看出8001变成了master,而原来的master7001变成了8001的slave

cluster failover有两个参数:

  • 缺省:默认流程如下图

  • force: 省略了offset一致性校验

  • takeover: 直接执行第5步,忽略数据一致性,忽略master状态和其他master的意见

.
.

代码实现:

  1. 在pom文件中引入redis的starter依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 在application.yml中添加配置
spring:
  redis:
    cluster:
      nodes: 
        - 192.168.128.128:7001
        - 192.168.128.128:7002
        - 192.168.128.128:7003
        - 192.168.128.128:8001
        - 192.168.128.128:8002
        - 192.168.128.128:8003

logging:
  level:
    io.lettuce.core: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
  1. 配置读写分离

配置类中添加下面Bean

   @Bean
    public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
        return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }

ReadFrom是配置redis的读取策略,是一个枚举,包括下面选择:
MASTER:从主节点读取
MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave
REPLICA:从slave读取
REPLICA_PREFERRED:优先从slave读取,所有的slave都不可用才从master读取

  1. 自行添加get/set方法测试,并查看日志

可以参考上一篇末尾添加set和get接口用来测试 https://www.cnblogs.com/big-strong-yu/p/17037543.html

posted @ 2023-01-13 15:37  big-strong-yu  阅读(481)  评论(0编辑  收藏  举报