分布式缓存

分布式缓存

redis版本6.2.4

Redis持久化

RDB (Redis Database Backup file) Redis数据备份文件

AOF (Append Only File) 追加文件

RDB持久化在四种情况下会执行:

  • 执行save命令:同步保存,会导致其他命令被阻塞
  • 执行bgsave命令:background save 异步保存,不会影响主进程
  • Redis停机时:自动执行save命令
  • 触发RDB条件时

AOF原理

  • Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件,记录的是步骤

设置RDB触发条件

  • 修改redis目录下的redis.conf文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
    save 900 1
    save 300 10
    save 60 10000

    # 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
    rdbcompression yes

    # RDB文件名称
    dbfilename dump.rdb

    # 文件保存的路径目录
    dir ./

设置AOF

  • 开启AOF

    1
    2
    3
    4
    5
    #修改配置文件
    appendonly no --> appendonly yes

    #AOF文件名
    appendfilename "appendonly.aof"
  • 设置记录频率

    1
    2
    3
    4
    5
    6
    7
    # always: 每执行一次写命令,立即记录到AOF文件
    # every sync: 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
    # no: 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘

    # appendfsync always
    appendfsync everysec
    # appendfsync no

因为是记录命令,AOF文件会比RDB文件大的多,故需要重写AOF文件来压缩体积

  • 设置重写触发条件

    1
    2
    3
    4
    # AOF文件比上次文件 增长超过多少百分比则触发重写
    auto-aof-rewrite-percentage 100
    # AOF文件体积最小多大以上才触发重写
    auto-aof-rewrite-min-size 64mb

RDB和AOF比较

RDB和AOF比较

Redis主从节点

配置主从节点

  • 准备实例和配置

    1
    2
    3
    4
    # 复制三份redis.conf配置文件到不同的文件夹下
    cp redis-4.0.0/redis.conf 7001
    cp redis-4.0.0/redis.conf 7002
    cp redis-4.0.0/redis.conf 7003

    复制配置文件

  • 修改端口和工作目录

    1
    2
    3
    sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/home\/cyx\/redis\/7001\//g' 7001/redis.conf
    sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/home\/cyx\/redis\/7002\//g' 7002/redis.conf
    sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/home\/cyx\/redis\/7003\//g' 7003/redis.conf
  • 修改每个实例的声明IP

    虚拟机本身有多个IP,为了避免将来混乱,我们需要在redis.conf文件中指定每一个实例的绑定ip信息,

    1
    2
    3
    sed -i '1a slave-announce-ip 192.168.229.128' 7001/redis.conf
    sed -i '1a slave-announce-ip 192.168.229.128' 7002/redis.conf
    sed -i '1a slave-announce-ip 192.168.229.128' 7003/redis.conf
  • 启动服务端

    1
    2
    3
    4
    5
    6
    # 分别启动三个服务端
    [root@root src]# ./redis-server ../../7001/redis.conf

    [root@root src]# ./redis-server ../../7002/redis.conf

    [root@root src]# ./redis-server ../../7003/redis.conf
  • 客户端连接

    1
    2
    # -p选择端口
    redis-cli -p 7001
  • 配置主从节点

    有临时和永久两种模式:

    • 修改配置文件(永久生效)

      • 在redis.conf中添加一行配置:slaveof <masterip> <masterport>
    • 使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 连接 7002
    redis-cli -p 7002
    # 执行slaveof
    slaveof 192.168.229.128 7001

    # 连接 7003
    redis-cli -p 7003
    # 执行slaveof
    slaveof 192.168.229.128 7001
  • 测试

    通过7001端口的主节点写入数据,在从节点也能读得到

主从同步流程

主从同步流程.png

概念

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据。

完整流程描述:

  • slave节点请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

Redis哨兵

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。

哨兵作用

Redis哨兵

哨兵的作用如下:

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

Sentinel如何判断一个redis实例是否健康

  • 每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线
  • 如果大多数sentinel都认为实例主观下线,则判定服务下线

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点配置,添加slaveof 新master

配置哨兵节点

  • 准备实例和配置

    1
    # 创建三个文件夹,存放sentinel的配置文件

  • 每个目录下创建一个sentinel.conf文件

    1
    2
    3
    4
    5
    6
    port 27001
    sentinel announce-ip 192.168.229.128
    sentinel monitor mymaster 192.168.229.128 7001 2
    sentinel down-after-milliseconds mymaster 5000
    sentinel failover-timeout mymaster 60000
    dir "/home/cyx/redis/sentinel1"

    解读:

    • port 27001:是当前sentinel实例的端口
    • sentinel monitor mymaster 192.168.150.101 7001 2:指定主节点信息
      • mymaster:主节点名称,自定义,任意写
      • 192.168.150.101 7001:主节点的ip和端口
      • 2:选举master时的quorum值
  • 修改每个配置文件的端口port XXX

  • 启动

    1
    2
    3
    4
    5
    6
    # 第1个
    ./redis-sentinel ../../sentinel1/sentinel.conf
    # 第2个
    ./redis-sentinel ../../sentinel2/sentinel.conf
    # 第3个
    ./redis-sentinel ../../sentinel3/sentinel.conf
  • 出现无法故障转移的时候,试试把从节点的slaveof 改成 slaveof 127.0.0.1 主节点端口

RedisTemplate

导入坐标

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis地址

然后在配置文件application.yml中指定redis的sentinel相关信息:

1
2
3
4
5
6
7
8
spring:
redis:
sentinel:
master: mymaster
nodes:
- 192.168.150.101:27001
- 192.168.150.101:27002
- 192.168.150.101:27003

配置读写分离

在项目的启动类中,添加一个新的bean:

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

这个bean中配置的就是读写策略,包括四种:

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave(replica)节点读取
  • REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master

Redis分片集群

概念

分片集群特点

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

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

  • master之间通过ping监测彼此健康状态

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

散列插槽

0~16383共16384个插槽会被分配到master节点上,

数据key不是与节点绑定,而是与插槽绑定,redis会根据key的有效部分计算插槽值

  • key中包含”{}”,且“{}”中至少包含1个字符,“{}”中的部分是有效部分,可以通过{}来将同一类数据存储到同一个Redis实例中
  • key中不包含“{}”,整个key都是有效部分

配置分片集群实例

准备实例和配置
  • 准备实例和配置

    IP PORT 角色
    192.168.229.128 7001 master
    192.168.229.128 7002 master
    192.168.229.128 7003 master
    192.168.229.128 8001 slave
    192.168.229.128 8002 slave
    192.168.229.128 8003 slave
  • 创建配置文件redis.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    port 6379
    # 开启集群功能
    cluster-enabled yes
    # 集群的配置文件名称,不需要我们创建,由redis自己维护
    cluster-config-file /home/cyx/redis/6379/nodes.conf
    # 节点心跳失败的超时时间
    cluster-node-timeout 5000
    # 持久化文件存放目录
    dir /home/cyx/redis/6379
    # 绑定地址
    bind 0.0.0.0
    # 让redis后台运行
    daemonize yes
    # 注册的实例ip
    replica-announce-ip 192.168.229.128
    # 保护模式
    protected-mode no
    # 数据库数量
    databases 1
    # 日志
    logfile /home/cyx/redis/6379/run.log
    1
    2
    # 执行拷贝
    echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
  • 修改配置文件,将其中的6379修改为与所在目录一致

    1
    2
    # 同时修改配置文件
    printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
  • 启动/关闭

    1
    2
    3
    4
    5
    6
    7
    8
    #同时启动所有redis
    printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf

    #查看redis进程
    ps -ef | grep redis

    #关闭所有redis进程
    printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown
创建集群
  • 集群管理以及集成到了redis-cli中

    1
    redis-cli --cluster create --cluster-replicas 1 192.168.229.128:7001 192.168.229.128:7002 192.168.229.128:7003 192.168.229.128:8001 192.168.229.128:8002 192.168.229.128:8003

    命令说明:

    • redis-cli --cluster或者./redis-trib.rb:代表集群操作命令
    • create:代表是创建集群
    • --replicas 1或者--cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master
  • 查看集群状态

    1
    redis-cli -p 7001 cluster nodes
使用
  • 添加数据

    1
    2
    3
    # 打开客户端,-c代表集群操作
    redis-cli -c -p 7001
    # 之后就可以CRUD了,redis根据key算出的hash值存到对应插槽中
操作集群
  • 查看帮助文档

    1
    redis-cli --cluster help

  • 添加节点到集群(add-node)

    1
    2
    # 添加的节点是没有插槽的
    redis-cli --cluster add-node 要添加的节点ip:端口 一个maser节点的ip:端口
  • 转移插槽(reshard)

    1
    2
    redis-cli --cluster reshard 要分配插槽的Redis实例的ip:端口
    # 之后会让输入要分配的插槽数量、从哪个节点移动插槽、跟着提示来就行

故障转移

自动故障转移

出现宕机的节点时,自动提升一个slave为新的master

宕机的节点重新上线时,会变成slave节点

手动故障转移

进入节点的客户端,执行cluster failover命令,这个节点就会称为master节点

RedisTemplate访问集群

和哨兵模式差不多

  • 引入redis的starter依赖
  • 配置分片集群地址 (就这步有差异)
  • 配置读写分离
1
2
3
4
5
6
7
8
9
10
spring:
redis:
cluster:
nodes:
- 192.168.229.128:7001
- 192.168.229.128:7002
- 192.168.229.128:7003
- 192.168.229.128:8001
- 192.168.229.128:8002
- 192.168.229.128:8003

分布式缓存
http://xwww12.github.io/2022/09/25/微服务/分布式缓存/
作者
xw
发布于
2022年9月25日
许可协议