Sentinel的客户端
如果要做到应用程序(客户端)对Redis的failover透明Transparent),客户端需要监控sentinel的频道信息,并自动连接新的主节点。官方提供了一个专门的topic来讲解这个问题:Guidelines for Redis clients with support for Redis Sentinel,而一些常用的开发语言也已经有了整合sentinel的redis driver:
Python:Redis
Java:Jedis
这里以Python为例,首先安装redis-py。
1 |
$ pip install redis |
简单连接
1 2 3 4 5 6 |
>>> import redis >>> r = redis.StrictRedis(host='localhost', port=6379, db=0) >>> r.set('foo', 'bar') True >>> r.get('foo') 'bar' |
哨兵支持
1 2 3 4 5 6 |
>>> from redis.sentinel import Sentinel >>> sentinel = Sentinel([('127.0.0.1', 26379),('127.0.0.1', 26380)], socket_timeout=0.1) >>> sentinel.discover_master('mymaster') ('127.0.0.1', 6379) >>> sentinel.discover_slaves('mymaster') [('127.0.0.1', 6380)] |
然后可以从Sentinel实例创建Redis客户端连接,可以连接到Redis Master(用于写入操作)或Redis Slave(用于只读操作)。
1 2 3 4 5 |
>>> master = sentinel.master_for('mymaster', socket_timeout=0.1) >>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1) >>> master.set('foo', 'bar') >>> slave.get('foo') 'bar' |
如果Redis有密码,在这里需要改成这样:
1 |
master = sentinel.master_for('mymaster', socket_timeout=0.1, password='12345') |
master对象和slave对象是正常的StrictRedis实例,其连接池绑定到Sentinel实例。当Sentinel支持的客户端尝试建立连接时,它首先查询Sentinel服务器以确定要连接的适当主机。如果没有找到服务器,则会引发MasterNotFoundError或SlaveNotFoundError,这两个异常都是ConnectionError的子类。当尝试连接到从站客户端时,Sentinel连接池将遍历从站列表,直到找到可以连接的从站。如果没有从站可以连接,则与主站建立连接。
下面使用Python驱动来测试Redis高可用以及Sentinel高可用,环境为一主一从两个哨兵:
1 2 3 4 5 |
$ ps aux | grep redis | grep -v grep root 13518 0.0 0.1 136936 8092 ? Sl 00:43 0:08 redis-sentinel *:26379 [sentinel] root 14065 0.0 0.1 136936 8084 pts/3 Sl 01:59 0:04 redis-sentinel *:26380 [sentinel] root 14099 0.0 0.1 138984 9760 ? Ssl 02:00 0:03 redis-server 127.0.0.1:6380 root 14280 0.0 0.0 136936 7672 ? Ssl 02:06 0:02 redis-server 127.0.0.1:6379 |
测试程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
from redis.sentinel import Sentinel import time while True: sentinel = Sentinel([('127.0.0.1', 26379),('127.0.0.1', 26380)], socket_timeout=0.1) time.sleep(0.5) print sentinel.discover_master('mymaster') print sentinel.discover_slaves('mymaster') master = sentinel.master_for('mymaster', socket_timeout=0.1) print master.set('foo', 'bar') print master.get('foo') slave = sentinel.slave_for('mymaster', socket_timeout=0.1) slave.get('foo') |
测试结果:
一、发生主从切换时,业务大概会有1-2s的中断后恢复正常。
二、当哨兵挂掉一个时(两个哨兵),业务无感知,但是是建立在主从不会切换的情况下(此时一个哨兵无法完成故障转移)。