Redis高可用集群、哨兵模式(Redis-Sentinel)搭建配置详解

  |   0 评论   |   470 浏览

Redis主从复制简单介绍

为了使得集群在一部分节点下线或者无法与集群的大多数节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。[ 摘自 Redis 集群中的主从复制 ]

那么上面是主从复制呢,简单的来说就是一个主节点master可以拥有一个甚至多个从节点的slave,而一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架构。

20180302150043481png

其中主节点以写为主(可写也可以读),从节点只能读不可写入!【读写分离场景】
其中主节点写入的数据会同步(不是准实时的)到salve上,这样如果主节点出现故障,数据丢失,则可以通过salve进行恢复。【容灾恢复场景,注:因为数据不是实时同步的,可能会存在从salve恢复数据后有数据丢失问题】

综上:下面是关于redis主从复制的一些特点:

1. 一个master可以有多个slave 
2. 除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构 
3. 主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞不能处理client的请求。 
主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用于client的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余 
4. 可以在master禁用数据持久化,只需要注释掉master 配置文件中的所有save配置,然后只在slave上配置数据持久化。 
5. 可以用于读写分离和容灾恢复。

Redis主从复制的常用的几种方式

一主二仆 A(B、C) 一个Master两个Slave
薪火相传(去中心化)A - B - C ,B既是主节点(C的主节点),又是从节点(A的从节点)
反客为主(主节点down掉后,手动操作升级从节点为主节点) & 哨兵模式(主节点down掉后,自动升级从节点为主节点)
本次主要介绍一主二仆,和反客为主的操作,薪火相传不做介绍。哨兵模式后面专门写一篇进行介绍!

Redis主从复制的搭建(一主二仆)

1.下载Windows环境的Redis安装包,并解压,目录如下图:

2018030215152380png

2.相关配置操作
(1)复制redis.windows.conf配置文件为redis.windows.6380.conf,redis.windows.6381.conf

redis.windows.conf,不做修改!

redis.windows.6380.conf,修改如下:

port 6380

# slaveof <masterip> <masterport>
slaveof 127.0.0.1 6379

redis.windows.6381.conf,修改如下:

port 6381

# slaveof <masterip> <masterport>
slaveof 127.0.0.1 6379

3.启动测试
启动规则:先启动主节点,然后在启动从节点!先启动Master。使用客户端登录,查看信息如图:
20180302154642438png

然后启动6380和6381,然后可以看到:如图
20180302154856173png

在此查看6378的主从复制信息:如图
20180302154931389png

在登录6380和6381的客户端,查看节点信息:如图
20180302154939839png

测试读写,【主节点可读可写,从节点只能读不可写】,如下图:
20180302155138685png

测试当主节点shutdown后,从节点的状态【从节点可读,从节点也不会升级为主节点】。

127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:15
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381>
127.0.0.1:6381> get hello
"world"

测试当主节点重新启动后,从节点的状态【从节点依然可以连接主节点】:

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=43,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=43,lag=0
master_repl_offset:43
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:42
127.0.0.1:6379>

小插曲【反客为主】
测试当主节点shutdown后,使用slaveof no one 是的6380成为主节点,但是也只是主节点,没有任何从节点!:如图

127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:155
master_link_down_since_seconds:jd
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381>
127.0.0.1:6381>
127.0.0.1:6381> slave no one
(error) ERR unknown command 'slave'
127.0.0.1:6381> slaveof no one
OK
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381> set test 11
OK
127.0.0.1:6381> get test
"11"
127.0.0.1:6381>

Redis主从复制的原理

第一种介绍

当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。
Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步。
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。(第一次全量)
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步。(之后增量)
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行。
当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件 后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从 client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个 slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。

第二种介绍:

20180302164003590png

第三种介绍:

Redis 主从同步有两种方式(或者所两个阶段):全同步和部分同步。
主从刚刚连接的时候,进行全同步;全同步结束后,进行部分同步。当然,如果有需要,Slave 在任何时候都可以发起全同步。Redis 策略是,无论如何,首先会尝试进行部分同步,如不成功,要求从机进行全同步,并启动 BGSAVE……BGSAVE 结束后,传输 RDB 文件;如果成功,允许从机进行部分同步,并传输积压空间中的数据。
wKiom1N3nPbS5JMAAHj5MGbf50000jpg

Redis主从复制(一主两从/一主多从)的分析

  • IO剧增
    每次slave断开以后(无论是主动断开,还是网路故障)再连接master都要将master全部dump出来rdb,在aof,即同步的过程都要重新执行一遍;所以要记住多台slave不要一下都启动起来,否则master可能IO剧增(间隔1-2分)

  • 复制延迟
    由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

  • 可用性不高
    当有主节点发生异常情况,就会导致不能写入,导致业务出错!解决方法是可以使用Redis-Sentinel模式,参见下方。

Redis哨兵模式,用现在流行的话可以说就是一个“哨兵机器人”,给“哨兵机器人”进行相应的配置之后,这个"机器人"可以7*24小时工作,它能能够自动帮助你做一些事情,如监控,提醒,自动处理故障等。

Redis-sentinel简介

Redis-sentinel是Redis的作者antirez,因为Redis集群的被各大公司使用,每个公司要写自己的集群管理工具,于是antirez花了几个星期写出了Redis-sentinel。

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance),Redis 的 Sentinel 为Redis提供了高可用性。使用哨兵模式创建一个可以不用人为干预而应对各种故障的Redis部署。

该系统执行以下三个任务:

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

Sentinel的分布式特性

Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

单个sentinel进程来监控redis集群是不可靠的,当sentinel进程宕掉后(sentinel本身也有单点问题,single-point-of-failure)整个集群系统将无法按照预期的方式运行。所以有必要将sentinel集群,这样有几个好处:

  • 有一些sentinel进程宕掉了,依然可以进行redis集群的主备切换;

  • 如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题);

  • 如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息

一个健壮的部署至少需要三个哨兵实例。

三个哨兵实例应该放置在客户使用独立方式确认故障的计算机或虚拟机中。例如不同的物理机或不同可用区域的虚拟机。【本次讲解是一个机器上进行搭建,和多级是一个道理】

Redis-sentinel搭建

本次搭建说明:
master:127.0.0.1:6379 【初始化master】

slave:127.0.0.1:6380  127.0.0.1:6381
sentinel:127.0.0.1:26379  127.0.0.1:26380  127.0.0.1:26381

Sentinel配置

根据安装和基本配置,已经有了主从配置 ,对应文件夹Redis6379~Redis6381。然后在每个文件夹下面新增 一个名为 sentinel.conf 的文件。配置内容如下:

# 这个是Redis6379配置内容,其他文件同理新增然后改一下端口即可,26380,和 26381。

#当前Sentinel服务运行的端口
port 26379  
# 哨兵监听的主服务器 
sentinel monitor mymaster 127.0.0.1 6379 2
# 3s内mymaster无响应,则认为mymaster宕机了
sentinel down-after-milliseconds mymaster 3000
#如果10秒后,mysater仍没启动过来,则启动failover  
sentinel failover-timeout mymaster 10000  
# 执行故障转移时, 最多有1个从服务器同时对新的主服务器进行同步
sentinel parallel-syncs mymaster 1

配置文件只需要配置master的信息就好啦,不用配置slave的信息,因为slave能够被自动检测到(master节点中有关于slave的消息)。

为了更清楚每一行配置的含义,对每个选项的含义进行简单介绍:

sentinel monitor [master-group-name] [ip] [port] [quorum]
  • master-group-name:master名称(可以自定义)
  • ip port : IP地址和端口号
  • quorun:票数,Sentinel需要协商同意master是否可到达的数量。

第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。
票数在本文中:redis集群中有3个sentinel实例,其中master挂掉啦,这里设置票数为2,表示有2个sentinel认为master挂掉啦,才能被认为是正真的挂掉啦。

sentinel <选项的名字> <主服务器的名字> <选项的值>
  • down-after-milliseconds 选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
    如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。
    不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。
    将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。

  • parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长。

启动Sentinel实例

哨兵启动命令 redis-server.exe sentinel.conf --sentinel
  • 第一步:点击startRedis.cmd ,启动Redis集群

  • 第二步:点击startRedisSentinel.cmd ,启动哨兵实例

查看Sentinel启动日志,看到```
生成哨兵ID(Sentinel ID),并自动识别主服务器和从服务器!

[114252] 03 Mar 13:32:57.896 # Sentinel ID is 89f521b40a803495472c0457b0396473c4bfb100
[114252] 03 Mar 13:32:57.896 # +monitor master mymaster 127.0.0.1 6379 quorum 2
[114252] 03 Mar 13:32:57.909 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:32:57.917 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379

查看主服务器6379(Master)信息:

F:\nosql_learn\Redis-Sentinel\Redis6379>redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=54148,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=54148,lag=1
master_repl_offset:54414
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:54413
127.0.0.1:6379>

查看主服务器6380(Slave)信息:

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:80531
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>

Redis-Sentinel高可用场景演示

场景1:主服务器master宕机

当主服务器master宕机,那么Sentinel会通过选举(算法)机制,从Salve中选出一个作为新Master。
大概原理是当选出一个Slave要作为Master的时候,会发送命令slaveofno one来取消选中的这个slave,使其成为Master。哨兵会发送给其他从服务器Slave配置选中的这个为新主服务器Master,并删除监听列表中出现故障的Master服务器。
(1)关闭掉 6379主服务器

127.0.0.1:6379> shutdown
not connected>

(2)查看观察选举新的master的过程和显示了failover的过程,整个日志信息还是比较完整的。最后选举了6381为主服务器!

[114252] 03 Mar 13:32:59.945 * +sentinel sentinel 926e67646440b200ee41bb224bacf9e0314e3b32 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:33:00.018 * +sentinel sentinel 7fc21e38de0408ccaa06111e44638e2693794e08 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.223 # +sdown master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.300 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2
[114252] 03 Mar 13:53:19.300 # +new-epoch 1
[114252] 03 Mar 13:53:19.300 # +try-failover master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.306 # +vote-for-leader 89f521b40a803495472c0457b0396473c4bfb100 1
[114252] 03 Mar 13:53:19.319 # 7fc21e38de0408ccaa06111e44638e2693794e08 voted for 89f521b40a803495472c0457b0396473c4bfb100 1
[114252] 03 Mar 13:53:19.369 # +elected-leader master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.370 # +failover-state-select-slave master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.428 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.428 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.530 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:20.327 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:20.328 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:20.398 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.390 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.390 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.445 # +failover-end master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.445 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
[114252] 03 Mar 13:53:21.447 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
[114252] 03 Mar 13:53:21.449 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
[114252] 03 Mar 13:53:23.193 # +sdown sentinel 926e67646440b200ee41bb224bacf9e0314e3b32 127.0.0.1 26379 @ mymaster 127.0.0.1 6381
[114252] 03 Mar 13:53:24.451 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381

(3)查看6381服务器信息,角色为主,从服务器6380!

127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=33358,lag=1
master_repl_offset:33505
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:33504
127.0.0.1:6381>

场景2:之前故障的6379 master重新启动

(1)启动6379服务,发现6379成为6381的从服务器!

F:\nosql_learn\Redis-Sentinel\Redis6379>redis-server.exe redis.windows.conf

[116640] 03 Mar 13:59:25.753 * The server is now ready to accept connections on port 6379
[116640] 03 Mar 13:59:48.315 * SLAVE OF 127.0.0.1:6381 enabled (user request from 'id=2 addr=127.0.0.1:61677 fd=7 name=sentinel-7fc21e38-cmd age=10 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=0 qbuf-free=32768 obl=36 oll=0 omem=0 events=r cmd=exec')
[116640] 03 Mar 13:59:48.326 # CONFIG REWRITE executed with success.
[116640] 03 Mar 13:59:48.826 * Connecting to MASTER 127.0.0.1:6381
[116640] 03 Mar 13:59:48.851 * MASTER <-> SLAVE sync started

(2)查看6381服务器状态信息:原来的master自动切换成slave,不会自动恢复成master。

127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=73183,lag=0
slave1:ip=127.0.0.1,port=6379,state=online,offset=73183,lag=0
master_repl_offset:73183
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:73182
127.0.0.1:6381>

场景3:从服务器Slave宕机和重启

(1)关闭6380从服务器:

127.0.0.1:6380> shutdown
not connected>

(2)Sentinel日志:

[113488] 03 Mar 14:06:50.143 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381

(3)查看住服务器6381状态信息:

127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6379,state=online,offset=111361,lag=1
master_repl_offset:111361
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:111360
127.0.0.1:6381>

(4)启动从服务器6380

Connecting to MASTER 127.0.0.1:6381

(5)查看住服务器6381状态信息:6380又回来了!

role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6379,state=online,offset=141232,lag=0
slave1:ip=127.0.0.1,port=6380,state=online,offset=141232,lag=1
master_repl_offset:141232
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:141231
127.0.0.1:6381>

Jedis客户端使用Sentinel

import java.util.HashSet;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

public class RedisManagerUtil {

	private static JedisSentinelPool pool = null;
	// 自带的哨兵模式 JedisSentinelPool, 并在一开始初始化连接池
	static {
		try {
			JedisPoolConfig config = new JedisPoolConfig();
			// 控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
			// 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
			config.setMaxTotal(Integer.valueOf(1000));
			// 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
			config.setMaxIdle(Integer.valueOf(20));
			// 表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
			config.setMinEvictableIdleTimeMillis(Integer.valueOf(-1));
			// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
			config.setTestOnBorrow(Boolean.valueOf(true));

			// master名称和配置文件中配置的要一样
			String master = "mymaster";
			//setinel客户端提供了master自动发现功能
			Set<String> sentinels = new HashSet<String>();
			sentinels.add("127.0.0.1:26379");
			sentinels.add("127.0.0.1:26380");
			sentinels.add("127.0.0.1:26381");

			pool = new JedisSentinelPool(master, sentinels, config);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 构建redis连接池
	 * 
	 * @return JedisPool
	 */
	public static JedisSentinelPool getPool() {
		return pool;
	}

	/**
	 * 返还到连接池
	 * 
	 * @param pool
	 * @param redis
	 */
	public static void returnResource(JedisSentinelPool pool, Jedis redis) {
		if (redis != null) {
			try {
				pool.returnResource(redis);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 测试redis线程池是否正常
	 * @param args
	 */
	public static void main(String[] args) {
		JedisSentinelPool pool = RedisPoolAPIManager.getPool();
		Jedis redis = pool.getResource();
		System.out.println("redis = " + redis);

		if(redis != null){
			returnResource(pool,redis);
		}
	}
}

总结
Redis-Sentinel是Redis官方推荐的高可用性(HA) 解决方案,Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。Sentinel可以监视任意多个主服务器(复用),以及主服务器属下的从服务器,并在被监视的主服务器下线时,自动执行故障转移操作。

为了防止sentinel的单点故障,可以对sentinel进行集群化,创建多个sentinel。

redis.conf 配置文件介绍

1: Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
    daemonize no

2: 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
    pidfile /var/run/redis.pid

3: 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,
因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
  port 6379

4: 绑定的主机地址
  bind 127.0.0.1

5: 当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
  timeout 300

6: 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,
默认为verbose
  loglevel verbose

7: 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志
记录方式为标准输出,则日志将会发送给/dev/null
  logfile stdout

8: 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
  databases 16

9: 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
  save <seconds> <changes>
  Redis默认配置文件中提供了三个条件:
  save 900 1
  save 300 10
  save 60 10000
  分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

10: 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,
可以关闭该选项,但会导致数据库文件变的巨大
  rdbcompression yes

11: 指定本地数据库文件名,默认值为dump.rdb
  dbfilename dump.rdb

12: 指定本地数据库存放目录
  dir ./

13: 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
  slaveof <masterip> <masterport>

14: 当master服务设置了密码保护时,slav服务连接master的密码
  masterauth <master-password>

15: 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
  requirepass foobared

16: 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端
返回max number of clients reached错误信息
  maxclients 128

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

18: 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。
因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
  appendonly no

19: 指定更新日志文件名,默认为appendonly.aof
   appendfilename appendonly.aof

20: 指定更新日志条件,共有3个可选值: 
  no:表示等操作系统进行数据缓存同步到磁盘(快) 
  always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全) 
  everysec:表示每秒同步一次(折衷,默认值)
  appendfsync everysec

21: 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,
访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
   vm-enabled no

22: 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
   vm-swap-file /tmp/redis.swap

23: 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),
也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
   vm-max-memory 0

24: Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,
vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;
如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
   vm-page-size 32

25: 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
   vm-pages 134217728

26: 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,
可能会造成比较长时间的延迟。默认值为4
   vm-max-threads 4

27: 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
  glueoutputbuf yes

28: 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
  hash-max-zipmap-entries 64
  hash-max-zipmap-value 512

29: 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
  activerehashing yes

30: 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
  include /path/to/local.conf

配置实例:


daemonize yes

#  当 redis 在后台运行的时候, Redis 默认会把 pid 文件放在 /var/run/redis.pid ,你可以配置到其他地址。

#  当运行多个 redis 服务时,需要指定不同的 pid 文件和端口

pidfile /var/run/redis_6379.pid

#  指定 redis 运行的端口,默认是 6379

port 6379

#  在高并发的环境中,为避免慢客户端的连接问题,需要设置一个高速后台日志

tcp-backlog 511

#  指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求

# bind 192.168.1.100 10.0.0.1

# bind 127.0.0.1

#  设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接

# 0 是关闭此设置

timeout 0

# TCP keepalive

#  在 Linux 上,指定值(秒)用于发送 ACKs 的时间。注意关闭连接需要双倍的时间。默认为 0 。

tcp-keepalive 0

#  指定日志记录级别,生产环境推荐 notice

# Redis 总共支持四个级别: debug 、 verbose 、 notice 、 warning ,默认为 verbose

# debug     记录很多信息,用于开发和测试

# varbose   有用的信息,不像 debug 会记录那么多

# notice    普通的 verbose ,常用于生产环境

# warning   只有非常重要或者严重的信息会记录到日志

loglevel notice

#  配置 log 文件地址

#  默认值为 stdout ,标准输出,若后台模式会输出到 /dev/null 。

logfile /var/log/redis/redis.log

#  可用数据库数

#  默认值为 16 ,默认数据库为 0 ,数据库范围在 0- ( database-1 )之间

databases 16

################################ 快照#################################

#  保存数据到磁盘,格式如下 :

#   save  

#    指出在多长时间内,有多少次更新操作,就将数据同步到数据文件 rdb 。

#    相当于条件触发抓取快照,这个可以多个条件配合

#    比如默认配置文件中的设置,就设置了三个条件

#   save 900 1  900 秒内至少有 1 个 key 被改变

#   save 300 10  300 秒内至少有 300 个 key 被改变

#   save 60 10000  60 秒内至少有 10000 个 key 被改变

# save 900 1

# save 300 10

# save 60 10000

#  后台存储错误停止写。

stop-writes-on-bgsave-error yes

#  存储至本地数据库时(持久化到 rdb 文件)是否压缩数据,默认为 yes

rdbcompression yes

# 对rdb数据进行校验,耗费CPU资源,默认为yes

rdbchecksum yes

#  本地持久化数据库文件名,默认值为 dump.rdb

dbfilename dump.rdb

#  工作目录

#  数据库镜像备份的文件放置的路径。

#  这里的路径跟文件名要分开配置是因为 redis 在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成,

#  再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。

# AOF 文件也会存放在这个目录下面

#  注意这里必须制定一个目录而不是文件

dir /var/lib/redis-server/

################################# 复制 #################################

#  主从复制 . 设置该数据库为其他数据库的从数据库 .

#  设置当本机为 slav 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步

# slaveof 

#  当 master 服务设置了密码保护时 ( 用 requirepass 制定的密码 )

# slave 服务连接 master 的密码

# masterauth 

#  当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:

# 1)  如果 slave-serve-stale-data 设置为 yes( 默认设置 ) ,从库会继续响应客户端的请求

# 2)  如果 slave-serve-stale-data 是指为 no ,出去 INFO 和 SLAVOF 命令之外的任何请求都会返回一个

#     错误 "SYNC with master in progress"

slave-serve-stale-data yes

#  配置 slave 实例是否接受写。写 slave 对存储短暂数据(在同 master 数据同步后可以很容易地被删除)是有用的,但未配置的情况下,客户端写可能会发送问题。

#  从 Redis2.6 后,默认 slave 为 read-only

slaveread-only yes

#  从库会按照一个时间间隔向主库发送 PINGs. 可以通过 repl-ping-slave-period 设置这个时间间隔,默认是 10 秒

# repl-ping-slave-period 10

# repl-timeout  设置主库批量数据传输时间或者 ping 回复时间间隔,默认值是 60 秒

#  一定要确保 repl-timeout 大于 repl-ping-slave-period

# repl-timeout 60

#  在 slave socket 的 SYNC 后禁用 TCP_NODELAY

#  如果选择“ yes ” ,Redis 将使用一个较小的数字 TCP 数据包和更少的带宽将数据发送到 slave , 但是这可能导致数据发送到 slave 端会有延迟 , 如果是 Linux kernel 的默认配置,会达到 40 毫秒 .

#  如果选择 "no" ,则发送数据到 slave 端的延迟会降低,但将使用更多的带宽用于复制 .

repl-disable-tcp-nodelay no

#  设置复制的后台日志大小。

#  复制的后台日志越大, slave 断开连接及后来可能执行部分复制花的时间就越长。

#  后台日志在至少有一个 slave 连接时,仅仅分配一次。

# repl-backlog-size 1mb

#  在 master 不再连接 slave 后,后台日志将被释放。下面的配置定义从最后一个 slave 断开连接后需要释放的时间(秒)。

# 0 意味着从不释放后台日志

# repl-backlog-ttl 3600

#  如果 master 不能再正常工作,那么会在多个 slave 中,选择优先值最小的一个 slave 提升为 master ,优先值为 0 表示不能提升为 master 。

slave-priority 100

#  如果少于 N 个 slave 连接,且延迟时间 <=M 秒,则 master 可配置停止接受写操作。

#  例如需要至少 3 个 slave 连接,且延迟 <=10 秒的配置:

# min-slaves-to-write 3

# min-slaves-max-lag 10

#  设置 0 为禁用

#   默认 min-slaves-to-write 为 0 (禁用), min-slaves-max-lag 为 10

################################## 安全 ###################################

#  设置客户端连接后进行任何其他指定前需要使用的密码。

#  警告:因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解

# requirepass foobared

#  命令重命名 .

#  在一个共享环境下可以重命名相对危险的命令。比如把 CONFIG 重名为一个不容易猜测的字符。

#  举例 :

# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52

#  如果想删除一个命令,直接把它重命名为一个空字符 "" 即可,如下:

# rename-command CONFIG ""

################################### 约束###################################

#设置同一时间最大客户端连接数,默认无限制, 

#Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,

#如果设置  maxclients 0 ,表示不作限制。

#当客户端连接数到达限制时, Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息

# maxclients 10000

#  指定 Redis 最大内存限制, Redis 在启动时会把数据加载到内存中,达到最大内存后, Redis 会按照清除策略尝试清除已到期的 Key

#  如果 Redis 依照策略清除后无法提供足够空间,或者策略设置为 ”noeviction” ,则使用更多空间的命令将会报错,例如 SET, LPUSH 等。但仍然可以进行读取操作

#  注意: Redis 新的 vm 机制,会把 Key 存放内存, Value 会存放在 swap 区

#  该选项对 LRU 策略很有用。

# maxmemory 的设置比较适合于把 redis 当作于类似 memcached 的缓存来使用,而不适合当做一个真实的 DB 。

#  当把 Redis 当做一个真实的数据库使用的时候,内存使用将是一个很大的开销

# maxmemory 

#  当内存达到最大值的时候 Redis 会选择删除哪些数据?有五种方式可供选择

# volatile-lru ->  利用 LRU 算法移除设置过过期时间的 key (LRU: 最近使用  Least RecentlyUsed )

# allkeys-lru ->  利用 LRU 算法移除任何 key

# volatile-random ->  移除设置过过期时间的随机 key

# allkeys->random -> remove a randomkey, any key

# volatile-ttl ->  移除即将过期的 key(minor TTL)

# noeviction ->  不移除任何可以,只是返回一个写错误

#  注意:对于上面的策略,如果没有合适的 key 可以移除,当写的时候 Redis 会返回一个错误

#  默认是 :  volatile-lru

# maxmemory-policy volatile-lru  

# LRU  和  minimal TTL 算法都不是精准的算法,但是相对精确的算法 ( 为了节省内存 ) ,随意你可以选择样本大小进行检测。

# Redis 默认的灰选择 3 个样本进行检测,你可以通过 maxmemory-samples 进行设置

# maxmemory-samples 3

############################## AOF###############################

#  默认情况下, redis 会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。

#  所以 redis 提供了另外一种更加高效的数据库备份及灾难恢复方式。

#  开启 append only 模式之后, redis 会把所接收到的每一次写操作请求都追加到 appendonly.aof 文件中,当 redis 重新启动时,会从该文件恢复出之前的状态。

#  但是这样会造成 appendonly.aof 文件过大,所以 redis 还支持了 BGREWRITEAOF 指令,对 appendonly.aof 进行重新整理。

#  你可以同时开启 asynchronous dumps 和  AOF

appendonly no

# AOF 文件名称  ( 默认 : "appendonly.aof")

# appendfilename appendonly.aof

# Redis 支持三种同步 AOF 文件的策略 :

# no:  不进行同步,系统去操作  . Faster.

# always: always 表示每次有写操作都进行同步 . Slow, Safest.

# everysec:  表示对写操作进行累积,每秒同步一次 . Compromise.

#  默认是 "everysec" ,按照速度和安全折中这是最好的。

#  如果想让 Redis 能更高效的运行,你也可以设置为 "no" ,让操作系统决定什么时候去执行

#  或者相反想让数据更安全你也可以设置为 "always"

#  如果不确定就用  "everysec".

# appendfsync always

appendfsync everysec

# appendfsync no

# AOF 策略设置为 always 或者 everysec 时,后台处理进程 ( 后台保存或者 AOF 日志重写 ) 会执行大量的 I/O 操作

#  在某些 Linux 配置中会阻止过长的 fsync() 请求。注意现在没有任何修复,即使 fsync 在另外一个线程进行处理

#  为了减缓这个问题,可以设置下面这个参数 no-appendfsync-on-rewrite

no-appendfsync-on-rewrite no

# AOF  自动重写

#  当 AOF 文件增长到一定大小的时候 Redis 能够调用  BGREWRITEAOF  对日志文件进行重写

#  它是这样工作的: Redis 会记住上次进行些日志后文件的大小 ( 如果从开机以来还没进行过重写,那日子大小在开机的时候确定 )

#  基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动

#  同时需要指定一个最小大小用于 AOF 重写,这个用于阻止即使文件很小但是增长幅度很大也去重写 AOF 文件的情况

#  设置  percentage 为 0 就关闭这个特性

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

################################ LUASCRIPTING #############################

# 一个 Lua 脚本最长的执行时间为 5000 毫秒( 5 秒),如果为 0 或负数表示无限执行时间。

lua-time-limit 5000

################################LOW LOG################################

# Redis Slow Log  记录超过特定执行时间的命令。执行时间不包括 I/O 计算比如连接客户端,返回结果等,只是命令执行时间

#  可以通过两个参数设置 slow log :一个是告诉 Redis 执行超过多少时间被记录的参数 slowlog-log-slower-than( 微妙 ) ,

#  另一个是 slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除

#  下面的时间以微妙为单位,因此 1000000 代表一秒。

#  注意指定一个负数将关闭慢日志,而设置为 0 将强制每个命令都会记录

slowlog-log-slower-than 10000

#  对日志长度没有限制,只是要注意它会消耗内存

#  可以通过  SLOWLOG RESET 回收被慢日志消耗的内存

#  推荐使用默认值 128 ,当慢日志超过 128 时,最先进入队列的记录会被踢出

slowlog-max-len 128

################################  事件通知  #############################

#  当事件发生时, Redis 可以通知 Pub/Sub 客户端。

#  可以在下表中选择 Redis 要通知的事件类型。事件类型由单个字符来标识:

# K     Keyspace 事件,以 _keyspace@_ 的前缀方式发布

# E     Keyevent 事件,以 _keysevent@_ 的前缀方式发布

# g     通用事件(不指定类型),像 DEL, EXPIRE, RENAME, …

# $     String 命令

# s     Set 命令

# h     Hash 命令

# z     有序集合命令

# x     过期事件(每次 key 过期时生成)

# e     清除事件(当 key 在内存被清除时生成)

# A     g$lshzxe 的别称,因此 ”AKE” 意味着所有的事件

# notify-keyspace-events 带一个由 0 到多个字符组成的字符串参数。空字符串意思是通知被禁用。

#  例子:启用 list 和通用事件:

# notify-keyspace-events Elg

#  默认所用的通知被禁用,因为用户通常不需要改特性,并且该特性会有性能损耗。

#  注意如果你不指定至少 K 或 E 之一,不会发送任何事件。

notify-keyspace-events “”

##############################  高级配置  ###############################

#  当 hash 中包含超过指定元素个数并且最大的元素没有超过临界时,

# hash 将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值

# Redis Hash 对应 Value 内部实际就是一个 HashMap ,实际这里会有 2 种不同实现,

#  这个 Hash 的成员比较少时 Redis 为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的 HashMap 结构,对应的 valueredisObject 的 encoding 为 zipmap,

#  当成员数量增大时会自动转成真正的 HashMap, 此时 encoding 为 ht 。

hash-max-zipmap-entries 512

hash-max-zipmap-value 64  

#  和 Hash 一样,多个小的 list 以特定的方式编码来节省空间。

# list 数据类型节点值大小小于多少字节会采用紧凑存储格式。

list-max-ziplist-entries 512

list-max-ziplist-value 64

# set 数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。

set-max-intset-entries 512

#  和 hashe 和 list 一样 , 排序的 set 在指定的长度内以指定编码方式存储以节省空间

# zsort 数据类型节点值大小小于多少字节会采用紧凑存储格式。

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

# Redis 将在每 100 毫秒时使用 1 毫秒的 CPU 时间来对 redis 的 hash 表进行重新 hash ,可以降低内存的使用

#  当你的使用场景中,有非常严格的实时性需要,不能够接受 Redis 时不时的对请求有 2 毫秒的延迟的话,把这项配置为 no 。

#  如果没有这么严格的实时性要求,可以设置为 yes ,以便能够尽可能快的释放内存

activerehashing yes

# 客户端的输出缓冲区的限制,因为某种原因客户端从服务器读取数据的速度不够快,

# 可用于强制断开连接(一个常见的原因是一个发布 / 订阅客户端消费消息的速度无法赶上生产它们的速度)。

#  可以三种不同客户端的方式进行设置:

# normal ->  正常客户端

# slave  -> slave 和 MONITOR 客户端

# pubsub ->  至少订阅了一个 pubsub channel 或 pattern 的客户端

#  每个 client-output-buffer-limit 语法 :

# client-output-buffer-limit   

#  一旦达到硬限制客户端会立即断开,或者达到软限制并保持达成的指定秒数(连续)。

#  例如,如果硬限制为 32 兆字节和软限制为 16 兆字节 /10 秒,客户端将会立即断开

#  如果输出缓冲区的大小达到 32 兆字节,客户端达到 16 兆字节和连续超过了限制 10 秒,也将断开连接。

#  默认 normal 客户端不做限制,因为他们在一个请求后未要求时(以推的方式)不接收数据,

#  只有异步客户端可能会出现请求数据的速度比它可以读取的速度快的场景。

#  把硬限制和软限制都设置为 0 来禁用该特性

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb60

client-output-buffer-limit pubsub 32mb 8mb60

# Redis 调用内部函数来执行许多后台任务,如关闭客户端超时的连接,清除过期的 Key ,等等。

#  不是所有的任务都以相同的频率执行,但 Redis 依照指定的“ Hz ”值来执行检查任务。

#  默认情况下,“ Hz ”的被设定为 10 。

#  提高该值将在 Redis 空闲时使用更多的 CPU 时,但同时当有多个 key 同时到期会使 Redis 的反应更灵敏,以及超时可以更精确地处理。

#  范围是 1 到 500 之间,但是值超过 100 通常不是一个好主意。

#  大多数用户应该使用 10 这个预设值,只有在非常低的延迟的情况下有必要提高最大到 100 。

hz 10  

#  当一个子节点重写 AOF 文件时,如果启用下面的选项,则文件每生成 32M 数据进行同步。

aof-rewrite-incremental-fsync yes

参见:

评论

发表评论