1、介绍
读写分离适用于大量的访问场景,且写操作小于读操作的情况。由主服务器进行数据的写入,数据的读取由从服务器完成。主从服务器之间的的数据同步通过发布订阅机制完成。当主服务器被写入数据时,就会发布订阅把数据统一同步到从的服务器上,数据保存一致。发送者(pub)发送消息,订阅者(sub)接受消息。Redis 客户端可以订阅任意数量的频道。
发布订阅的原理:Redis通过subscribe命令订阅频道后,redis-server里维护一个字典,字典的键就是一个个频道,而值则是一个链表,链表中保存了所有订阅这个channel的客户端。publish命令则向订阅者发送消息,redis-server会使用给定的频道作为键,在维护的channel中查找记录了订阅这个频道的所有客户端的链表,遍历这个链表,将消息发送给所有订阅者。
2、特点:
(1)透明兼容
读写分离和普通集群规格一样,都使用了redis-proxy做请求转发,多分片令使用存在一定的限制,但从主从升级单分片读写分离,或者从集群升级到多分片的读写分离集群可以做到完全兼容。
用户和redis-proxy建立连接,redis-proxy会识别出客户端连接发送过来的请求是读还是写,然后按照权重作负载均衡,将请求转发到后端不同的DB节点中,写请求转发给master,读操作转发给read-only replica(master默认也提供读,可以通过权重控制)。
用户只需要购买读写分离规格的实例,直接使用任何客户端即可直接使用,业务不用做任何修改就可以开始享受读写分离服务带来的巨大性能提升,接入成本几乎为0。
(2)高可用
高可用模块(HA)监控所有DB节点的健康状态,为整个实例的可用性保驾护航。master宕机时自动切换到新主。如果某个read-only replica宕机,HA也能及时感知,然后重搭一个新的read-only replica,下线宕机节点。
除HA之外,redis-proxy也能实时感知每个read-only replica的状态。在某个read-only replica异常期间,redis-proxy会自动降低这个节点的权重,如果发现某个read-only replica连续失败超过一定次数以后,会暂时屏蔽异常节点,直到异常消失以后才会恢复其正常权重。
redis-proxy和HA一起做到尽量减少业务对后端异常的感知,提高服务可用性
(3)高性能
对于读多写少的业务场景,直接使用集群版本往往不是最合适的方案,现在读写分离提供了更多的选择,业务可以根据场景选择最适合的规格,充分利用每一个read-only replica的资源。
3、使用案例
如上图所示,搭建一个读写分离的场景
(1)创建目录
(2)拷贝配置文件redis.conf
(3)给配置文件重新命名,并修改配置文件信息。
设置一个通用的redis-common.con配置文件
(4)新建三个配置文件,redis-6379.conf充当主服务器的配置文件,redis-6380.conf和redis-6381.conf充当两个从节点的配置文件。
redis-6379.conf配置文件的内容:
#引用公共配置
include /opt/redis/conf/redis-common.conf
#进程编号文件
pidfile /var/run/redis-6379.pid
#进程端口号
port 6379
#日志记录文件
logfile "/opt/redis/log/redis-6379.conf"
#数据记录文件
dbfilename dump-6379.rdb
#追加文件名称
appendfilename "appendonly-6379.aof"
#主节点master不需要配置此信息,表示从节点从属于6379
#slaveof 192.168.172.132 6379
redis-6380.conf配置文件的内容:
#引用公共配置
include /opt/redis/conf/redis-common.conf
#进程编号文件
pidfile /var/run/redis-6380.pid
#进程端口号
port 6380
#日志记录文件
logfile "/opt/redis/log/redis-6380.conf"
#数据记录文件
dbfilename dump-6380.rdb
#追加文件名称
appendfilename "appendonly-6380.aof"
#主节点master不需要配置此信息,表示从节点从属于6379
slaveof 192.168.172.132 6379
redis-6381.conf配置文件的内容:
#引用公共配置
include /opt/redis/conf/redis-common.conf
#进程编号文件
pidfile /var/run/redis-6381.pid
#进程端口号
port 6381
#日志记录文件
logfile "/opt/redis/log/redis-6381.conf"
#数据记录文件
dbfilename dump-6381.rdb
#追加文件名称
appendfilename "appendonly-6381.aof"
#主节点master不需要配置此信息,表示从节点从属于6379
slaveof 192.168.172.132 6379
(5)启动redis服务
查看主从状态信息:
(6)启动主节点,并添加一条数据信息。
(7)启动从节点,获取主节点设置的信息
从节点尝试设置数据库信息,设置失败
4、关于读写分离的探讨
在知乎上看到有人说:redis 作为NoSQL而言,不应该具有读写分离的概念,因为读写分离是对于有磁盘IO阻塞的数据库。相对而言,所谓的读写分离仅仅是对并发量增大后的集群压力进行分担,从而将读写压力分给集群的单元节点,而不是将读写操作拆开。前面介绍redis是单线程的,因此不会存在任何的数据并发锁问题,自然也就不存在X锁和S锁的竞争,也就没必要使用读写分离。因此,如果压力大,可以考虑使用集群分布式。
有兴趣的可阿里云的的这篇文章:Redis读写分离技术解析