Redis实战总结-Redis的高可用性
在之前的博客《Redis实战总结-配置、持久化、复制》给出了一种Redis主从复制机制,简单地实现了Redis高可用。然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的高可用性较低。正常会采用多台Redis服务器构成一个集群,即使某台,或者某几台Redis宕机,Redis集群仍能正常运行,从而提高其高可用性。
在Redis中,主要存在两种方式实现Redis集群机制:
Redis Sentinel集群机制:在Redis2.X版本,往往都是通过这种方式实现Redis的高可用。redis-sentinel是在master-slave机制上加入监控机制哨兵Sentinel实现的。
Redis Cluster集群机制:在Redis3.0版本后推出了redis-cluster集群机制。redis-cluster集群中各个节点之间是对等的,即master-master模式。
**注意:**Redis Sentinel集群是解决HA问题的(主从同步),Redis Cluster集群是解决sharding问题的(分区),两种不重复,可以混合使用。
- Sharding机制:http://blog.csdn.net/basycia/article/details/52013098
- HA机制:https://baike.baidu.com/item/%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7(HA)/2355576
下面详解这两种集群,并给出具体的演示示例。
1. Redis Sentinel集群机制
Redis-Sentinel是在master-slave机制上加入监控机制哨兵Sentinel实现的。Sentinel主要功能就是为Redis Master-Slave集群提供:
- 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
在Sentinel集群中,一个最小的Master-Slave单元包含一个master和一个slave服务器。当master失效后,sentinel自动将slave提升为master,从而可以减少管理员的人工切换slave的操作过程。
1.1 Redis-Sentinel集群架构图
1.2 各个机器配置
部署在本地机器上,保证各个端口号不一样,具体配置如下
Redis服务器:
- master:127.0.0.1:6379
- slave01:127.0.0.1:6389
- slave02:127.0.0.1:6399
Sentinel服务器
- sentinel01:127.0.0.1:26379
- sentinel02:127.0.0.1:26389
- sentinel03:127.0.0.1:26399
1.3 redis.conf和sentinel.conf配置
redis.conf
- master特殊配置如下:
# 后台线程启动 daemonize yes # 监听端口号 port 6379 # 访问验证密码 requirepass "123456"- slave特殊配置如下:
# 后台线程启动 daemonize yes # 监听端口号,如果为slave02,端口号为6399 port 6389 # 主节点访问密码 masterauth "123456" # 访问验证密码 requirepass "123456" # 主节点服务器IP和端口号 slaveof 127.0.0.1 6379sentinel.conf
# 后台线程启动
daemonize yes
# 监听端口号,如果为sentinel02,则端口号为26389,如果为sentinel01,则端口号为26399
port 26379
#1表示在sentinel集群中只要有两个节点检测到redis主节点出故障就进行切换
sentinel monitor mymaster 127.0.0.1 6379 1
# master节点密码验证
sentinel auth-pass mymaster 123456
#如果3秒内mymaster无响应,则认为mymaster宕机了
sentinel down-after-milliseconds mymaster 3000
# 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长
sentinel parallel-syncs mymaster 1
#如果10秒后,mysater仍没活过来,则启动failover
sentinel failover-timeout mymaster 10000
注意:
- 1.如果上述涉及的所有配置均放置在同一目录下,需保证各配置名称不同;
- 2.在配置中,不同实例的日志输出、快照文件要求名称不能一样,具体可自行配置;
- 3.一定要保证”sentinel myid”不相同,否则无法进行故障转移
1.4 启动集群及启动后结果详情展示
各Redis节点启动:
redis-server redis_****.conf
各Sentinel节点启动
redis-sentinel sentinel_*****.conf
- Redis Master节点详情展示
Redis Slave节点效果截图展示
各个Sentinel节点详情展示
1.5 高可用性场景测试
- Master宕机
- sentinel使用failover机制重新选举出master
- Master恢复
- master节点恢复后,由Master变成slave
- Slave宕机
- 哨兵发现6399已经宕机,等待6399的恢复(主观下线)
- Slave重启6399节点
如果想详细了解sentinel机制的话,可以参考博客:
http://shift-alt-ctrl.iteye.com/blog/1884370
2. Redis Cluster集群机制
2.1 Redis-cluster介绍
Redis-cluster是一种服务器Sharding技术,Redis3.0以后版本正式提供支持。
Redis-cluster没有使用一致性hash,而是引入了哈希槽的概念。Redis-cluster中有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。Cluster中的每个节点负责一部分hash槽(hash slot),比如集群中存在三个节点,则可能存在的一种分配如下:
- 节点A包含0到5500号哈希槽;
- 节点B包含5501到11000号哈希槽;
- 节点C包含11001 到 16384号哈希槽。
这种集群架构很容易扩展,如果扩充一个节点D,只需要将A、B、C节点中的部分槽放置在D上;如果想移除节点A,只需要将A的slot转移到B和C节点上。由于将哈希槽从一个节点移动到另一个节点不需要停止服务,只需要通过命令直接再分配,因而上述拓展不会造成集群不可用。目前这种方式还是一种半自动的方式,需要人工介入。
2.2 Redis-Cluster主从复制
在Redis-Cluster中,如果某个节点宕机或者处在不可用状态时,那它负责的Hash槽也将失效,导致整个集群不可用。因而为了提供高可用性,正常会将每个节点配置成主从式结构,即一个master节点,挂在多个slave节点。如果Master节点失效时,集群便会选取一个slave节点作为master,继续提供服务,从而不会导致整个集群不可用。
2.3 Redis-Cluster集群模拟
2.3.1 Redis-Cluster集群准备
- 集群部署图
集群由三个节点组成,每个节点均为主从式架构。因而共需要创建6个Redis实例,分配如下:
- Redis01:127.0.0.1:7000
- Redis02:127.0.0.1:7001
- Redis03:127.0.0.1:7002
- Redis04:127.0.0.1:7003
- Redis05:127.0.0.1:7004
- Redis06:127.0.0.1:7005
对于每个实例的redis_700*.conf配置如下:
# 监听端口号
port 700*
# 开启集群
cluster-enabled yes
# 修改集群加载配置文件,不需要手动创建,启动后默认生成,并且需要时自动更新
cluster-config-file /Users/guweiyu/develop/redis/redis-cluster/workpid/nodes-7000.conf
# 集群中的节点能够失联的最大时间,超过这个时间,该节点就会被认为故障
cluster-node-timeout 15000
# 默认为“no”,表示部分Key所在的节点不可用时,集群仍然为可达节点提供服务;如果为“yes”,表示部分key所在的节点不可用时,则整个集群停止服务。注意:实际使用中要修改为"yes"
cluster-require-full-coverage no安装ruby,如果为Mac OS系统,直接执行即可:
brew install ruby
2.3.2 集群启动
启动所有Redis实例,可以编写一个启动和停止所有redis实例的脚本(start.sh,stop.sh)
redis-server redis_7000.conf
redis-server redis_7001.conf
redis-server redis_7002.conf
redis-server redis_7003.conf
redis-server redis_7004.conf
redis-server redis_7005.conf ps -ef | grep redis-server
echo "redis 7000-7005全部启动完成"redis-cli -p 7000 shutdown
redis-cli -p 7001 shutdown
redis-cli -p 7002 shutdown
redis-cli -p 7003 shutdown
redis-cli -p 7004 shutdown
redis-cli -p 7005 shutdown ps -ef | grep redis-server
echo "redis-server 7000-7005节点已全部停止"
1创建redis-cluster
Redis中创建集群是通过redis-trib.rb命令实现的,redis-trib.rb位于Redis源码的src目录下,可将其直接拷贝到当前目录下。
运行命令
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
如果出现如下错误:
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- redis (LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from ./redis-trib.rb:25:in `<main>'
这是由于没有安装redis的第三方接口导致的。因此需要给Ruby安装client包,如下(必须加上sudo执行,否则会执行失败):
sudo gem install redis
再执行创建集群命令,结果如下:
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: aab0162a039d2f224322afe6caf2e153230f2d82 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: 058204226f52757925a606b9697a8e39756bfdff 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: 857075aef280cf35cd369ebc30738cd31c05e479 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: 7dac141fa9510315905f505be52bba0208c391ab 127.0.0.1:7003
replicates aab0162a039d2f224322afe6caf2e153230f2d82
S: 65a2bc432e5930e97f0fd172eb838af9f07229b6 127.0.0.1:7004
replicates 058204226f52757925a606b9697a8e39756bfdff
S: 3d2a665d2e2eb28acb0a187c1a0b4bbce9ce87d2 127.0.0.1:7005
replicates 857075aef280cf35cd369ebc30738cd31c05e479
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: aab0162a039d2f224322afe6caf2e153230f2d82 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 3d2a665d2e2eb28acb0a187c1a0b4bbce9ce87d2 127.0.0.1:7005
slots: (0 slots) slave
replicates 857075aef280cf35cd369ebc30738cd31c05e479
S: 65a2bc432e5930e97f0fd172eb838af9f07229b6 127.0.0.1:7004
slots: (0 slots) slave
replicates 058204226f52757925a606b9697a8e39756bfdff
S: 7dac141fa9510315905f505be52bba0208c391ab 127.0.0.1:7003
slots: (0 slots) slave
replicates aab0162a039d2f224322afe6caf2e153230f2d82
M: 857075aef280cf35cd369ebc30738cd31c05e479 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 058204226f52757925a606b9697a8e39756bfdff 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
创建成功,16384个Hash槽分配完成,所有节点(Master和slave节点)均已加入到集群中。三个Master节点分配的Hash槽及从节点如下:
Master01:127.0.0.1:7000
M: aab0162a039d2f224322afe6caf2e153230f2d82
slots:0-5460 (5461 slots) master
127.0.0.1:7004 to 127.0.0.1:7000Master02:127.0.0.1:7001
M: 058204226f52757925a606b9697a8e39756bfdff
slots:5461-10922 (5462 slots) master
127.0.0.1:7005 to 127.0.0.1:7001M: 857075aef280cf35cd369ebc30738cd31c05e479
slots:10923-16383 (5461 slots) master
127.0.0.1:7003 to 127.0.0.1:7002
Master03:127.0.0.1:7002
2.3.3 集群测试
- 测试集群存取值
客户端命令redis-cli连接集群需要带上”-c”, 比如redis-cli -c -p 端口号
127.0.0.1:7000> set test1 guweiyu
OK
127.0.0.1:7000> set name guweiyu
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get name
"guweiyu"
127.0.0.1:7001> get test1
-> Redirected to slot [4768] located at 127.0.0.1:7000
"guweiyu"
127.0.0.1:7000>
测试发现”set test1 guweiyu”,直接返回OK,说明该值就是存储在7000上,执行“set name guweiyu”发生了Redirected到7001上,获取的时候,同样出现上述情况。这个是Redis Cluster去中心特性,访问集群中的任一节点,均可直接操作集群。
主节点宕机测试
从节点宕机
Redis实战总结-Redis的高可用性的更多相关文章
- Redis实战之Redis + Jedis
用Memcached,对于缓存对象大小有要求,单个对象不得大于1MB,且不支持复杂的数据类型,譬如SET 等.基于这些限制,有必要考虑Redis! 相关链接: Redis实战 Redis实战之Redi ...
- Redis实战之Redis + Jedis[转]
http://blog.csdn.net/it_man/article/details/9730605 2013-08-03 11:01 1786人阅读 评论(0) 收藏 举报 目录(?)[-] ...
- 分布式缓存技术redis学习系列(五)——redis实战(redis与spring整合,分布式锁实现)
本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...
- 分布式缓存技术redis系列(五)——redis实战(redis与spring整合,分布式锁实现)
本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...
- Redis 实战 —— 05. Redis 其他命令简介
发布与订阅 P52 Redis 实现了发布与订阅(publish/subscribe)模式,又称 pub/sub 模式(与设计模式中的观察者模式类似).订阅者负责订阅频道,发送者负责向频道发送二进制字 ...
- Redis 实战 —— 14. Redis 的 Lua 脚本编程
简介 Redis 从 2.6 版本开始引入使用 Lua 编程语言进行的服务器端脚本编程功能,这个功能可以让用户直接在 Redis 内部执行各种操作,从而达到简化代码并提高性能的作用. P248 在不编 ...
- .Net Redis实战——使用Redis构建Web应用
示例介绍 示例1:借助Redis实现购物车功能 示例2:Redis实现网页缓存和数据缓存 借助Redis实现购物车功能 每个用户的购物车都是一个散列,散列存储了商品ID与商品订购数量之间的映射.订购商 ...
- Redis实战之Redis命令
阅读目录 1. 字符串命令 2. 列表命令 3. 集合命令 4. 散列命令 5. 有序集合命令 6. 发布与订阅命令 7. 小试牛刀 Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结 ...
- Redis 实战 —— 01. Redis 数据结构简介
一些数据库和缓存服务器的特性和功能 P4 名称 类型 数据存储选项 查询类型 附加功能 Redis 使用内存存储(in-memory)的非关系数据库 字符串.列表.哈希表.集合.有序集合 每种数据类型 ...
随机推荐
- JS本地存储信息的实现方式(localStorage 与 userData)
详细介绍请看: http://www.cnblogs.com/beiyuu/archive/2011/07/20/js-localstorage-userdata.html 里面涉及到的 demo 代 ...
- delphi CreateAnonymousThread 匿名线程
引用 http://www.cnblogs.com/del/archive/2011/05/18/2049913.html 先看一个非多线程的例子, 代码执行时不能进行其它操作(譬如拖动窗体): { ...
- 使用JavaScript的数组实现数据结构中的队列与堆栈
今天在项目中要使用JavaScript实现数据结构中的队列和堆栈,这里做一下总结. 一.队列和堆栈的简单介绍 1.1.队列的基本概念 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被 ...
- libxml2.dylb 罗致<libxml/tree.h> 老是找不到头文件
libxml2.dylb 导致<libxml/tree.h> 老是找不到头文件 添加了libxml2.dylb的framework ,结果还是引用不了<libxml/tree.h&g ...
- EBS 系统当前完成请求时间监测
/* Formatted on 2018/3/14 23:32:17 (QP5 v5.256.13226.35538) */ SELECT REQUEST_ID , PROGRAM , ROUND ( ...
- WordPress主题开发:设置和获取浏览次数
将以下代码放在functions.php,一个是获取阅读量,一个是设置阅读量 <?php /** * getPostViews()函数 * 功能:获取阅读数量 * 在需要显示浏览次数的位置,调用 ...
- 工具:使用过的 API 文档生成工具
背景 2012 年之前几乎没有为代码增加注释,当然,代码的命名也不见得合理(好的代码胜过面面俱到的注释),后来接触过一些开源框架,优秀的框架都有一个特点:文档和示例非常多,在后来的日子里,几乎会强制自 ...
- 深入浅出!从语义角度分析隐藏在Unity协程背后的原理
Unity的协程使用起来比较方便,但是由于其封装和隐藏了太多细节,使其看起来比较神秘.比如协程是否是真正的异步执行?协程与线程到底是什么关系?本文将从语义角度来分析隐藏在协程背后的原理,并使用C++来 ...
- 绝命毒师第五季/全集Breaking Bad迅雷下载
本季Breaking Bad Season 5(2012)看点:故事紧接着上一季,通过一场精心策划的大爆炸,沃尔特(布莱恩·科兰斯顿 Bryan Cranston 饰)终于除掉了长久以来的威胁古斯塔沃 ...
- Xcode修改项目的Build Location
Xcode默认project通过build输出的目录,存放于目录 /Users/用户名/Library/Developer/Xcode/DerivedData/产品名称-hjwqiconnjhpjle ...