redis 主从复制与哨兵模式

上一篇文章我们简单介绍了redis api 的使用方式,本节的内容,我们讲一下他是如何保证高可用的。
测试版本是redis-3.2.11,从官网拉去到源码后,进行编译make,就会在src目录下看到很多可执行文件,例如redis-server,redis-cli,redis-sentinel等大家耳熟能详的。

首先我们解释一下主从的区别:主对于数据可读可写。从默认是只读不写的。当从连接上主时,主会将数据同步到从上。详细的内容我们可以参考一下Redis主从同步原理-SYNC这篇文章讲的还是很详细的。

哨兵:当主挂掉,哨兵可以通过选举从从服务器中选择一台作为主,提供高可用的方案。注意当原来的主恢复时,也将成为现在主的从服务器。

概念解释完了,我们来搭建环境。首先我们搭建的是主从。从最基本的一主一从开始。

主的配置相较于默认的配置文件修改的点,主要修改的是存放数据的目录而已

bind 127.0.0.1
port 6379
pidfile "/Users/olifer/middle/redis/master/redis_6379.pid"
dir "/Users/olifer/middle/redis/master"

配置好了我们启动服务redis-server redis.conf , 如果看到下面的文字,说明启动成功

783:M 02 Dec 19:19:39.829 # Server started, Redis version 3.2.11
783:M 02 Dec 19:19:39.829 * The server is now ready to accept connections on port 6379

从的配置也相对较为简单,端口改一下6380,最为主要的是配置slaveof,指明他的主是谁

bind 127.0.0.1
port 6380
pidfile "/Users/olifer/middle/redis/slave/redis_6380.pid"
dir "/Users/olifer/middle/redis/slave1"

slaveof 127.0.0.1 6379

配置好了我们启动服务redis-server redis.conf , 如果看到下面的文字,说明启动成功

900:S 02 Dec 19:22:16.682 # Server started, Redis version 3.2.11
900:S 02 Dec 19:22:16.682 * The server is now ready to accept connections on port 6380
900:S 02 Dec 19:22:16.684 * Connecting to MASTER 127.0.0.1:6379
900:S 02 Dec 19:22:16.684 * MASTER <-> SLAVE sync started

通过slave的日志我们可以看出,启动成功,暴露端口为6380,并且连接上了自己的主6379,并且开始了同步数据。

这时候我们可以看一下主的日志,同样也能得到类似的信息,从主的日志可以看出,从确实连接上了主,并且爱是同步数据到从服务器,这个数据同步的过程我们会在下一篇文章中讲述。

783:M 02 Dec 19:22:16.685 * Slave 127.0.0.1:6380 asks for synchronization
783:M 02 Dec 19:22:16.685 * Full resync requested by slave 127.0.0.1:6380
783:M 02 Dec 19:22:16.685 * Starting BGSAVE for SYNC with target: disk
783:M 02 Dec 19:22:16.685 * Background saving started by pid 901
901:C 02 Dec 19:22:16.685 * DB saved on disk
783:M 02 Dec 19:22:16.760 * Background saving terminated with success
783:M 02 Dec 19:22:16.761 * Synchronization with slave 127.0.0.1:6380 succeeded

目前为止我们一个redis的主从就这么搭建好了,是不是超级简单,搭建好了,我们就需要验证功能了。我们使用redis-cli连接到主上,也就是6379。当然你也可以不用指定-p,因为默认的就是6379,这样就可以进入到redis shell的操作界面。我们简单的set一个值

redis-cli -p 6379
127.0.0.1:6379> set name olifer
OK

这时候我们验证一下从服务器的数据有没有同步过来。

redis-cli -p 6380
127.0.0.1:6380> get name
"olifer"

和我们预想的是一致的,我们从从的服务器上可以获取到主的数据,更为确切的说,是主从数据进行了准实时的同步,所以可以从从服务器上获取到数据。

我们可以往从服务器上设置值吗?实践是检验真理的唯一的方式,试一下

127.0.0.1:6380> set age 123
(error) READONLY You can't write against a read only slave.

发现报错了,slave默认情况下是不能写数据,只能读取数据。当然这个也是可以设置的,在从的配置文件中有这个一个配置

slave-read-only yes

从名字我们就看出来他是只读的,如果我们想slave也可以写,我们可以修改此配置为no,之后我们重启一下,看结果就可以了。

127.0.0.1:6380> set age 123
OK

所以一些有用的配置大家还是属性一下吧。

现在大家思考一个问题,主从结构只能保证数据有备份,但是如果主挂掉了,怎么办,整个服务就不可用了,这显然是个大问题。当然redis也帮我们考虑到了这一点。解决方案就是哨兵。他可以作为一个第三方,监控着我们主节点的状态,当发现主挂掉后,就会从这个主的从服务器中进行选举,推选出一个新主,同时slave也切换成这个新主的slave,如果原来的主重启成功了也不会再次成为主了,而是作为slave挂到新主上。现在我们再逐步进行验证。因为涉及到选举所以一个slave肯定是不够的,所以最少是两个,上面我们的6380已经是一个从了,所以我们再新建一个6381的从服务器。配置如下

bind 127.0.0.1
port 6381
pidfile "/Users/olifer/middle/redis/slave/redis_6381.pid"
dir "/Users/olifer/middle/redis/slave2"

slaveof 127.0.0.1 6379

启动redis-server redis-conf后出现下面的页面,说明配置成功

1229:S 02 Dec 19:57:08.243 # Server started, Redis version 3.2.11
1229:S 02 Dec 19:57:08.243 * DB loaded from disk: 0.000 seconds
1229:S 02 Dec 19:57:08.243 * The server is now ready to accept connections on port 6381
1229:S 02 Dec 19:57:08.243 * Connecting to MASTER 127.0.0.1:6379

下面我们再配置哨兵,其实也是特别的简单,我们可以从redis的源文件中找到sentinel.conf配置文件,他就是哨兵的配置

port 26379
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 2

port不用多说,就是一个端口号。我们说一下这个配置,sentinel monitor mymaster 127.0.0.1 6379 1,我们给监控的主节点起了个名字叫做mymaster,他的位置是127.0.0.1,端口是6379,主挂掉后我们要通过选举获得最新的主,所以1代表了法定的人数,也就是有1台服务器同意这个提案就可以。这个配置sentinel down-after-milliseconds mymaster 5000,表示master或slave 5s(默认30秒)不能使用后标记为s_down状态。sentinel parallel-syncs mymaster 2,指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步,配置完成后,开始启动

redis-sentinel sentinel.conf
1385:X 02 Dec 20:12:44.725 * Increased maximum number of open files to 10032 (it was originally set to 7168).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 3.2.11 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 1385
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

1385:X 02 Dec 20:12:44.726 # Sentinel ID is 104e563c9931120931c3594973cab424509c2646
1385:X 02 Dec 20:12:44.726 # +monitor master mymaster 127.0.0.1 6379 quorum 1
1385:X 02 Dec 20:12:44.727 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:12:44.728 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379

从这个日志中我们可以看出,记录了master的信息(127.0.0.1 6379),也记录了slave的信息(127.0.0.1 6380,127.0.0.1 6381).我们可以进入查看一下

redis-cli -p 26379

就可以查看一下master,slave包括哨兵的信息

sentinel master mymaster    //查看master的状态 
sentinel slaves mymaster    //查看salves的状态
sentinel sentinels mymaster //查看哨兵的状态
info sentinel               //查看哨兵信息

我们的环境配置好了,就可以验证一些问题了。第一个问题当主挂掉能否自动切换,从slave中挑选一台作为主。下面我们就把master shutdown.我们可以从哨兵的日志中发现一段这样的日志

1385:X 02 Dec 20:26:49.199 # +sdown master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.199 # +odown master mymaster 127.0.0.1 6379 #quorum 1/1
1385:X 02 Dec 20:26:49.199 # +new-epoch 1
1385:X 02 Dec 20:26:49.199 # +try-failover master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.208 # +vote-for-leader 104e563c9931120931c3594973cab424509c2646 1
1385:X 02 Dec 20:26:49.208 # +elected-leader master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.208 # +failover-state-select-slave master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.274 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.274 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:49.379 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:50.309 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:50.309 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:50.391 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:51.332 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:52.392 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:52.447 # +failover-end master mymaster 127.0.0.1 6379
1385:X 02 Dec 20:26:52.447 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
1385:X 02 Dec 20:26:52.447 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
1385:X 02 Dec 20:26:52.447 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1385:X 02 Dec 20:26:57.489 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380

每个sentinel会向其它sentinal、master、slave定时发送消息,以确认对方是否“活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的“主观认为宕机” Subjective Down,简称SDOWN)。若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"彻底死亡"(即:客观上的真正down机,Objective Down,简称ODOWN),通过一定的vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置。到最后通过选举决定了6380作为新的主,同时将6379(已经挂掉)与6381(存活)作为 6380 的slave。这时候我们看一下各个节点的配置文件。首先看一下6380,原来配置文件中的slaveof 127.0.0.1 6379 已经删掉了,说明他已经不是从节点了,那么他就变成主节点了。在看一下6381 ,他的配置已经从原来的slaveof 127.0.0.1 6379 变成了 slaveof 127.0.0.1 6380。看一下哨兵的配置文件,最下面多了几行

# Generated by CONFIG REWRITE
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-slave mymaster 127.0.0.1 6379
sentinel known-slave mymaster 127.0.0.1 6381
sentinel current-epoch 1

说明哨兵也已经做好了切换。6379这时候在哨兵的眼里就是一个slave了,所以他重启后,不可能变成主了,只能是从了。我们现在启动6379 ,在哨兵的日志中增加了下面两行

1385:X 02 Dec 20:40:09.929 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1385:X 02 Dec 20:40:19.872 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380

在6379的redis-conf文件的最后面,增加了两行

# Generated by CONFIG REWRITE
slaveof 127.0.0.1 6380

所以总的过程就是当哨兵发现主挂掉后,会通过选举选出新主,slave的关系进行切换。整个过程顺滑、完整。不得不说做的很漂亮啊。

参考文章:
redis可用性提升(哨兵sentinel)配置示例
redis哨兵配置主从

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • "只要站在风口,猪也能飞上天",这几年网店,团购,APP,智能硬件一波接着一波,今年人工智能又要"火".弄得我都不...
    xieyan0811阅读 286评论 0 1
  • Crop 裁剪图片Repo(备用): https://github.com/jeduan/cordova-plug...
    待花谢花开阅读 733评论 0 1
  • 写这篇文章的时候,我刚与一玻璃心的人心塞至此,但现在我只想平心气和的写完这篇文章,希望我以后不要轻易忘记对自己的告...
    叶子呐阅读 3,518评论 0 0