在之前的blog中,介绍过redis分布式锁实现。在日程的工作中,redis也使用得非常频繁,包括缓存,分布式锁,消息队列等。本系列将系统性地对redis做一个完整的介绍和总结。
Redis服务安装和远程访问
Redis安装网上教程很多,这里就不介绍了。
安装好之后可通过redis-server启动,通过客户端redis-cli进行访问,默认使用6379端口(本文环境为ubuntu+redis3.0.6)。
如果要在远程访问redis服务器,则需要在启动的时候指定redis.conf配置文件,并修改redis配置文件参数。将下行注释掉:
# bind 127.0.0.1
如果不注释,从远程访问时会报错:
Could not connect to Redis at ip:6379: Connection refused。
从而只能在本地访问。
注释掉绑定ip后,通过ps -ef | grep redis
找到服务进程,通过kill -9 [pid]
杀死服务进程并重启服务(如果开启了守护进程,则杀死之后就会重启,可通过/etc/init.d/redis-server stop来停止)。此时可远程访问redis服务器了。
可通过info命令来查看redis服务器相关信息,如下图所示:
输入config get requirepass
可看到结果为:
此时,redis服务器是没有密码的。这种情况存在着安全隐患,即未授权登录。无需认证即可访问到内部数据,可导致敏感信息泄露,也可以恶意执行flushall来清空所有数据。
因此为了保证安全,通常会设置登录密码:
通过config set requirepass [password]
可以设置临时密码。设置成功后再进行任何操作都会提示:
(error) NOAUTH Authentication required.
可通过auth [password]
进行认证。
但这种设置方式在服务器重启之后无效,要想使密码认证一直有效,同样需要修改redis.conf配置文件:
并重启服务。
Redis集群
Redis有三种集群模式,分别是主从模式,哨兵(Sentinel)模式和集群(Cluster)模式。
主从模式(Master-Slave)
主从模式比较简单,跟mysql的主从模式类似,由一个主节点和多个从节点组成。主节点提供写能力,从节点提供读能力。主从模式的问题在于:master节点在主从模式中唯一,若master挂掉,则redis无法对外提供写服务。
部署
主节点ip:10.241.149.44,端口6379。
从节点ip:本机。端口分别为6381和6382。
现有本机目录/usr/local/redis-node/6381和/usr/local/redis-node/6382。将redis.conf分别拷贝到这两个目录。修改6381下的配置文件:
port 6381
...
masterauth xxx # 主节点开启了密码,则需要配置。见上文
...
slaveof 10.241.149.44 6379 # 配置主从模式
类似地修改6382下的配置文件。
最后,启动两个从节点:
redis-server /usr/local/redis-node/6381/redis.conf
redis-server /usr/local/redis-node/6382/redis.conf
连接上主节点:
redis-cli -h 10.241.149.44 -p 6379
写入:10.241.149.44:6379> set user howe
成功
连接上从节点:redis-cli -p 6381
读取user:
127.0.0.1:6381> get user
"howe"
说明主节点上的数据同步到了从节点。
如果此时在从节点上写入,就会提示:
(error) READONLY You can't write against a read only slave.
哨兵模式(Sentinel)
主从模式的弊端就是不具备高可用性,当master挂掉以后,Redis将不能再对外提供写入操作,因此sentinel应运而生。
Sentinel中文含义为哨兵,顾名思义,它的作用就是监控redis集群的运行状况。当发现主节点挂掉以后,它会选举一个从节点升级为主节点,并让其他从节点从这个新的主节点进行数据同步。
sentinel因为也是一个进程,有挂掉的可能,所以sentinel也会启动多个形成一个sentinel集群。
当使用sentinel模式的时候,客户端不要直接连接Redis,而是连接sentinel,由sentinel来提供具体的可提供服务的Redis实现,这样当master节点挂掉以后,sentinel就会感知并将新的master节点提供给使用者。
部署
在主从模式已搭建的基础上,可以进一步搭建哨兵模式。
redis主节点为10.241.149.44:6379,两个从节点为本机:10.234.209.24:6381, 10.234.209.24:6382。
将两个从节点的配置文件中的bind 127.0.0.1改成bind 0.0.0.0,以便远程客户端能够访问。
同时,哨兵模式下从节点可能会切换为主节点,因此从节点和主节点地位同等,配置需要保持一致,将两个从节点的requirepass打开。
假设现有本地目录:
/usr/local/redis-sentinel。在该目录下创建s1,s2,s3,然后将sentinel.conf分别拷贝至s1,s2,s3下。Sentinel.conf初始内容如下:
port 26379
dir /tmp
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
# 主节点别名,ip,端口,确认master失效的哨兵数
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
修改s1的sentinel配置文件:
添加:
daemonize yes
logfile “/usr/local/redis-sentinel/s1.log”
修改监听的主节点为:
sentinel monitor mymaster 10.241.149.44 6379 2
如果主节点开启了密码,则还需添加密码认证:
sentinel auth-pass mymaster <password>
其余参数保持不变。
同理修改s2,s3的sentinel配置文件。
以指定配置文件的方式启动三个哨兵:
redis-sentinel /usr/local/redis-sentinel/s1/sentinel.conf
redis-sentinel /usr/local/redis-sentinel/s2/sentinel.conf
redis-sentinel /usr/local/redis-sentinel/s3/sentinel.conf
这里将三个哨兵放到同一台机器上,实际上为了避免单点故障,通常哨兵是部署在不同的机器上的。
现在kill掉主节点的redis服务进程。打开s1.log,可以看到进行了故障迁移:
说明如下:
*****s1节点哨兵端口为26379,监听另外两个哨兵节点26380和26381,监听主节点10.241.149.44 6379*****
10343:X 23 Apr 16:08:38.511 * +sentinel sentinel 10.234.209.24:26380 10.234.209.24 26380 @ mymaster 10.241.149.44 6379
10343:X 23 Apr 16:08:41.549 * +sentinel sentinel 10.234.209.24:26381 10.234.209.24 26381 @ mymaster 10.241.149.44 6379
*****监听到redis主节点下线*****
10343:X 23 Apr 16:10:40.093 # +sdown master mymaster 10.241.149.44 6379
*****选举一个新的redis主节点*****
10343:X 23 Apr 16:10:40.236 # +new-epoch 1
10343:X 23 Apr 16:10:40.242 # +vote-for-leader 9528d63b865c3fb8773c8ac6cfb52cb0a702f3e5 1
*****三个哨兵投票,满足2个确认的条件,认为redis主节点确实已下线*****
10343:X 23 Apr 16:10:41.186 # +odown master mymaster 10.241.149.44 6379 #quorum 3/2
10343:X 23 Apr 16:10:41.186 # Next failover delay: I will not start a failover before Thu Apr 23 16:16:40 2020
*****更新哨兵配置文件*****
10343:X 23 Apr 16:10:41.337 # +config-update-from sentinel 10.234.209.24:26380 10.234.209.24 26380 @ mymaster 10.241.149.44 6379
*****切换redis主节点为6382节点(原来的两个从节点之一)*****
10343:X 23 Apr 16:10:41.338 # +switch-master mymaster 10.241.149.44 6379 10.234.209.24 6382
10343:X 23 Apr 16:10:41.338 * +slave slave 10.234.209.24:6381 10.234.209.24 6381 @ mymaster 10.234.209.24 6382
10343:X 23 Apr 16:10:41.338 * +slave slave 10.241.149.44:6379 10.241.149.44 6379 @ mymaster 10.234.209.24 6382
*****此时,原redis主节点切换成了从节点,并且是下线状态*****
10343:X 23 Apr 16:11:11.397 # +sdown slave 10.241.149.44:6379 10.241.149.44 6379 @ mymaster 10.234.209.24 6382
查看s2.log和s3.log,大体过程都差不多。
此时打开s1节点的sentinel.conf配置文件可以发现,监听的主节点自动更新为:
sentinel monitor mymaster 10.234.209.24 6382 2
s2和s3的配置文件也是一样的被自动更新了。
再启动原来的主节点10.241.149.44:6379,发现s1.log多了一行日志:
10343:X 23 Apr 16:55:53.487 # -sdown slave 10.241.149.44:6379 10.241.149.44 6379 @ mymaster 10.234.209.24 6382
说明此时这个节点是作为从节点重新上线。
sentinel操作
连接上任意一个哨兵:
redis-cli -p 26379
查看主节点状态:
查看从节点状态:sentinel slaves mymaster
代码连接
在哨兵模式下,主节点和从节点是动态变化的,其状态有哨兵群管理。因此客户端连接redis服务器时,需要通过哨兵进行连接。
配置如下:
[redis]
host = 10.234.209.24:26379,10.234.209.24:26380,10.234.209.24:26381
pass = root
timeout = 100
代码示例:
import settings
from redis.sentinel import Sentinel
sentinels = []
host_list = settings.get('redis', 'host').split(",")
for host in host_list:
ip = host.split(":")[0]
port = host.split(":")[1]
sentinels.append((ip, port))
sentinel = Sentinel(sentinels=sentinels)
service_name = "mymaster"
redis_master = sentinel.master_for(service_name=service_name, password=settings.get('redis', 'pass'))
redis_slave = sentinel.slave_for(service_name=service_name, password=settings.get('redis', 'pass'))
redis_master.set("user", "test") # 主节点写入
print redis_slave.get("user") # 从节点读取
分片集群模式(Cluster)
Redis的sentinel哨兵模式虽然可以解决Redis单点故障的问题,但是一主多从的结构必然会导致客户端写入数据只能在Master节点上操作,当写入量特别大的时候主节点压力就会很大。
Redis从3.0版本之后提供了cluster集群模式,解决了这个问题。但是集群分布式不一定好,分布式集群的客户端性能一般会低一些,flush、mget、keys等命令也不能跨节点使用,客户端的维护也更复杂,所以业务能在哨兵下满足需求尽量用哨兵模式。
这里就不详细介绍分片集群模式了,可自行在网上搜索。
下一篇将介绍redis支持的数据结构,持久化方式和过期策略。
参考资料
[1].https://www.jianshu.com/p/897dcc654613
[2].https://blog.csdn.net/truelove12358/article/details/79612954