centos7 下 redis-sentinel 主从集群搭建



宏观上Sentinel功能的完整列表

  • 监控。Sentinel会不断检查您的主实例和副本实例是否按预期工作。
  • 通知。Sentinel可以通过API通知系统管理员或其他计算机程序,其中一个受监视的Redis实例出了问题。
  • 自动故障转移。如果主服务器未按预期工作,则Sentinel可以启动故障转移过程,在该过程中将副本升级为主服务器,将其他附加副本重新配置为使用新的主服务器,并通知使用Redis服务器的应用程序要使用的新地址。连接时。
  • 配置提供程序。Sentinel充当客户端服务发现的授权来源:客户端连接到Sentinels,以询问负责给定服务的当前Redis主服务器的地址。如果发生故障转移,Sentinels将报告新地址。

Sentinel的分布式性质

Redis Sentinel是一个分布式系统:

Sentinel本身设计为在有多个Sentinel进程协同合作的配置中运行。具有多个Sentinel进程进行协作的优点如下:

  1. 当多个哨兵就给定的主机不再可用这一事实达成共识时,将执行故障检测。这降低了误报的可能性。
  2. 即使不是所有的Sentinel进程都在工作,Sentinel仍能正常工作,从而使系统能够应对故障。毕竟,拥有故障转移系统本身就是一个单点故障

部署前有关Sentinel的基本知识

  1. 一个健壮的部署至少需要三个Sentinel实例
  2. 应将三个Sentinel实例放置到被认为以独立方式发生故障的计算机或虚拟机中。因此,例如在不同的可用区域上执行的不同物理服务器或虚拟机。
  3. Sentinel + Redis分布式系统不保证在故障期间保留已确认的写入,因为Redis使用异步复制。但是,有一些部署Sentinel的方法使窗口丢失写入仅限于某些时刻,而还有其他一些不太安全的方法来部署它。
  4. 您的客户需要Sentinel支持。流行的客户端库具有Sentinel支持,但不是全部。
  5. 如果您不在开发环境中不时进行测试,则没有安全的HA设置,如果可以,则在生产环境中甚至可以更好地进行测试。您可能有一个错误的配置,只有在为时已晚时(主服务器停止工作的凌晨3点),该错误才会变得明显。
  6. Sentinel,Docker或其他形式的网络地址转换或端口映射应格外小心:Docker执行端口重新映射,破坏Sentinel对其他Sentinel进程的自动发现以及主副本的列表。有关更多信息,请参阅本文档后面有关Sentinel和Docker的部分。

1、安装redis(3台同步)

官网文档:https://redis.io/topics/sentinel

Github:https://github.com/antirez/redis/releases

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 1、安装gcc依赖
yum install -y gcc
yum install -y wget
# 2、下载并解压安装包
cd /data/soft/new/
wget https://github.com/antirez/redis/archive/3.2.13.tar.gz -O redis-3.2.13.tar.gz
tar -zxf redis-3.2.13.tar.gz
# 3、cd切换到redis解压目录下,执行编译
cd redis-3.2.13
make MALLOC=libc
# 4、安装并指定安装目录
make install PREFIX=/usr/local/redis
cp redis.conf /usr/local/redis/bin/
# 5、后台启动
/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis.conf
# 6、开机启动
cat >> /etc/systemd/system/redis.service << EOF
[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF

# 7、创建软连接
ln -s /usr/local/redis/bin/redis-cli /usr/bin/redis

systemctl daemon-reload
systemctl status redis.service #查看服务当前状态
systemctl enable redis.service #设置开机自启动
systemctl disable redis.service #停止开机自启动
systemctl start redis.service #启动redis服务
systemctl stop redis.service #停止redis服务
systemctl restart redis.service #重新启动服务

make test 报错解决方案:

1
2
3
4
5
6
7
# You need tcl 8.5 or newer in order to run the Redis test.
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
sudo tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
sudo ./configure
sudo make
sudo make install

2、配置redis.conf

vi /usr/local/redis/bin/redis.conf

scp root@dn1:/usr/local/redis/bin/redis.conf /usr/local/redis/bin/redis.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 使用 yes 启用守护进程
daemonize yes

# 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id
databases 16
pidfile /var/run/redis.pid
port 6379
# 绑定的主机地址
bind 127.0.0.1

# 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH <password> 命令提供密码,默认关闭
requirepass 123456
# 当客户端闲置多长时间后关闭连接,如果指定为 0,表示关闭该功能
timeout 300
# 设置同一时间最大客户端连接数,默认无限制,Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息
maxclients 128
# 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes

# 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区
# maxmemory <bytes>

# 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
# 指定是否激活重置哈希,默认为开启(后面在介绍 Redis 的哈希算法时具体介绍)
activerehashing yes
# 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
# include /path/to/local.conf

# 指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默认为 notice
loglevel notice
# 日志记录方式,默认为标准输出,如果配置 Redis 为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给 /dev/null
# logfile stdout
logfile /root/redis.log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# rdb: 指定在多长时间内,有多少次更新操作,就将数据同步到rdb数据文件,可以多个条件配合
# save <seconds> <changes>
#当有一条Keys数据被改变时,900秒刷新到Disk一次
save 900 1
# 当有10条Keys数据被改变时,300秒刷新到Disk一次
save 300 10
# 当有10000条Keys数据被改变时,60秒刷新到Disk一次
save 60 10000
# rdb: 文件是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
# rdb: 指定本地RDB数据库文件名,默认值为 dump.rdb
dbfilename dump.rdb
# rdb: 指定本地数据库存放目录
dir ./

# aof: 如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis 本身同步数据文件是按上面 save 条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为 no
appendonly no
# aof: 指定更新日志文件名,默认为 appendonly.aof
appendfilename "appendonly.aof"
# aof: 指定更新日志条件,共有 3 个可选值:
# no:表示等操作系统进行数据缓存同步到磁盘(快)
# always:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折中,默认值)
appendfsync everysec
1
2
3
4
5
6
7
8
9
10
11
12
# 指定是否启用虚拟内存机制,默认值为 no,简单的介绍一下,VM 机制将数据分页存放,由 Redis 将访问量较少的页即冷数据 swap 到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析 Redis 的 VM 机制)
vm-enabled no
# 虚拟内存文件路径,默认值为 /tmp/redis.swap,不可多个 Redis 实例共享
vm-swap-file /tmp/redis.swap
# 将所有大于 vm-max-memory 的数据存入虚拟内存,无论 vm-max-memory 设置多小,所有索引数据都是内存存储的(Redis 的索引数据 就是 keys),也就是说,当 vm-max-memory 设置为 0 的时候,其实是所有 value 都存在于磁盘。默认值为 0
vm-max-memory 0
# Redis swap 文件分成了很多的 page,一个对象可以保存在多个 page 上面,但一个 page 上不能被多个对象共享,vm-page-size 是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page 大小最好设置为 32 或者 64bytes;如果存储很大大对象,则可以使用更大的 page,如果不确定,就使用默认值
vm-page-size 32
# 设置 swap 文件中的 page 数量,由于页表(一种表示页面空闲或使用的 bitmap)是在放在内存中的,,在磁盘上每 8 个 pages 将消耗 1byte 的内存
vm-pages 134217728
# 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4
1
2
3
4
# 设置当本机为 slav 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步
slaveof <masterip> <masterport>
# 当 master 服务设置了密码保护时,slav 服务连接 master 的密码
masterauth <master-password>

3、配置redis-sentinel集群


参考链接:https://www.jianshu.com/p/06ab9daf921d

配置3个哨兵 和 2个redis集群

服务类型 是否是主服务器 IP地址 端口
Redis dn1 6379
Redis 否(dn1的slave) dn2 6379
Redis dn3 6379
Sentinel - dn1 26379
Sentinel - dn2 26379
Sentinel - dn3 26379

3.1、修改 redis.conf

vi /usr/local/redis/bin/redis.conf

scp root@dn1:/usr/local/redis/bin/redis.conf /usr/local/redis/bin/redis.conf

dn1 和 dn3 配置

1
2
3
4
5
6
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass 123456
# 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456

dn2 配置

1
2
3
4
5
6
7
8
9
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass 123456
# 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456

# 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
slaveof dn1 6379

3.2、修改sentinel.conf

1
2
3
4
5
6
7
8
9
10
\cp /data/soft/new/redis-3.2.13/sentinel.conf /usr/local/redis/bin/
vi /usr/local/redis/bin/sentinel.conf
# vi编辑器如何把开头是#的行全都删掉
:g/^#/d
# 删除空行
:g/^$/d
# 删除空行以及只有空格的行
:g/^\s*$/d
# 删除以 # 开头或 空格# 或 tab#开头的行
:g/^\s*#/d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
port 26379
daemonize yes
dir "/root/"
logfile "redis-sentinel.log"

# 禁止保护模式
protected-mode no
# 配置监听的主服务器,这里sentinel monitor代表监控,master-a代表服务器的名称,可以自定义,dn1 代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor master-a dn1 6379 2
# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass master-a 123456

sentinel monitor master-b dn3 6379 2
sentinel auth-pass master-b 123456
1
scp -r root@dn1:/usr/local/redis/bin/sentinel.conf /usr/local/redis/bin/sentinel.conf

开机启动

1
2
echo '/usr/local/redis/bin/redis-sentinel /usr/local/redis/bin/sentinel.conf --sentinel' >> /etc/rc.local
chmod +x /etc/rc.d/rc.local

开机启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat >> /etc/systemd/system/redis-sentinel.service << EOF
[Unit]
Description=redis-sentinel
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/bin/sentinel.conf --sentinel
ExecStop=/usr/local/redis/bin/redis-cli -p 26379 shutdown
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl status redis-sentinel.service #查看服务当前状态
systemctl enable redis-sentinel.service #设置开机自启动
systemctl disable redis-sentinel.service #停止开机自启动
systemctl start redis-sentinel.service

配置环境变量

1
2
echo 'export PATH=$PATH:/usr/local/redis/bin' >> /etc/profile
source /etc/profile

3.3、启动 redis 和 sentinel

1
2
3
systemctl start redis.service   #启动redis服务
systemctl stop redis.service #停止redis服务
systemctl restart redis.service #重新启动服务
1
2
3
4
5
6
7
8
9
10
11
$ /usr/local/redis/bin/redis-sentinel /usr/local/redis/bin/sentinel.conf --sentinel
$ /usr/local/redis/bin/redis-cli -p 26379 shutdown

$ /usr/local/redis/bin/redis-cli -p 26379
127.0.0.1:26379> sentinel master master-a
127.0.0.1:26379> sentinel slaves master-a
127.0.0.1:26379> sentinel sentinels master-a
127.0.0.1:26379> sentinel get-master-addr-by-name master-a
127.0.0.1:26379> info sentinel
# 相对于常规的故障切换,其无需进行Sentinel节点的领导者选举。直接由当前Sentinel节点进行后续的故障切换。
127.0.0.1:26379> sentinel failover master-a