目录

Life in Flow

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

X

Redis6

安装

# 安装gcc
yum install -y gcc-c++ autoconf automake

# centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版才能编译
gcc -v

# 升级新版gcc,配置永久生效
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash  
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile 

# 安装redis
[root@localhost redis6]# mkdir -p /usr/local/redis
[root@localhost software]# tar -zxvf redis-6.2.1.tar.gz
[root@localhost software]# mv redis-6.2.1 redis6
[root@localhost software]# cd redis6
[root@localhost redis6]# make
[root@localhost redis6]# make PREFIX=/usr/local/redis install

# 启动redis
[root@localhost redis6]# /usr/local/redis/bin/redis-server
[root@localhost redis6]# /usr/local/redis/bin/redis-server /software/redis6/redis.conf  #指定配置文件路径

# 连接redis
[root@localhost ~]# /usr/local/redis/bin/redis-cli

容器化部署Redis6

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

常见核心配置

创建目录

日志 /usr/local/redis/log
数据 /usr/local/redis/data
配置文件 /usr/local/redis/conf

[root@localhost redis6]# mkdir -p /usr/local/redis/log
[root@localhost redis6]# mkdir -p  /usr/local/redis/data
[root@localhost redis6]# mkdir -p  /usr/local/redis/conf

核心配置

[root@localhost redis6]# vim /usr/local/redis/conf/redis.conf
# 任何ip可以访问
bind 0.0.0.0

# 守护进程
daemonize yes

# 密码
requirepass 123456

# 日志文件
logfile "/usr/local/redis/log/redis.log"

# 持久化文件名称
dbfilename xdclass.rdb

# 持久化文件存储路径
dir /usr/local/redis/data

# 持久化策略, 10秒内有个1个key改动,执行快照
save 10 1

启动

# 用指定的配置文件启动redis
[root@localhost redis6]# /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf

# 查看监听端口
[root@localhost redis6]# lsof -i:6379
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 13535 root    6u  IPv4 395737      0t0  TCP *:6379 (LISTEN)
redis-ser 13535 root    7u  IPv4 395785      0t0  TCP localhost:6379->localhost:38014 (ESTABLISHED)
redis-cli 13549 root    3u  IPv4 396886      0t0  TCP localhost:38014->localhost:6379 (ESTABLISHED)

# cli连接
[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
  • 产生快照的情况
    # save
    会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止
    
    # bgsave
    fork创建子进程,RDB持久化过程由子进程负责,会在后台异步进行快照操作,快照同时还可以响应客户端请求
    
    # 自动化
    配置文件来完成,配置触发 Redis的 RDB 持久化条件
    比如 "save m n"。表示m秒内数据集存在n次修改时,自动触发bgsave
    
    # 主从架构
    从服务器同步数据的时候,会发送sync执行同步操作,master主服务器就会执行bgsave
    

优点:

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

缺点:

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

核心配置

  • dir 持久化文件的路径
  • dbfilename 文件名
#任何ip可以访问
bind 0.0.0.0

#守护进程
daemonize yes

#密码
requirepass 123456

#日志文件
logfile "/usr/local/redis/log/redis.log"

#持久化文件名称
dbfilename xdclass.rdb

#持久化文件存储路径
dir /usr/local/redis/data

#持久化策略, 10秒内有个1个key改动,执行快照
save 10 1

######之前配置######

#导出rdb数据库文件压缩字符串和对象,默认是yes,会浪费CPU但是节省空间
rdbcompression yes
# 导入时是否检查
rdbchecksum yes

重启

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

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
    • 不主从同步,由操作系统自动调度刷磁盘,性能是最好的,但是最不安全
bind 0.0.0.0

daemonize yes

requirepass 123456Xdclass

logfile "/usr/local/redis/log/redis.log"

dbfilename xdclass.rdb

dir /usr/local/redis/data

#save 10 2
#save 100 5
save ""
rdbcompression yes
#对rdb数据进行校验,耗费CPU资源,默认为yes
rdbchecksum yes

appendonly yes
appendfilename "appendonly.aof"
appendfsync 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)的比值

常用配置

# 是否开启aof
appendonly yes

# 文件名称
appendfilename "appendonly.aof"

# 同步方式
appendfsync everysec

# aof重写期间是否同步
no-appendfsync-on-rewrite no

# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 加载aof时如果有错如何处理
# yes表示如果aof尾部文件出问题,写log记录并继续执行。no表示提示写入等待修复后写入

aof-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从架构环境准备

配置

mkdir -p /data/redis/master/data 
mkdir -p /data/redis/slave1/data 
mkdir -p /data/redis/slave2/data

#从节点开启只读模式(默认)
replica-read-only yes
#从节点访问主节点的密码,和requirepass一样
masterauth 123456
#哪个主节点进行复制
replicaof 8.129.113.233 6379

创建主配置文件redis.conf

bind 0.0.0.0
port 6379
daemonize yes

requirepass "123456"

logfile "/usr/local/redis/log/redis1.log"
dbfilename "xdclass1.rdb"
dir "/usr/local/redis/data"
appendonly yes
appendfilename "appendonly1.aof"
masterauth "123456"

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

bind 0.0.0.0
port 6380
daemonize yes
requirepass "123456"
logfile "/usr/local/redis/log/redis2.log"
dbfilename "xdclass2.rdb"
dir "/usr/local/redis/data"
appendonly yes
appendfilename "appendonly2.aof"
replicaof 8.129.113.233 6379
masterauth "123456"

创建从配置文件redis.conf

bind 0.0.0.0
port 6381
daemonize yes
requirepass "123456"
logfile "/usr/local/redis/log/redis3.log"
dbfilename "xdclass3.rdb"
dir "/usr/local/redis/data"
appendonly yes
appendfilename "appendonly3.aof"
replicaof 8.129.113.233 6379
masterauth "123456"

启动

#启动主
./redis-server /data/redis/master/data/redis.conf


#启动从
./redis-server /data/redis/slave1/data/redis.conf

#启动从
./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】记得开放
#不限制ip
bind 0.0.0.0

# 让sentinel服务后台运行
daemonize yes

# 配置监听的主服务器,mymaster代表服务器的名称,自定义,172.18.172.109 代表监控的主服务器,6379代表端口,
#2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor mymaster 172.18.172.109 6379 2

# sentinel auth-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
sentinel auth-pass mymaster 123456

#超过5秒master还没有连接上,则认为master已经停止
sentinel down-after-milliseconds mymaster 5000

#如果该时间内没完成failover操作,则认为本次failover失败
sentinel failover-timeout mymaster 30000
  • 在目录下创建3个文件sentinel-1.conf、sentinel-2.conf、sentinel-3.conf
port 26379
bind 0.0.0.0
daemonize yes
pidfile "/var/run/redis-sentinel-1.pid"
logfile "/var/log/redis/sentinel_26379.log"
dir "/tmp"
sentinel monitor mymaster 8.129.113.233 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 30000
port 26380
bind 0.0.0.0
daemonize yes
pidfile "/var/run/redis-sentinel-2.pid"
logfile "/var/log/redis/sentinel_26380.log"
dir "/tmp"
sentinel monitor mymaster 8.129.113.233 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 30000
port 26381
bind 0.0.0.0
daemonize yes
pidfile "/var/run/redis-sentinel-3.pid"
logfile "/var/log/redis/sentinel_26381.log"
dir "/tmp"
sentinel monitor mymaster 8.129.113.233 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 30000
  • 记得创建 /var/log/redis 文件夹
  • 启动哨兵集群
./redis-server /usr/local/redis/conf/sentinel-1.conf --sentinel

./redis-server /usr/local/redis/conf/sentinel-2.conf --sentinel

./redis-server /usr/local/redis/conf/sentinel-3.conf --sentinel
  • 优点
    • 主从可以自动切换,可用性更高
  • 缺点
    • 主从切换会丢失短暂数据
    • 主节点的写能力和存储能力受限

作者:Soulboy