柴少鹏的官方网站 技术在分享中进步,水平在学习中升华

Redis的持久化以及主从复制

一、持久化

因为数据是存储在内存中的如果停电机器重启等数据就没了,为了使redis在重启之后仍能保证数据不丢失,需要将数据从内存中某种形式同步到硬盘中,这一过程就是持久化。

Redis支持两种方式的持久化,一种是RDB方式一种是AOF方式。可以单独使用其中一种或将二者结合使用。

1.1 RDB方式

RDB介绍:

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照的形式,它恢复时是将快照文件直接读到内存里。Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换旧的RDB文件,至此一次快照操作完成。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

当复制的时候内存占用是原来的2倍,因为是复制了一个跟当前的进程一样的进程。当执行shutdown会迅速的结束进程并产生一份新的rdb文件。

RDB文件是经过压缩(可以配置rdbcompression参数以禁用压缩节省CPU占用)的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。

除了自动快照,还可以手动发送SAVE或BGSAVE命令让Redis直行快照,两个命令的区别在于,前者是由主进程进行快照操作,会阻塞住其他请求,后者会通过fork子进程快照操作。还可以通过lastsave命令获取最后一次成功执行快照的时间。

配置文件介绍:

save 900 1
save 300 10
save 60 10000
#上面三个选项就是RDB的自动触发条件,都是或的关系。如果要禁用RDB持久化策略,只要不设置任何save指令或者save""便可。
rdbcompression yes
#默认是开启压缩存储的,采用LZF算法进行压缩,如果redis占用空间不大或者不想消耗CPU来进行压缩可以设置no为关闭此功能,一般不关闭。
rdbchecksum yes
#在存储快照后,还可以让redis使用CRC64算法来进行数据检验,但是这样会增加大约10%的性能消耗,一般也是开启的。
dbfilename dump.rdb
#指定rdb文件的名称
dir /data/
#指定rdb文件的目录位置,只能为文件夹不能为文件,一般我们保持到一个单独的目录中,如我们生产就是单挂的SSD盘

1.2 AOF方式

AOF方式就是以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,也就是说,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

默认情况下Redis没有开启AOF(append only file)方式的持久化。

appendonly yes
#上面是开启AOF持久化。每执行一条会更改redis中的数据的命令,redis就会将该命令写入硬盘中的AOF文件。
appendfilename appendonly.aof
#设置AOF文件的名称。因为我们上面已经制定了目录文件是/data  所以这个AOF文件也会存储在/data中。

RDB和AOF文件可以同时存在,但是Redis启动的时候会优先加载aof文件。

# redis-check-aof --fix appendonly.aof   #修复aof文件,将不规范的规则语法清理掉。

127.0.0.1:6379> set jilu 123   #写入一条记录
OK

# cat /data/appendonly.aof

*2
$6
SELECT
$1
0
*3
$3
set
$4
jilu
$3
123

#从上面的例子可以看出AOF文件是纯文本文件,其内容是redis客户端向redis发送的原始通信协议的内容。随着执行命令的越来越多,AOF文件的大小也会越来越大,即使内存中实际的数据可能并不多。希望将无用的记录删除,只保留有用的操作记录。所以下面的设置让达到一定条件时,redis就会自动重写AOF文件。

auto-aof-rewrite-percentage 100
#当目前AOF文件大小超过上一次重写时的AOF文件的百分之多少时会再次进行重写,这里是百分之百也就是翻了一倍。如果之前没有重写过,则以启动时的AOF文件大小为依据。
auto-aof-rewrite-min-size 64mb
#允许重写的最小AOF文件的大小,这里是当小于64MB的时候不执行重写。

重写原理:

AOF文件持续增长而过大时,会fork出一条新进程将文件重写(显示写到临时文件最后再rename),遍历新进程的内存中的数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件。

127.0.0.1:6379> BGREWRITEAOF   #可手工让其执行重写

需要注意的是:

由于操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了系统的硬盘缓存。默认情况下系统每30秒会执行一次同步操作,以便将硬盘缓存中的内容真正地写入硬盘,在这30秒的过程中如果系统异常退出也会导致硬盘缓存中的数据丢失。

appendfsync everysec
#默认采用的是这种形式即每秒执行一次同步操作。# appendfsync always表示每次执行写入操作都会执行同步这是最安全的也是最慢的方式。# appendfsync no表示交给系统来执行同步操作这是最快也是最不安全的方式。一般选择默认便可。

相同的数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb。aof运行效率要慢于rdb,每秒同步效率策略较好,不同步效率和rdb相同。

一般就用默认的启动rdb不启动aof就可以了,当然可能会丢失写数据。很多时候是用的下面主从复制的方式,一般只在slave上面持久化rdb文件。

二、主从复制

一般数据库都会有主从复制,一方面可以做到其他服务器上面也可以备份数据,另一方面也可以做到读写分离,而且就算主服务器出现问题,从服务器也可以顶上去继续提供服务。

2.1 一主一从的配置

数据库分类主数据库(master)和从数据库(slave)。主数据库可以进行读写操作,当发生些操作时自动将数据同步给从数据库。从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。

主数据库上面不用配置,只要在从数据库上面配置就可以了。

这里我们让一台机器192.168.1.111作为主数据库,192.168.1.112作为从数据库。

192.168.1.112配置文件的修改:

slaveof 192.168.1.111 6379

#只要开启上面一句话,指定主服务器的IP 端口,重新加载一下配置文件就可以了。

#当然在从数据库上面也可以直接命令启动:

# redis-server --port 6379 --slaveof 192.168.1.111 6379
当然一般会有报错:

2890:S 01 Jul 08:47:35.715 # Error reply to PING from master: '-DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect'
#要么你就在master上面加上密码,这里通过加主服务器的密码进行主从同步,要么就在主redis的配置文件里面加上一句protected-mode no (默认是开启的,这是3.2版本之后新增的保护模式)。

好了调整之后,进入从redis服务器,查看一下Info:

# Replication
role:slave                #角色是slave服务器
master_host:192.168.1.111  #主服务器IP是192.168.1.111
master_port:6379           #端口是6379
master_link_status:up      #主从同步状态是开启的(没有做上面的操作,这里是master_link_status:down)

好了然后再主服务器192.168.1.111上面执行一条命令看是否能同步:

127.0.0.1:6379> set master 192.168.1.111
OK

在从192.168.1.112上面进行查看(当然从上面也是有保护模式的,这里我们配置文件中绑定IP便可以):

192.168.1.112:6379> get master
"192.168.1.111"
192.168.1.112:6379> set nihao  123  #试着手工写入一下,默认是只读模式。
(error) READONLY You can't write against a read only slave.
#当然可以开启写操作,配置文件中的salve-read-only为no。但是从数据库的任何更改不会同步给任何其他数据库,并且一旦主数据库中更新了
对应的数据就会覆盖从数据库的改动。

#这个已经主从同步配置完毕了,这种也是最基本的主从模式。

复制原理:

全量复制:salve启动成功连接到master后会发送一个sync命令,主数据库接收到sync命令后会开始在后台保存快照(即RDB持久化的过程)并将保存期间接收到的命令缓存起来。当快照完成后,redis会将快照文件和所有缓存的命令发送给从数据库,以完成一次完全同步全量复制。而slave服务在收到后,会载入快照文件并执行收到的缓存的命令。在这个过程中主从同步是通过RDB来同步数据, 即使禁用了RDB也没有用,那么就会产生IO问题,在这个复制过程可能就会出现瓶颈. Redis在2.8.18版本开始实现了无磁盘复制功能。Redis在与从库进行复制初始化时将不会把快照储存到磁盘,而是直接通过网络发送给从库,避免了IO性能问题.

增量复制:master继续讲新的所有收集到的修改命令一次传给slave,完成同步但是只要是重新连接master(不支持断点续传),一次完全同步(全量复制)将被自动执行。

读写分离:

图片.png

通过复制可以实现读写分离以提高服务器的负载能力。在常见的场景中,读的频率大于写,当单机的Redis无法应付大量的读请求时(尤其是较耗资源的请求,比如SORT命令等)可以通过复制功能建立多个从数据库,主数据库只进行写操作,而从数据库负责读操作。

从数据库持久化:

另一个相对耗时的操作是持久化,为了提高性能,可以通过复制功能建立一个(或若干个)从数据库,并在从数据库中启用持久化,同时在主数据库禁用持久化。当从数据库崩溃时重启后主数据库会自动将数据同步过来,所以无需担心数据丢失。而当主数据库崩溃时,需要在从数据库中使用SLAVEOF NO ONE命令将从数据库提升成主数据库继续服务,并在原来的主数据库启动后使用SLAVEOF命令将其设置成新的主数据库的从数据库,即可将数据同步回来。

2.2 主-从-从结构

我们让192.168.1.111作为最顶级的主数据库专门负责写入,然后192.168.1.112作为其从库,然后192.168.1.114作为192.168.1.112的从库:

现在新加了个192.168.1.114的配置:

slaveof 192.168.1.112 6379   #配置文件中加上这么一句话就完事了,指定其向192.168.1.112的6379同步

好了现在让我们Info查看一下各个数据库的状态:

192.168.1.111的查看:

127.0.0.1:6379> INFO Replication
# Replication
role:master              #角色是master
connected_slaves:1       #有一个从库跟其连接
slave0:ip=192.168.1.112,port=6379,state=online,offset=3751,lag=0   #从库的信息
master_repl_offset:226
repl_backlog_active:1         #开启复制积压缓冲区
repl_backlog_size:1048576     
repl_backlog_first_byte_offset:2  #复制缓冲区里偏移量的大小
master_repl_offset:226#积压队列server.repl_backlog中,当前累积的数据量的大小。该值不会超过积压队列的总容量server.repl_backlog_size。

 server.master_repl_offset:一个全局性的计数器。该属性只有存在积压队列的情况下才会增加计数。当存在积压队列时,每次收到客户端发来的,长度为len的请求命令时,就会将server.master_repl_offset增加len。该属性也就是所谓的主节点上的复制偏移量。当从节点发来PSYNC命令后,主节点回复从节点"+FULLRESYNC  <runid> <offset>"消息时,其中的offset就是取的主节点当时的server.master_repl_offset的值。这样当从节点收到该消息后,将该值保存在复制偏移量server.master->reploff中。进入命令传播阶段后,每当主节点收到客户端的命令请求,则将命令的长度增加到server.master_repl_offset上,然后将命令传播给从节点,从节点收到后,也会将命令长度加到server.master->reploff上,从而保证了主节点上的复制偏移量server.master_repl_offset和从节点上的复制偏移量server.master->reploff的一致性。需要注意的,server.master_repl_offset的值并不是严格的从0开始增加的。它只是一个计数器,只要能保证主从节点上的复制偏移量一致即可。比如如果它的初始值为10,发送给从节点后,从节点保存的复制偏移量初始值也为10,当新的命令来临时,主从节点上的复制偏移量都会相应增加该命令的长度,因此这并不影响主从节点上偏移量的一致性。

repl_backlog_size:repl_backlog是redis用于存储更新命令的一块buffer,在部分复制的时候Slave会请求Master从这块buffer中获取闪断情况下丢失的更新操作。repl_backlog在redis启动的时候初始化为NULL,当有Slave连接上来的时候,会被指向创建的buffer,默认为1024*1024(即1Mb)。repl_backlog_size表示该buffer的大小(默认1024*1024,即1Mb)。该buffer是作为一个环形缓存区使用的,当有数据超过buffer的大小以后就会重新从buffer的头部开始写入。

192.168.1.112的查看:

192.168.1.112:6379> INFO Replication
# Replication
role:slave          #角色还是从库
master_host:192.168.1.111   #向哪个主库同步
master_port:6379               #主服务器的 TCP 监听端口号。
master_link_status:up          #复制连接当前的状态, up 表示连接正常, down 表示连接断开。
master_last_io_seconds_ago:2   #距离最近一次与主服务器进行通信已经过去了多少秒钟。
master_sync_in_progress:0      # 一个标志值,记录了主服务器是否正在与这个从服务器进行同步。
slave_repl_offset:226          #上面讲过了跟主服务器哪里一致,就是记录数据同步的偏移量也就是同步到哪个点了。
slave_priority:100             #适用Sentinel模块(unstable,M-S集群管理和监控),需要额外的配置文件支持。slave的权重值,默认100.当master失效后,Sentinel将会从slave列表中找到权重值最低(>0)的slave,并提升为master。
如果权重值为0,表示此slave为"观察者",不参与master选举。
slave_read_only:1        #只读状态
connected_slaves:1       #一个从库连接
slave0:ip=192.168.1.114,port=6379,state=online,offset=226,lag=0   #从库信息
master_repl_offset:226
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:225

192.168.1.114上面的查看:

192.168.1.114:6379> INFO Replication
# Replication
role:slave                 #角色也是从库
master_host:192.168.1.112  #对于192.168.1.114来说它的主服务器是192.168.1.112
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:226
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

下面在192.168.1.111上面操作一下,看是否都同步过去了:

127.0.0.1:6379> set mastertest 192.168.112-192.168.1.114
OK

192.168.1.112上面查看:

192.168.1.112:6379> get mastertest
"192.168.112-192.168.1.114"

192.168.1.114上面查看:

192.168.1.114:6379> get mastertest
"192.168.112-192.168.1.114"

2.3 一主双从的结构

192.168.1.114修改下配置文件(然后重新启动下服务):

slaveof 192.168.1.111 6379

192.168.1.111上面的查看:

127.0.0.1:6379> INFO Replication
# Replication
role:master
connected_slaves:2   #现在从服务器增加了一个多了一个192.168.1.114
slave0:ip=192.168.1.112,port=6379,state=online,offset=1156,lag=1
slave1:ip=192.168.1.114,port=6379,state=online,offset=1156,lag=1
master_repl_offset:1156
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1155

模拟master停止服务,找一台salve升级为master:

现在我们把主master192.168.1.111的redis服务关闭。

127.0.0.1:6379> SHUTDOWN
not connected>

#然后你观察另外两台salve服务器,192.168.1.112和192.168.1.114,发现数据还在,但是一直在报错连不上主服务器了。

现在我们将192.168.1.112从salve升级为master:

192.168.1.112:6379> SLAVEOF NO ONE 
OK

然后我们让192.168.1.114改为向192.168.1.112去获取同步数据:

192.168.1.114:6379> slaveof 192.168.1.112 6379
OK

然后回到192.168.1.112上面进行查看:

192.168.1.112:6379> INFO Replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.1.114,port=6379,state=online,offset=1590,lag=0
master_repl_offset:1590
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1589

然后192.168.1.112进行一下写操作进行下查看192.168.1.114是否能同步:

192.168.1.112:6379> set newmaster 192.168.1.112
OK

然后192.168.1.114上面进行查看:

192.168.1.114:6379> get newmaster
"192.168.1.112"

#上面这种操作时成功的,因为我们要求迅速的主从切换,肯定不能再去改什么配置文件重启服务啥的了,所以一般都是命令行执行,然后再可以去修改配置文件。当然这种操作还需要人工不够自动。

三、Sentinel配置(哨兵模式)

在线文档:http://doc.redisfans.com/topic/sentinel.html

这个是从开发的角度讲的很详细:http://blog.csdn.net/gqtcgq/article/details/51531328

3.1 Sentinel介绍

Sentinel是一个管理多个redis实例的工具,它可以实现对redis的监控、通知、自动故障转移。sentinel不断的检测redis实例是否可以正常工作,通过API向其他程序报告redis的状态,如果redis master不能工作,则会自动启动故障转移进程,将其中的一个slave提升为master,其他的slave重新设置新的master实例。也就是说,它提供了:
监控(Monitoring): Sentinel 会不断地检查你的主实例和从实例是否正常。
通知(Notification): 当被监控的某个 Redis 实例出现问题时, Sentinel 进程可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主redis实例失效时, Sentinel 会开始记性一次failover, 它会将失效主实例的其中一个从实例升级为新的主实例, 并让失效主实例的其他从实例改为复制新的主实例; 而当客户端试图连接失效的主实例时, 集群也会向客户端返回新主实例的地址, 使得集群可以使用新主实例代替失效实例。
Redis Sentinel自身也是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程, 这些进程使用流言协议(gossip protocols)来接收关于主Redis实例是否失效的信息, 然后使用投票协议来决定是否执行自动failover,以及评选出从Redis实例作为新的主Redis实例。

3.2 Sentinel的配置

这个配置文件最好的方式是最好放在三个不同的服务器上面,当然配置文件内容是一致的。redis.conf配置文件还是上面主备文件。

# vim /usr/redis/sentinel.conf

port 26379   #默认端口就是26379,当前sentinel服务运行的端口
dir /tmp     #Sentinel服务运行时使用的临时文件夹
sentinel monitor mymaster 192.168.1.111 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

第三行:默认是sentinel monitor mymaster 127.0.0.1 6379 2。这句话的意思是 Sentinel 去监视一个名为 mymaster 的主redis实例,这个主实例的 IP 地址为本机地址127.0.0.1 , 端口号为 6379 , 而将这个主实例判断为失效至少需要 2 个 Sentinel 进程的同意,只要同意 Sentinel 的数量不达标,自动failover就不会执行。同时,一个Sentinel都需要获得系统中大多数Sentinel进程的支持, 才能发起一次自动failover, 并预留一个新主实例配置的编号。而当超过半数Redis不能正常工作时,自动故障转移是无效的。
第四行:sentinel down-after-milliseconds mymaster 30000。指定了 Sentinel 认为Redis实例已经失效所需的毫秒数。这里是30秒。当实例超过该时间没有返回PING,或者直接返回错误, 那么 Sentinel 将这个实例标记为主观下线(subjectively down,简称 SDOWN )。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移: 只有在足够数量的 Sentinel 都将一个实例标记为主观下线之后,实例才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。

第五行:sentinel parallel-syncs mymaster 1。指定了在执行故障转移时, 最多可以有多少个从Redis实例在同步新的主实例, 在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长。尽管复制过程的绝大部分步骤都不会阻塞从实例, 但从redis实例在载入主实例发来的 RDB 文件时, 仍然会造成从实例在一段时间内不能处理命令请求: 如果全部从实例一起对新的主实例进行同步, 那么就可能会造成所有从Redis实例在短时间内全部不可用的情况出现。所以从实例被设置为允许使用过期数据集(参见对 redis.conf 文件中对 slave-serve-stale-data 选项),可以缓解所有从实例都在同一时间向新的主实例发送同步请求的负担。你可以通过将这个值设为 1 来保证每次只有一个从Redis实例处于不能处理命令请求的同步状态。

第六行:sentinel failover-timeout mymaster 180000。如果在该时间(ms)内未能完成failover操作,则认为该failover失败。

3.3 运行Sentinel的两种方式

第一种:# redis-sentinel /usr/redis/sentinel.conf
第二种:#redis-server /usr/redis/sentinel.conf --sentinel

以上两种方式,都必须指定一个sentinel的配置文件sentinel.conf,如果不指定,将无法启动sentinel。sentinel默认监听26379端口,所以运行前必须确定该端口没有被别的进程占用。

3.4 关闭master服务查看是否成功

现在将sentinel.conf从192.168.1.111上分发到192.168.1.112和192.168.1.114上面,然后通过上面的第一种启动服务方式启动服务。

192.168.1.111上面的输出信息:

5893:X 01 Jul 12:21:10.186 # Sentinel ID is c8f790011c9d8984f62bc2b014c91f3dd1bee2ec
5893:X 01 Jul 12:21:10.186 # +monitor master mymaster 192.168.1.111 6379 quorum 2
5893:X 01 Jul 12:21:11.619 * +sentinel-address-switch master mymaster 192.168.1.111 6379 ip 192.168.1.114 port 26379 for ac181c6967e3142e50b74df92e7cf03ac168d7c4
5893:X 01 Jul 12:21:40.221 # +sdown sentinel bbd7202cefa53a1872e981c184e7d2d702dd3684 192.168.1.112 26379 @ mymaster 192.168.1.111 6379
5893:X 01 Jul 12:21:41.656 # +sdown sentinel ac181c6967e3142e50b74df92e7cf03ac168d7c4 192.168.1.114 26379 @ mymaster 192.168.1.111 6379

192.168.1.112上面的输出信息:

图片.png

192.168.1.114上面的输出信息也差不多是这个意思。

现在我们将192.168.1.111关闭,查看现在哪个从redis主机变为了主。

下面是一个完整的master下线然后裁决的过程:

1828:X 01 Jul 15:05:45.717 # +sdown master mymaster 192.168.1.111 6379
1828:X 01 Jul 15:05:45.784 # +odown master mymaster 192.168.1.111 6379 #quorum 3/2
1828:X 01 Jul 15:10:11.216 # +new-epoch 6
1828:X 01 Jul 15:10:11.216 # +try-failover master mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:11.219 # +vote-for-leader c8f790011c9d8984f62bc2b014c91f3dd1bee2ec 6
1828:X 01 Jul 15:10:11.227 # bbd7202cefa53a1872e981c184e7d2d702dd3684 voted for c8f790011c9d8984f62bc2b014c91f3dd1bee2ec 6
1828:X 01 Jul 15:10:11.279 # ac181c6967e3142e50b74df92e7cf03ac168d7c4 voted for c8f790011c9d8984f62bc2b014c91f3dd1bee2ec 6
1828:X 01 Jul 15:10:11.295 # +elected-leader master mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:11.295 # +failover-state-select-slave master mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:11.371 # +selected-slave slave 192.168.1.112:6379 192.168.1.112 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:11.371 * +failover-state-send-slaveof-noone slave 192.168.1.112:6379 192.168.1.112 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:11.455 * +failover-state-wait-promotion slave 192.168.1.112:6379 192.168.1.112 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:12.161 # +promoted-slave slave 192.168.1.112:6379 192.168.1.112 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:12.161 # +failover-state-reconf-slaves master mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:12.231 * +slave-reconf-sent slave 192.168.1.114:6379 192.168.1.114 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:13.219 * +slave-reconf-inprog slave 192.168.1.114:6379 192.168.1.114 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:13.219 * +slave-reconf-done slave 192.168.1.114:6379 192.168.1.114 6379 @ mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:13.290 # +failover-end master mymaster 192.168.1.111 6379
1828:X 01 Jul 15:10:13.290 # +switch-master mymaster 192.168.1.111 6379 192.168.1.112 6379
1828:X 01 Jul 15:10:13.291 * +slave slave 192.168.1.114:6379 192.168.1.114 6379 @ mymaster 192.168.1.112 6379
1828:X 01 Jul 15:10:13.291 * +slave slave 192.168.1.111:6379 192.168.1.111 6379 @ mymaster 192.168.1.112 6379
1828:X 01 Jul 15:10:43.330 # +sdown slave 192.168.1.111:6379 192.168.1.111 6379 @ mymaster 192.168.1.112 6379

#从上面可以看出已经最后是192.168.1.112当选成为了master。

然后上192.168.1.112上面查看一下:

192.168.1.112:6379> INFO Replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.1.114,port=6379,state=online,offset=70154,lag=0
master_repl_offset:70436
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:70435

然后将192.168.1.111的redis服务启动起来:

1828:X 01 Jul 15:16:44.961 # -sdown slave 192.168.1.111:6379 192.168.1.111 6379 @ mymaster 192.168.1.112 6379

#只有这一条消息,192.168.1.111不再是离线状态,然后让它设置192.168.1.112为主。

再次查看192.168.1.112的info信息:

192.168.1.112:6379> INFO Replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.114,port=6379,state=online,offset=150656,lag=1
slave1:ip=192.168.1.111,port=6379,state=online,offset=150656,lag=1
master_repl_offset:150656
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:150655

#从上面的结果会看出192.168.1.112依旧是master,原来旧的master已经变为了slave。而且你可以看下配置文件是不是也发生了变化。

3.5 redis设置了密码,sentinel.conf配置文件的修改

#http://www.51niux.com/?id=127  #最后redis做了密码设置

sentinel auth-pass cms_redis redis48cs    #就是在上面的配置文件中加上这么一句话

# vim /usr/redis/sentinel.conf  #这是启动之后sentinel.conf被更改后的一些信息

port 26379     #哨兵的端口
protected-mode no

sentinel myid 361c709c82eaa963e877452317272ebee22db36a
sentinel monitor cms_redis 192.168.1.111 20000 2  
dir "/data/redisdata/CMS"    #这种就是一个项目一个目录名称,一般一台服务器上面会跑多个redis服务以及多个哨兵
sentinel auth-pass cms_redis redis48cs
sentinel config-epoch cms_redis  3
sentinel leader-epoch cms_redis  3
sentinel known-slave cms_redis 192.168.1.112 20000
sentinel known-slave cms_redis 192.168.1.114 20000
#上面两个也是启动sentinel之后产生的,是另外redis slave的IP和端口,这里另外两个节点的sentinel.conf是一致的
sentinel known-sentinel cms_redis 192.168.1.112 26379 d3a28579310358b0cddbe5a1b88290f619dd5b76
sentinel known-sentinel cms_redis 192.168.1.114 26379 c8a1b05cbe80b736bbf479df3de8401961ae82ed
#这上面也是启动sentinel之后产生的,另外两个sentinel节点的信息,每个sentinel这里都没有本节点的IP信息,都是其他sentinel的
sentinel current-epoch  3

#对上面参数的解释:

1. protected-mode :   

默认情况下,redis node和sentinel的protected-mode都是yes,在搭建集群时,若想从远程连接redis集群,需要将redis node和sentinel的protected-mode修改为no,若只修改redis node,从远程连接sentinel后,依然是无法正常使用的,且sentinel的配置文件中没有protected-mode配置项,需要手工添加。依据redis文档的说明,若protected-mode设置为no后,需要增加密码证或是IP限制等保护机制,否则是极度危险的。

2.sentinel myid :

每当一个Sentinel启动后,它就会修改并通知其它Sentinel同时修改自身的sentinel.conf文件,例如:生成一个myid

当启动过redis-sentinel时,会在主机sentinel.conf和从机sentinel.conf中生成myid,建议重启redis-sentinel时将sentinel.conf中生成的myid删除,不然主从切换时,会根据myid去找对应的从机,当新生成的myid和原来的myid不一致,将无法切换

3.sentinel monitor:

上面这句话的意思是监控集群名是cms_redis的IP是192.168.1.111的20000端口,然后当有2台哨兵监控到主机出错后执行主从切换

sentinel提供的master ip:sentinel保存着所有可用node的IP,程序通过sentinel来获取redis的可用master ip来创建连接池连接,若sentinel和redis node部署在同一台服务器,sentinel监控的master ip不能写成127.0.0.1,需要写成真实IP。sentinel在对外管理MASTER IP时,只是简单的将配置文件中的IP保存,而不会在对外提供服务时,动态转换为127.0.0.1所在机器的真实IP

4.dir:

Sentinel服务运行时使用的临时文件夹,一般跟redis的日志啊等放到一个目录下就可以了

5.sentinel auth-pass:

cmd_redis的集群的验证密码,这个密码需要和redis.conf中的masterauth一致。

6.sentinel config-epoch:

指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步

7.sentinel leader-epoch

同时一时间最多少个slave可同时更新配置

8.sentinel current-epoch

当前可同时同步的salve数最大同步阀值

注:

注1:

redis在使用过程中,内存是一直增加状态,虽然删除了 key,但是内存空间已经开辟了,这块内存空间也不会退回给系统。所以如果对redis作了大规模key清理,然后不重启redis的话,可能会发现redis还是占用那么大的内存空间。

注2:

redis使用单核,但是线上redis所使用的服务器一般CPU核数都比较多,内存一般也会比较大,而且会可能会使用SSD作为持久化文件的存储盘。这样一来如果上面只要一个redis实例显然有些浪费。一般可能会在一个主redis目录下面,创建好多不同以对应业务命令的目录,里面存放redis的配置文件,当然配置文件里面的端口是不一样的。然后持久化文件也存放在本目录下面,这样一种多实例的方式来使用redis。然后几台服务器都是跑相同的多实例,通过哨兵模式进行主从复制,读写分离和容灾策略。

注3:

redis实例一般不用默认的6379端口,一般都会自定义端口,如:26750。

注4:

前一段时间爆出了redis的漏洞,可以通过redis来攻占服务器。所以redis一般都是监听在127.0.01上面并且设置复杂密码。

注5:

如果我们程序直接连接master的ip和端口进行写操作,如果这时候主redis死了,哨兵发现了换了一个主master,这时候redis的主IP就变化了,你再去改程序?显然是不合适的,所以这就体现了哨兵模式的强大之处了。

哨兵模式可不仅仅是监控以及调度,还能返回信息。先看几个命令的使用。

# redis-cli -h 192.168.1.111 -p 26379 info sentinel  #直接指定哨兵的IP和端口,通过info sentinel 可以获得master的IP和端口

# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.1.112:6379,slaves=2,sentinels=3

# redis-cli -h 192.168.1.111 -p 26379 SENTINEL get-master-addr-by-name mymaster    #也可以获得master的主机和端口。

1) "192.168.1.112"
2) "6379"

# redis-cli -h 192.168.1.111 -p 26379 SENTINEL slaves mymaster|grep :  #获得现在运行的redis的从主机的IP和端口

192.168.1.114:6379
192.168.1.111:6379

# redis-cli -h 192.168.1.111 -p 26379 PING #查看一个哨兵是否正常,正常返回PONG

PONG

再看下这边博文:http://blog.sina.com.cn/s/blog_48c95a190102v6bg.html

其实就是你程序其实连接的是你哨兵的IP和端口,然后你首先是跟哨兵通信,从它哪里拿到redis的master和slave的信息,这样就算redis的master切换了,程序端那里也不用修改,因为哨兵会返回给你正确的IP和端口。

作者:忙碌的柴少 分类:Redis 浏览:2772 评论:0
留言列表
发表评论
来宾的头像