Redis高可用架构

        说个题外话,今天我本来想搭建redis作为oracle的缓存的,可是在网上搜了好久,也没有这样的方案,更多的搭配是redis+mysql ,那么oracle就让他与timesten搭配吧。

        言归正传。

1. 什么是Redis?

Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库

Redis全称为:Remote Dictionary Server(远程数据服务),该软件使用C语言编写,Redis是一个key-value存储系统,它支持丰富的数据类型,如:string、list、set、zset(sorted set)、hash。



2. Redis有什么特点?

Redis以内存作为数据存储介质,所以读写数据的效率极高,远远超过数据库。

众多语言都支持Redis,因为Redis交换数据快,所以在服务器中常用来存储一些需要频繁调取的数据,这样可以大大节省系统直接读取磁盘来获得数据的I/O开销,更重要的是可以极大提升速度。


3.Redis与memcache有什么区别?

Redis跟memcache不同的是,储存在Redis中的数据是持久化的,断电或重启后,数据也不会丢失。因为Redis的存储分为内存存储、磁盘存储和log文件三部分,重启后,Redis可以从磁盘重新将数据加载到内存中,这些可以通过配置文件对其进行配置,正因为这样,Redis才能实现持久化。
Redis支持主从模式,可以配置集群,这样更利于支撑起大型的项目,这也是Redis的一大亮点。

4.以下是Redis的数据结构,这段内容需要做个了解。

下面不清楚的命令可以参考命令帮助 http://doc.redisfans.com/

---------------------------------------------------------------------------------

4.1 String类型
Redis能存储二进制安全的字符串,最大长度为1GB

redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> GET name
"John Doe"
String类型还支持批量的读写操作


redis 127.0.0.1:6379> MSET age 30 sex "male"
OK
redis 127.0.0.1:6379> MGET age sex
1) "30"
2) "male"


String类型其实也可以用来存储数字,并支持对数字的加减操作。
redis 127.0.0.1:6379> INCR age
(integer) 31
redis 127.0.0.1:6379> INCRBY age 4
(integer) 35
redis 127.0.0.1:6379> GET age
"35"
redis 127.0.0.1:6379> DECR age
(integer) 34
redis 127.0.0.1:6379> DECRBY age 4
(integer) 30
redis 127.0.0.1:6379> GET age
"30"


String类型还支持对其部分的修改和获取操作
redis 127.0.0.1:6379> APPEND name " Mr."
(integer) 12
redis 127.0.0.1:6379> GET name
"John Doe Mr."
redis 127.0.0.1:6379> STRLEN name
(integer) 12
redis 127.0.0.1:6379> SUBSTR name 0 3
"John"

---------------------------------------------------------------------------------
4.2 List类型
Redis能够将数据存储成一个链表,并能对这个链表进行丰富的操作

redis 127.0.0.1:6379> LPUSH students "John Doe"
(integer) 1
redis 127.0.0.1:6379> LPUSH students "Captain Kirk"
(integer) 2
redis 127.0.0.1:6379> LPUSH students "Sheldon Cooper"
(integer) 3
redis 127.0.0.1:6379> LLEN students
(integer) 3
redis 127.0.0.1:6379> LRANGE students 0 2
1) "Sheldon Cooper"
2) "Captain Kirk"
3) "John Doe"
redis 127.0.0.1:6379> LPOP students
"Sheldon Cooper"
redis 127.0.0.1:6379> LLEN students
(integer) 2
redis 127.0.0.1:6379> LRANGE students 0 1
1) "Captain Kirk"
2) "John Doe"
redis 127.0.0.1:6379> LREM students 1 "John Doe"
(integer) 1
redis 127.0.0.1:6379> LLEN students
(integer) 1
redis 127.0.0.1:6379> LRANGE students 0 0
1) "Captain Kirk"
Redis也支持很多修改操作

redis 127.0.0.1:6379> LINSERT students BEFORE "Captain Kirk" "Dexter Morgan"
(integer) 3
redis 127.0.0.1:6379> LRANGE students 0 2
1) "Dexter Morgan"
2) "Captain Kirk"
3) "John Doe"
redis 127.0.0.1:6379> LPUSH students "Peter Parker"
(integer) 4
redis 127.0.0.1:6379> LRANGE students 0 3
1) "Peter Parker"
2) "Dexter Morgan"
3) "Captain Kirk"
4) "John Doe"
redis 127.0.0.1:6379> LTRIM students 1 3
OK
redis 127.0.0.1:6379> LLEN students
(integer) 3
redis 127.0.0.1:6379> LRANGE students 0 2
1) "Dexter Morgan"
2) "Captain Kirk"
3) "John Doe"
redis 127.0.0.1:6379> LREM students 1 "John Doe"
(integer) 1
redis 127.0.0.1:6379> LLEN students
(integer) 1
redis 127.0.0.1:6379> LRANGE students 0 1
1) "Captain Kirk"

---------------------------------------------------------------------------------
4.3 集合(Sets)类型
Redis能够将一系列不重复的值存储成一个集合

redis 127.0.0.1:6379> SADD birds crow
(integer) 1
redis 127.0.0.1:6379> SADD birds pigeon
(integer) 1
redis 127.0.0.1:6379> SADD birds bat
(integer) 1
redis 127.0.0.1:6379> SADD mammals dog
(integer) 1
redis 127.0.0.1:6379> SADD mammals cat
(integer) 1
redis 127.0.0.1:6379> SADD mammals bat
(integer) 1
redis 127.0.0.1:6379> SMEMBERS birds
1) "bat"
2) "crow"
3) "pigeon"
redis 127.0.0.1:6379> SMEMBERS mammals
1) "bat"
2) "cat"
3) "dog"
Sets结构也支持相应的修改操作

redis 127.0.0.1:6379> SREM mammals cat
(integer) 1
redis 127.0.0.1:6379> SMEMBERS mammals
1) "bat"
2) "dog"
redis 127.0.0.1:6379> SADD mammals human
(integer) 1
redis 127.0.0.1:6379> SMEMBERS mammals
1) "bat"
2) "human"
3) "dog"
Redis还支持对集合的子交并补等操作

redis 127.0.0.1:6379> SINTER birds mammals
1) "bat"
redis 127.0.0.1:6379> SUNION birds mammals
1) "crow"
2) "bat"
3) "human"
4) "pigeon"
5) "dog"
redis 127.0.0.1:6379> SDIFF birds mammals
1) "crow"
2) "pigeon"
---------------------------------------------------------------------------------

4.4 有序集合(Sorted Sets)类型
Sorted Sets和Sets结构相似,不同的是存在Sorted Sets中的数据会有一个score属性,并会在写入时就按这个score排好序。

redis 127.0.0.1:6379> ZADD days 0 mon
(integer) 1
redis 127.0.0.1:6379> ZADD days 1 tue
(integer) 1
redis 127.0.0.1:6379> ZADD days 2 wed
(integer) 1
redis 127.0.0.1:6379> ZADD days 3 thu
(integer) 1
redis 127.0.0.1:6379> ZADD days 4 fri
(integer) 1
redis 127.0.0.1:6379> ZADD days 5 sat
(integer) 1
redis 127.0.0.1:6379> ZADD days 6 sun
(integer) 1
redis 127.0.0.1:6379> ZCARD days
(integer) 7
redis 127.0.0.1:6379> ZRANGE days 0 6
1) "mon"
2) "tue"
3) "wed"
4) "thu"
5) "fri"
6) "sat"
7) "sun"
redis 127.0.0.1:6379> ZSCORE days sat
"5"
redis 127.0.0.1:6379> ZCOUNT days 3 6
(integer) 4
redis 127.0.0.1:6379> ZRANGEBYSCORE days 3 6
1) "thu"
2) "fri"
3) "sat"
4) "sun"
---------------------------------------------------------------------------------

4.5 Hash类型
Redis能够存储key对多个属性的数据(比如user1.uname user1.passwd)

redis 127.0.0.1:6379> HKEYS student
1) "name"
2) "age"
3) "sex"
redis 127.0.0.1:6379> HVALS student
1) "Ganesh"
2) "30"
3) "Male"
redis 127.0.0.1:6379> HGETALL student
1) "name"
2) "Ganesh"
3) "age"
4) "30"
5) "sex"
6) "Male"
redis 127.0.0.1:6379> HDEL student sex
(integer) 1
redis 127.0.0.1:6379> HGETALL student
1) "name"
2) "Ganesh"
3) "age"
4) "30"
Hash数据结构能够批量修改和获取


redis 127.0.0.1:6379> HMSET kid name Akshi age 2 sex Female
OK
redis 127.0.0.1:6379> HMGET kid name age sex
1) "Akshi"
2) "2"
3) "Female"
3.Publish/Subscribe
Redis支持这样一种特性,你可以将数据推到某个信息管道中,然后其它人可以通过订阅这些管道来获取推送过来的信息。
---------------------------------------------------------------------------------
5.订阅信息管道
用一个客户端订阅管道

redis 127.0.0.1:6379> SUBSCRIBE channelone
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channelone"
3) (integer) 1
另一个客户端往这个管道推送信息


redis 127.0.0.1:6379> PUBLISH channelone hello
(integer) 1
redis 127.0.0.1:6379> PUBLISH channelone world
(integer) 1
然后第一个客户端就能获取到推送的信息


redis 127.0.0.1:6379> SUBSCRIBE channelone
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channelone"
3) (integer) 1
1) "message"
2) "channelone"
3) "hello"
1) "message"
2) "channelone"
3) "world"


 按一定模式批量订阅
用下面的命令订阅所有channel开头的信息通道

redis 127.0.0.1:6379> PSUBSCRIBE channel*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel*"
3) (integer) 1
在另一个客户端对两个推送信息


redis 127.0.0.1:6379> PUBLISH channelone hello
(integer) 1
redis 127.0.0.1:6379> PUBLISH channeltwo world
(integer) 1
然后在第一个客户端就能收到推送的信息


redis 127.0.0.1:6379> PSUBSCRIBE channel*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel*"
3) (integer) 1
1) "pmessage"
2) "channel*"
3) "channelone"
4) "hello"
1) "pmessage"
2) "channel*"
3) "channeltwo"
4) "world"

6.数据过期设置
Redis支持按key设置过期时间,过期后值将被删除(在客户端看来是补删除了的)用TTL命令可以获取某个key值的过期时间(-1表示永不过期)

redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> TTL name
(integer) -1
下面命令先用EXISTS命令查看key值是否存在,然后设置了5秒的过期时间


redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> EXISTS name
(integer) 1
redis 127.0.0.1:6379> EXPIRE name 5
(integer) 1
5秒后再查看


redis 127.0.0.1:6379> EXISTS name
(integer) 0
redis 127.0.0.1:6379> GET name
(nil)
这个值已经没有了。


上在是直接设置多少秒后过期,你也可以设置在某个时间点过期,下面例子是设置2011-09-24 00:40:00过期

redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> EXPIREAT name 1316805000
(integer) 1
redis 127.0.0.1:6379> EXISTS name
(integer) 0

7.事务性
Redis本身支持一些简单的组合型的命令,比如以NX结尾命令都是判断在这个值没有时才进行某个命令。

redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> SETNX name "Dexter Morgan"
(integer) 0
redis 127.0.0.1:6379> GET name
"John Doe"
redis 127.0.0.1:6379> GETSET name "Dexter Morgan"
"John Doe"
redis 127.0.0.1:6379> GET name
"Dexter Morgan"
当然,Redis还支持自定义的命令组合,通过MULTI和EXEC,将几个命令组合起来执行


redis 127.0.0.1:6379> SET counter 0
OK
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> INCR counter
QUEUED
redis 127.0.0.1:6379> INCR counter
QUEUED
redis 127.0.0.1:6379> INCR counter
QUEUED
redis 127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) 3
redis 127.0.0.1:6379> GET counter
"3"
你还可以用DICARD命令来中断执行中的命令序列


redis 127.0.0.1:6379> SET newcounter 0
OK
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> INCR newcounter
QUEUED
redis 127.0.0.1:6379> INCR newcounter
QUEUED
redis 127.0.0.1:6379> INCR newcounter
QUEUED
redis 127.0.0.1:6379> DISCARD
OK
redis 127.0.0.1:6379> GET newcounter
"0"


8.持久化
Redis的所有数据都存储在内存中,但是他也提供对这些数据的持久化。

8.1 数据快照
数据快照的原理是将整个Redis中存的所有数据遍历一遍存到一个扩展名为rdb的数据文件中。通过SAVE命令


可以调用这个过程。

redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> SAVE
OK
redis 127.0.0.1:6379> SET name "Sheldon Cooper"
OK
redis 127.0.0.1:6379> BGSAVE
Background saving started
如果你是使用的brew在Mac OSX上安全的Redis,那么rdb文件会存在如下路径


/usr/local/var/db/redis/dump.rdb

8.2 Append-Only File(追加式的操作日志记录)
Redis还支持一种追加式的操作日志记录,叫append only file,其日志文件以aof结局,我们一般各为aof文件。要开启aof日志的记录,你需要在配置文件中进行如下设置:

appendonly yes
这时候你所有的操作都会记录在aof日志文件中


redis 127.0.0.1:6379> GET name
(nil)
redis 127.0.0.1:6379> SET name "Ganesh Gunasegaran"
OK
redis 127.0.0.1:6379> EXIT


→ cat /usr/local/var/db/redis/appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$4
name
$18
Ganesh Gunasegaran


9.管理命令
Redis支持多个DB,默认是16个,你可以设置将数据存在哪一个DB中,不同DB间的数据具有隔离性。也可以在多个DB间移动数据。

redis 127.0.0.1:6379> SELECT 0
OK
redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> SELECT 1
OK
redis 127.0.0.1:6379[1]> GET name
(nil)
redis 127.0.0.1:6379[1]> SELECT 0
OK
redis 127.0.0.1:6379> MOVE name 1
(integer) 1
redis 127.0.0.1:6379> SELECT 1
OK
redis 127.0.0.1:6379[1]> GET name
"John Doe"
Redis还能进行一些如下操作,获取一些运行信息


redis 127.0.0.1:6379[1]> DBSIZE
(integer) 1
redis 127.0.0.1:6379[1]> INFO
redis_version:2.2.13
redis_git_sha1:00000000
redis_git_dirty:0
arch_bits:64
multiplexing_api:kqueue
......
Redis还支持对某个DB数据进行清除(当然清空所有数据的操作也是支持的)


redis 127.0.0.1:6379> SET name "John Doe"
OK
redis 127.0.0.1:6379> DBSIZE
(integer) 1
redis 127.0.0.1:6379> SELECT 1
OK
redis 127.0.0.1:6379[1]> SET name "Sheldon Cooper"
OK
redis 127.0.0.1:6379[1]> DBSIZE
(integer) 1
redis 127.0.0.1:6379[1]> SELECT 0
OK
redis 127.0.0.1:6379> FLUSHDB
OK
redis 127.0.0.1:6379> DBSIZE
(integer) 0
redis 127.0.0.1:6379> SELECT 1
OK
redis 127.0.0.1:6379[1]> DBSIZE
(integer) 1
redis 127.0.0.1:6379[1]> FLUSHALL
OK
redis 127.0.0.1:6379[1]> DBSIZE
(integer) 0


10.客户端
Redis的客户端很丰富,几乎所有流行的语言都有其客户端,这里就不再赘述,有兴趣的同学可以上Redis的Clients页面去查找。

---------------------------------------------------------------------------------------------------------------------------------------------------------

11.Redis高可用部署

基础的内容写完了,下面是实战的高可用搭建。

1)Redis目前高可用的架构非常多,比如:

keepalived+redis【经典的解决方案,依据keepalived脚本检测漂移VIP。】

redis cluster【官方集群解决方案,去中心化,分布式部署,每个节点持有全局元数据,但仅持有一部分数据。】

twemproxy【推特公司的软件,目前使用的不多。】

codis【芒果TV的产品,很好用,但是需要第三方的工具支持,比方Zookeeper。

2)这些架构各有优劣,今天暂且不细说这些架构,今天主要说说redis sentinel【官方解决方案】高可用架构。

sentinel中文解释哨兵,用于管理多个redis服务器,进行故障转移,详细说明见链接http://redisdoc.com/topic/sentinel.html

3)高可用部署实验

高可用方案redis主从+哨兵 浮动VIP的方案

Redis Sentinel 模式简介

Redis-Sentinel是官方推荐的高可用解决方案,当redis在做master-slave的高可用方案时,假如master宕机了,redis本身(以及其很多客户端)都没有实现自动进行主备切换,而redis-sentinel本身也是独立运行的进程,可以部署在其他与redis集群可通讯的机器中监控redis集群。

它的主要功能有一下几点

1、不时地监控redis是否按照预期良好地运行;
2、如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端);
3、能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave(如果有超过一个slave的话)中的一个来作为新的master,其它的slave节点会将它所追随的master的地址改为被提升为master的slave的新地址。
4、哨兵为客户端提供服务发现,客户端链接哨兵,哨兵提供当前master的地址然后提供服务,如果出现切换,也就是master挂了,哨兵会提供客户端一个新地址。

哨兵(sentinel)本身也是支持集群的

很显然,单个哨兵会存在自己挂掉而无法监控整个集群的问题,所以哨兵也是支持集群的,我们通常用三台哨兵机器来监控一组redis集群。



服务器环境:

1)redis服务器
192.168.56.70:6379 主库
192.168.56.71:6379 从库

192.168.56.86  VIP
2)sentinel哨兵
192.168.56.70:26379 

192.168.56.71:26379 

192.168.56.11:26379 

部署

安装

---------------------------------------------------------

1)使用jemalloc优化Nginx和MySQL内存管理

wget http://dl.fedoraproject.org/pub/epel/6/x86_64/jemalloc-3.6.0-1.el6.x86_64.rpm
rpm -ivh jemalloc-3.6.0-1.el6.x86_64.rpm

2)安装redis3.0.6版本(主从服务器上)

wget http://download.redis.io/releases/redis-3.0.6.tar.gz

tar zxvf  redis-3.0.6.tar.gz

cd redis-3.0.6/src

make test 

可能会遇到问题

1)比如报错 Test replication partial resync: ok psync。

解决方式:更改 tests/integration/replication-psync.tcl 文件:

vi tests/integration/replication-psync.tcl
因为超时的原因,把对应报错的那段代码中的 after后面的数字,从100改成 500,继续make test


2)比如报错You need tcl 8.5 or newer in order to run the Redis test
make: *** [test] Error 1

解决方式:安装软件包

 参考:http://www.linuxfromscratch.org/blfs/view/cvs/general/tcl.html

#make test

Tests ended at Sat Jul 01 21:08:21 CST 2017
all.tcl:        Total   136     Passed  120     Skipped 16      Failed  0
Sourced 0 Test Files.
Number of tests skipped for each constraint:
        8       have_gdbm
        8       have_lmdb
make[1]: Leaving directory `/usr/local/tcl8.6.6/unix/pkgs/thread2.8.0' 

没有报错,接下来make install ,成功。


问题解决成功后,cd /usr/local/redis-3.0.6/src          make && make install

--------------------------------------

总算装完了,此时我们需要用的二进制文件位于 /usr/local/redis-3.0.6/src/ 下,分别是:

(1)redis-benchmark —— 用于 Redis 性能测试
(2)redis-check-aof —— 用于检查 aof 日志的工具
(3)redis-check-dump —— 用于检查 rbd 日志的工具
(4)redis-server —— Redis 服务器进程
(5)redis-cli —— Redis 客户端进程
(6)redis-sentinel —— 软链接文件,软链接到 redis-server

-----------------------------------------------------------------------

3)redis.conf配置如下(配置在主从节点上):

 vi /etc/redis_6379.conf

daemonize yes
pidfile "/var/run/redis_6379.pid"
port 6379
tcp-backlog 65535
bind 0.0.0.0
timeout 0
tcp-keepalive 0
loglevel notice
logfile "/var/log/redis/redis_6379.log"
maxmemory 8gb
maxmemory-policy allkeys-lru
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dump.rdb"
dir "/data/redis/6379"
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
"/etc/redis_6379.conf" 40L, 891C

4)启动redis:

redis-server  /etc/redis_6379.conf

--------------------------------------------

sentinel配置(配置在sentinel三台节点上)

vim /etc/redis-sentine26379.conf

daemonize yes
port 26379
dir "/data/redis/redis_sentinels"
pidfile "/var/run/redis/sentinel26379.pid"
logfile "/data/redis/redis_sentinels/sentine26379.log"
sentinel monitor master6379 192.168.56.70 6379 2
sentinel down-after-milliseconds master6379 6000
sentinel failover-timeout master6379 18000

sentinel client-reconfig-script master6379 /opt/notify_master6379.sh (这个是调用下面的VIP脚本)


上述配置文件说明:
1. port :当前Sentinel服务运行的端口
2. dir : Sentinel服务运行时使用的临时文件夹
3.sentinel monitor master6379 192.168.56.70 6379 2 : Sentinel去监视一个名为master6379的主redis实例,这个主实例的IP地址为本机地址     192.168.56.70,端口号为6379,而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行。
4.sentinel down-after-milliseconds master6379 6000:指定了Sentinel认为Redis实例已经失效所需的毫秒数。当实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行。
5.sentinel parallel-syncs master6379 1:指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长。
6.sentinel failover-timeout master6379 18000:如果在该时间(ms)内未能完成failover操作,则认为该failover失败.
7.sentinel client-reconfig-script <master-name> <script-name>:当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。以下参数将会在调用脚本时传给脚本:<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>,目前<state>总是“failover”, <role>是“leader”或者“observer”中的一个。 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的。这个脚本应该是通用的,能被多次调用,不是针对性的。

8.sentinel can-failover master6379 yes #是否允许sentinel修改slave->master. 如为no,则只能监控,无权修改./

-----------------------------------------------------------------------------------------------------------------------------------------------

5)启动redis服务(192.168.56.70、192.168.56.71)
redis-server /etc/redis_6379.conf

6)查看redis进程
ps -ef|grep redis

初始化主从(192.168.56.71),说明自己从属于主(最好写在配置文件中)
redis-cli -p 6379 slaveof  192.168.56.70 6379  

7)查看状态

redis-cli  info 

8)启动sentinel服务(192.168.56.70、192.168.56.71、192.168.56.11)
redis-server /etc/redis-sentinel6400.conf --sentinel

9)查看redis-sentinel进程,端口26379
ps -ef|grep redis

注:如果启动不了,记得查看日志。

至此,整个高可用方案已经搭建完成。

Redis高可用架构


下面来做测试

1.关闭主库,备库切换为主,备库上的sentinel也变为主。

2.启动主动,不能自动切换回来了。

这里朋友们可能发现了,备库切换为主库,对外提供的IP地址变化了,这时我不自觉的想到了keepalived。这里说下sentinel在failover中自动调用脚本。

------------------------------------------------------------------

1)浮动VIP的脚本

vi /opt/notify_master6379.sh 
#!/bin/bash
MASTER_IP=${6}
LOCAL_IP='192.168.56.70'   #从库上配置修改为192.168.56.71
VIP='192.168.56.86'
NETMASK='24'         
INTERFACE='eth2' 
if [ ${MASTER_IP} = ${LOCAL_IP} ]; then
         /sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE}
         /sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE}
        exit 0
else
         /sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE}
        exit 0
fi
exit 1

PS:

这里大概说一下这个脚本的工作原理,sentinel在做failover的 过程中会传出6个参数,看截图最后一行,分别是<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip> 、<to-port>,其中第6个参数to-ip也就是新的master的ip,对应脚本中的MASTER_IP,下面的if判断大家应该都很了然了,如果MASTER_IP=LOCAL_IP,那就绑定VIP,反之删除VIP。

2)脚本赋权限 chmod  777 /opt/notify_master6379.sh 

3)在redis配置文件用调用脚本

4)绑定VIP到主库(192.168.56.70)
/sbin/ip addr add 192.168.56.86/24 dev eth2


有时候浮动VIP没有出现,不要着急,实在不行关闭进程,清空配置文件,重新配置一遍。

-----------------------------------------------------------------------------

最后推荐一片文章

https://dbarobin.com/2017/05/27/ha-of-redis/

http://lib.csdn.net/base/redis

https://www.cnblogs.com/kerwinC/p/6069864.html

Redis高可用架构