目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

Redis6

安装

 1# 安装gcc
 2yum install -y gcc-c++ autoconf automake
 3
 4# centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版才能编译
 5gcc -v
 6
 7# 升级新版gcc,配置永久生效
 8yum -y install centos-release-scl
 9yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
10scl enable devtoolset-9 bash  
11echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile 
12
13# 安装redis
14[root@localhost redis6]# mkdir -p /usr/local/redis
15[root@localhost software]# tar -zxvf redis-6.2.1.tar.gz
16[root@localhost software]# mv redis-6.2.1 redis6
17[root@localhost software]# cd redis6
18[root@localhost redis6]# make
19[root@localhost redis6]# make PREFIX=/usr/local/redis install
20
21# 启动redis
22[root@localhost redis6]# /usr/local/redis/bin/redis-server
23[root@localhost redis6]# /usr/local/redis/bin/redis-server /software/redis6/redis.conf  #指定配置文件路径
24
25# 连接redis
26[root@localhost ~]# /usr/local/redis/bin/redis-cli
27

容器化部署 Redis6

1docker run -itd --name xdclass-redis -p 6379:6379 redis --requirepass 123456
2-i 以交互模式运行容器,通常与 
3-t 同时使用;
4-d 后台运行容器,并返回容器ID;

常见核心配置

创建目录

1日志 /usr/local/redis/log
2数据 /usr/local/redis/data
3配置文件 /usr/local/redis/conf
4
5[root@localhost redis6]# mkdir -p /usr/local/redis/log
6[root@localhost redis6]# mkdir -p  /usr/local/redis/data
7[root@localhost redis6]# mkdir -p  /usr/local/redis/conf

核心配置

 1[root@localhost redis6]# vim /usr/local/redis/conf/redis.conf
 2# 任何ip可以访问
 3bind 0.0.0.0
 4
 5# 守护进程
 6daemonize yes
 7
 8# 密码
 9requirepass 123456
10
11# 日志文件
12logfile "/usr/local/redis/log/redis.log"
13
14# 持久化文件名称
15dbfilename xdclass.rdb
16
17# 持久化文件存储路径
18dir /usr/local/redis/data
19
20# 持久化策略, 10秒内有个1个key改动,执行快照
21save 10 1

启动

 1# 用指定的配置文件启动redis
 2[root@localhost redis6]# /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
 3
 4# 查看监听端口
 5[root@localhost redis6]# lsof -i:6379
 6COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
 7redis-ser 13535 root    6u  IPv4 395737      0t0  TCP *:6379 (LISTEN)
 8redis-ser 13535 root    7u  IPv4 395785      0t0  TCP localhost:6379->localhost:38014 (ESTABLISHED)
 9redis-cli 13549 root    3u  IPv4 396886      0t0  TCP localhost:38014->localhost:6379 (ESTABLISHED)
10
11# cli连接
12[root@localhost ~]# /usr/local/redis/bin/redis-cli -a 123456

可视化工具

redisdestop_v2020.5.0

持久化

Redis 是一个内存数据库,如果没有配置持久化,Redis 重启后数据就全丢失

因此开启 Redis 的持久化功能,将数据保存到磁盘上,当 Redis 重启后,可以从磁盘中恢复数据。

两种持久化方式:

  • RDB (Redis DataBase)
  • AOF (append only file)

RDB 持久化介绍

  • 在指定的时间间隔内将内存中的数据集快照写入磁盘
  • 默认的文件名为 dump.rdb
  • 产生快照的情况
     1# save
     2会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止
     3
     4# bgsave
     5fork创建子进程,RDB持久化过程由子进程负责,会在后台异步进行快照操作,快照同时还可以响应客户端请求
     6
     7# 自动化
     8配置文件来完成,配置触发 Redis的 RDB 持久化条件
     9比如 "save m n"。表示m秒内数据集存在n次修改时,自动触发bgsave
    10
    11# 主从架构
    12从服务器同步数据的时候,会发送sync执行同步操作,master主服务器就会执行bgsave
    

优点:

  • RDB 文件紧凑,全量备份,适合用于进行备份和灾难恢复
  • 在恢复大数据集时的速度比 AOF 的恢复速度要快
  • 生成的是一个紧凑压缩的二进制文件

缺点:

  • 每次快照是一次全量备份,fork 子进程进行后台操作,子进程存在开销
  • 在快照持久化期间修改的数据不会被保存,可能丢失数据

核心配置

  • dir 持久化文件的路径
  • dbfilename 文件名
 1#任何ip可以访问
 2bind 0.0.0.0
 3
 4#守护进程
 5daemonize yes
 6
 7#密码
 8requirepass 123456
 9
10#日志文件
11logfile "/usr/local/redis/log/redis.log"
12
13#持久化文件名称
14dbfilename xdclass.rdb
15
16#持久化文件存储路径
17dir /usr/local/redis/data
18
19#持久化策略, 10秒内有个1个key改动,执行快照
20save 10 1
21
22######之前配置######
23
24#导出rdb数据库文件压缩字符串和对象,默认是yes,会浪费CPU但是节省空间
25rdbcompression yes
26# 导入时是否检查
27rdbchecksum yes

重启

1[root@localhost ~]# lsof -i:6379
2COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
3redis-ser 13535 root    6u  IPv4 395737      0t0  TCP *:6379 (LISTEN)
4[root@localhost ~]# kill 13535
5[root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
6[root@localhost ~]# lsof -i:6379
7COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
8redis-ser 13622 root    6u  IPv4 397547      0t0  TCP *:6379 (LISTEN)
9

AOF 持久化介绍

  • append only file,追加文件的方式,文件容易被人读懂
  • 以独立日志的方式记录每次写命令, 重启时再重新执行 AOF 文件中的命令达到恢复数据的目的
  • 写入过程宕机,也不影响之前的数据,可以通过 redis-check-aof 检查修复问题

配置实战

  • appendonly yes,默认不开启
  • AOF 文件名 通过 appendfilename 配置设置,默认文件名是 appendonly.aof
  • 存储路径同 RDB 持久化方式一致,使用 dir 配置

核心原理

  • Redis 每次写入命令会追加到 aof_buf(缓冲区)
  • AOF 缓冲区根据对应的策略向硬盘做同步操作
  • 高频 AOF 会带来影响,特别是每次刷盘

提供了 3 种同步方式,在性能和安全性方面做出平衡

  • appendfsync always
    • 每次有数据修改发生时都会写入 AOF 文件,消耗性能多
  • appendfsync everysec
    • 每秒钟同步一次,该策略为 AOF 的缺省策略。
  • appendfsync no
    • 不主从同步,由操作系统自动调度刷磁盘,性能是最好的,但是最不安全
 1bind 0.0.0.0
 2
 3daemonize yes
 4
 5requirepass 123456Xdclass
 6
 7logfile "/usr/local/redis/log/redis.log"
 8
 9dbfilename xdclass.rdb
10
11dir /usr/local/redis/data
12
13#save 10 2
14#save 100 5
15save ""
16rdbcompression yes
17#对rdb数据进行校验,耗费CPU资源,默认为yes
18rdbchecksum yes
19
20appendonly yes
21appendfilename "appendonly.aof"
22appendfsync everysec

rewrite 重写介绍

  • AOF 文件越来越大,需要定期对 AOF 文件进行重写达到压缩
  • 旧的 AOF 文件含有无效命令会被忽略,保留最新的数据命令
  • 多条写命令可以合并为一个
  • AOF 重写降低了文件占用空间
  • 更小的 AOF 文件可以更快地被 Redis 加载

重写触发配置

  • 手动触发
    • 直接调用 bgrewriteaof 命令
  • 自动触发
    • auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数
    • auto-aof-rewrite-min-size
      • 表示运行 AOF 重写时文件最小体积,默认 为 64MB。
    • auto-aof-rewrite-percentage
      • 代表当前 AOF 文件空间和上一次重写后 AOF 文件空间(aof_base_size)的比值

常用配置

 1# 是否开启aof
 2appendonly yes
 3
 4# 文件名称
 5appendfilename "appendonly.aof"
 6
 7# 同步方式
 8appendfsync everysec
 9
10# aof重写期间是否同步
11no-appendfsync-on-rewrite no
12
13# 重写触发配置
14auto-aof-rewrite-percentage 100
15auto-aof-rewrite-min-size 64mb
16
17# 加载aof时如果有错如何处理
18# yes表示如果aof尾部文件出问题,写log记录并继续执行。no表示提示写入等待修复后写入
19
20aof-load-truncated yes 

AOF 和 RDB 的选择问题

Redis 提供了不同的持久性选项:

  • RDB 持久化以指定的时间间隔执行数据集的时间点快照。
  • AOF 持久化记录服务器接收的每个写入操作,将在服务器启动时再次读取,重建原始数据集。使用与 Redis 协议本身相同的格式以仅追加方式记录命令,当文件太大时,Redis 能够重写

RDB 的优缺点

  • 优点:
    • RDB 最大限度地提高了 Redis 的性能,父进程不需要参与磁盘 I/O
    • RDB 文件紧凑,全量备份,适合用于进行备份和灾难恢复
    • 在恢复大数据集时的速度比 AOF 的恢复速度要快
    • 生成的是一个紧凑压缩的二进制文件
  • 缺点:
    • 如果您需要在 Redis 停止工作时(例如断电后)将数据丢失的可能性降至最低,则 RDB 并不好
    • RDB 经常需要 fork 才能使用子进程持久存储在磁盘上。如果数据集很大,Fork 可能会非常耗时

AOF 的优缺点

  • 优点:
    • 数据更加安全
    • 当 Redis AOF 文件太大时,Redis 能够在后台自动重写 AOF
    • AOF 以易于理解和解析的格式,一个接一个地包含所有操作的日志
  • 缺点:
    • AOF 文件通常比同一数据集的等效 RDB 文件大
    • 根据确切的 fsync 策略,恢复的时候 AOF 可能比 RDB 慢

在线上我们到底该怎么做?

  • RDB 持久化与 AOF 持久化一起使用
  • 如果 Redis 中的数据并不是特别敏感或者可以通过其它方式重写生成数据
  • 集群中可以关闭 AOF 持久化,靠集群的备份方式保证可用性
  • 自己制定策略定期检查 Redis 的情况,然后可以手动触发备份、重写数据;
  • 采用集群和主从同步

Redis4.0 后开始的 rewrite 支持混合模式

  • 就是 rdb 和 aof 一起用
  • 直接将 rdb 持久化的方式来操作将二进制内容覆盖到 aof 文件中,rdb 是二进制,所以很小
  • 有写入的话还是继续 append 追加到文件原始命令,等下次文件过大的时候再次 rewrite
  • 默认是开启状态
  • 好处
    • 混合持久化结合了 RDB 持久化 和 AOF 持久化的优点,采取了 rdb 的文件小易于灾难恢复
    • 同时结合 AOF,增量的数据以 AOF 方式保存了,数据更少的丢失
  • 坏处
    • 前部分是 RDB 格式,是二进制,所以阅读性较差
  • 数据恢复
    • 先看是否存在 aof 文件,若存在则先按照 aof 文件恢复,aof 比 rdb 全,且 aof 文件也 rewrite 成 rdb 二进制格式
    • 若 aof 不存在,则才会查找 rdb 是否存在

主从复制

1 主 2 从架构环境准备

配置

 1mkdir -p /data/redis/master/data 
 2mkdir -p /data/redis/slave1/data 
 3mkdir -p /data/redis/slave2/data
 4
 5#从节点开启只读模式(默认)
 6replica-read-only yes
 7#从节点访问主节点的密码,和requirepass一样
 8masterauth 123456
 9#哪个主节点进行复制
10replicaof 8.129.113.233 6379

创建主配置文件 redis.conf

 1bind 0.0.0.0
 2port 6379
 3daemonize yes
 4
 5requirepass "123456"
 6
 7logfile "/usr/local/redis/log/redis1.log"
 8dbfilename "xdclass1.rdb"
 9dir "/usr/local/redis/data"
10appendonly yes
11appendfilename "appendonly1.aof"
12masterauth "123456"

创建两个从配置文件 redis.conf

 1bind 0.0.0.0
 2port 6380
 3daemonize yes
 4requirepass "123456"
 5logfile "/usr/local/redis/log/redis2.log"
 6dbfilename "xdclass2.rdb"
 7dir "/usr/local/redis/data"
 8appendonly yes
 9appendfilename "appendonly2.aof"
10replicaof 8.129.113.233 6379
11masterauth "123456"

创建从配置文件 redis.conf

 1bind 0.0.0.0
 2port 6381
 3daemonize yes
 4requirepass "123456"
 5logfile "/usr/local/redis/log/redis3.log"
 6dbfilename "xdclass3.rdb"
 7dir "/usr/local/redis/data"
 8appendonly yes
 9appendfilename "appendonly3.aof"
10replicaof 8.129.113.233 6379
11masterauth "123456"

启动

1#启动主
2./redis-server /data/redis/master/data/redis.conf
3
4
5#启动从
6./redis-server /data/redis/slave1/data/redis.conf
7
8#启动从
9./redis-server /data/redis/slave2/data/redis.conf

info replication 查看状态

主从复制-读写分离原理解析

全量复制

  • master 服务器会开启一个后台进程用于将 Redis 中的数据生成一个 rdb 文件
  • 主服务器会缓存所有接收到的来自客户端的写命令,当后台保存进程 处理完毕后,会将该 rdb 文件传递给 slave 服务器
  • slave 服务器会将 rdb 文件保存在磁盘并通过读取该文件将数据加载到内存
  • 在此之后 master 服务器会将在此期间缓存的命令通过 Redis 传输协议发送给 slave 服务器
  • 然后 slave 服务器将这些命令依次作用于自己本地的数据集上最终达到数据的一致性

增量复制

  • Slave 初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程
  • 服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令

特点

  • 主从复制对于 主/从 Redis 服务器来说是非阻塞的,所以同步期间都可以正常处理外界请求
  • 一个主 Redis 可以含有多个从 Redis,每个从 Redis 可以接收来自其他从 Redis 服务器的连接
  • 从节点不会让 key 过期,而是主节点的 key 过期删除后,成为 del 命令传输到从节点进行删除
    • 从节点开启 sync 看日志

加速复制

  • 完全重新同步需要在磁盘上创建一个 RDB 文件,然后加载这个文件以便为从服务器发送数据
  • 在比较低速的磁盘,这种操作会给主服务器带来较大的压力
  • 新版支持无磁盘的复制,子进程直接将 RDB 通过网络发送给从服务器,不使用磁盘作为中间存储
  • repl-diskless-sync yes (默认是 no)

主从断开重连

  • 如果遭遇连接断开,重新连接之后可以从中断处继续进行复制,而不必重新同步
  • 2.8 版本后 部分重新同步这个新特性内部使用 PSYNC 命令,旧的实现中使用 SYNC 命令

Sentinel 哨兵监控

  • 背景

  • 前面搭建了主从,当主服务器宕机后,需要手动把一台从服务器切换为主服务器,人工干预费事费力,还会造成一段时间内服务不可用

  • 哨兵模式介绍

    • Redis 提供了哨兵的命令,是一个独立的进程
    • 原理 哨兵通过发送命令给多个节点,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例的运行情况
    • 当哨兵监测到 master 宕机,会自动将 slave 切换成 master,通过通知其他的从服务器,修改配置文件切换主机
  • Sentinel 三大工作任务

    • 监控(Monitoring)
      • Sentinel 会不断地检查你的主服务器和从服务器是否运作正常
    • 提醒(Notification)
      • 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知
    • 自动故障迁移(Automatic failover)
      • 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器
      • 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器
  • 问题

    • 一个哨兵进程对 Redis 服务器进行监控,可能会出现问题
    • 一般是使用多个哨兵进行监控,各个哨兵之间还会进行监控,形成多哨兵模式
  • 多哨兵模式下线名称介绍

    • 主观下线(Subjectively Down, 简称 SDOWN)
      • 是单个 Sentinel 实例对服务器做出的下线判断,比如网络问题接收不到通知等
      • 一个服务器没有在 down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线
    • 客观下线(Objectively Down, 简称 ODOWN)
      • 指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断
      • 一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线
      • 客观下线条件只适用于主服务器
    • 仲裁 qurum
      • Sentinel 在给定的时间范围内, 从其他 Sentinel 那里接收到了【足够数量】的主服务器下线报告, 那么 Sentinel 就会将主服务器的状态从主观下线改变为客观下线
      • 这个【足够数量】就是配置文件里面的值,一般是 Sentinel 个数的一半加 1,比如 3 个 Sentinel 则就设置为 2
      • down-after-milliseconds 是一个哨兵在超过规定时间依旧没有得到响应后,会自己认为主机不可用
      • 当拥有认为主观下线的哨兵达到 sentinel monitor 所配置的数量时,就会发起一次投票,进行 failover

Sentinel 哨兵搭建环境准备

  • 核心流程
    • 每秒 ping,超过时间不响应 则认为主观下线
    • 满足多个,则认为是客观下线
    • 投票选择主节点
    • 如果没有足够的节点同意 master 下线,则状态会被移除
  • 环境准备
    • 配置 3 个哨兵,每个哨兵的配置都是一样的
    • 启动顺序 先启动主再启动从,最后启动 3 个哨兵
    • 哨兵端口是 【26379】记得开放
 1#不限制ip
 2bind 0.0.0.0
 3
 4# 让sentinel服务后台运行
 5daemonize yes
 6
 7# 配置监听的主服务器,mymaster代表服务器的名称,自定义,172.18.172.109 代表监控的主服务器,6379代表端口,
 8#2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
 9sentinel monitor mymaster 172.18.172.109 6379 2
10
11# sentinel auth-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
12sentinel auth-pass mymaster 123456
13
14#超过5秒master还没有连接上,则认为master已经停止
15sentinel down-after-milliseconds mymaster 5000
16
17#如果该时间内没完成failover操作,则认为本次failover失败
18sentinel failover-timeout mymaster 30000
  • 在目录下创建 3 个文件 sentinel-1.conf、sentinel-2.conf、sentinel-3.conf
 1port 26379
 2bind 0.0.0.0
 3daemonize yes
 4pidfile "/var/run/redis-sentinel-1.pid"
 5logfile "/var/log/redis/sentinel_26379.log"
 6dir "/tmp"
 7sentinel monitor mymaster 8.129.113.233 6379 2
 8sentinel down-after-milliseconds mymaster 5000
 9sentinel auth-pass mymaster 123456
10sentinel failover-timeout mymaster 30000
 1port 26380
 2bind 0.0.0.0
 3daemonize yes
 4pidfile "/var/run/redis-sentinel-2.pid"
 5logfile "/var/log/redis/sentinel_26380.log"
 6dir "/tmp"
 7sentinel monitor mymaster 8.129.113.233 6379 2
 8sentinel down-after-milliseconds mymaster 5000
 9sentinel auth-pass mymaster 123456
10sentinel failover-timeout mymaster 30000
 1port 26381
 2bind 0.0.0.0
 3daemonize yes
 4pidfile "/var/run/redis-sentinel-3.pid"
 5logfile "/var/log/redis/sentinel_26381.log"
 6dir "/tmp"
 7sentinel monitor mymaster 8.129.113.233 6379 2
 8sentinel down-after-milliseconds mymaster 5000
 9sentinel auth-pass mymaster 123456
10sentinel failover-timeout mymaster 30000
  • 记得创建 /var/log/redis 文件夹
  • 启动哨兵集群
1./redis-server /usr/local/redis/conf/sentinel-1.conf --sentinel
2
3./redis-server /usr/local/redis/conf/sentinel-2.conf --sentinel
4
5./redis-server /usr/local/redis/conf/sentinel-3.conf --sentinel
  • 优点
    • 主从可以自动切换,可用性更高
  • 缺点
    • 主从切换会丢失短暂数据
    • 主节点的写能力和存储能力受限

作者:Soulboy