ITPub博客

首页 > 数据库 > 数据库开发技术 > Redis—听说你速度跟甲斗一样快?——主从复制

Redis—听说你速度跟甲斗一样快?——主从复制

原创 数据库开发技术 作者:咸鱼运维杂谈 时间:2022-08-18 09:46:00 0 删除 编辑
前言


现如今,Redis变得越来越流行,在很多业务场景都使用到了Redis。那么在一些高并发、大流量的业务场景里,Redis是如何高效、稳定地提供服务呢?


现在假设你有一台Redis来对外提供服务,架构如下:


Redis负责缓存后端数据库的数据以及用户的写数据,由于Redis的数据都是运行在内存中,所以大大提高了业务的性能


刚开始你的业务流量不算很大,随着时间的推移,你的Redis里的数据越来越多,突然有一天,你的Redis宕机了,这时前端所有的流量都会打到后端的数据库上,这会导致你的数据库压力剧增,严重的话还对压垮数据库


这时你该怎么办,可能你想的是重启Redis不就行了,但是Redis的数据都是在内存中的,重启之后就什么都没了;这时你可能想到文章上篇介绍到的数据持久化机制,通过将内存中的数据持久化到磁盘里,避免了Redis因某些故障导致的数据丢失


但是在恢复数据这段时间里,你的业务很有可能还是会收到影响,有没有更好的方法呢?


一台Redis宕机,只能通过恢复数据来解决,那我们是不是可以部署多个Redis,然后让它们保持数据同步,这样当其中一台Redis宕机时,我们再重新挑选一台Redis继续提供服务就好了


这个方法就是下面我要将的Redis第一个架构——主从复制





主从复制



在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复和负载均衡等需求。


Redis也是如此,它为我们提供了复制功能,实现了相同数据的多个Redis副本。 


复制功能是高可用Redis 的基础,后面章节的哨兵和集群都是在复制的基础上实现高可用的


优点


保障数据安全,实现高可用


防止单点故障的问题出现


适用于高并发的业务场景


缺点


数据的复制是单向的,只能由主节点(master)到从节点(slave),简单理解就是从节点(slave)只支持读操作,不允许写操作


当主节点(master)出现问题时,Redis便不能提供服务,需要人工干预,将从节点(slave)提升为主节点(master)


由于只有一台master提供服务,当有大量的写操作发生时,容易出现性能瓶颈,而且master的存储能力也是有限的


主从节点数据复制同步方式


全量同步


一般在slave初始化阶段,这时slave需要将master上的所有数据都复制一份


步骤如下:

1.slave连接master,发送PSYNC命令 


2.master收到PSYNC命令之后开始执行BGSAVE命令生成RDB快照,在生成过程中使用缓冲区来记录此后执行 的所有写命令 


3.master执行完BGSAVE后,向slave发送快照文件,并在发送期间继续记录被执行的写命令 


4.slave收到快照文件后丢弃所有旧数据,载入收到的快照 


5.master快照发送完毕后开始向slave发送缓冲区中的写命令 


6.slave载入快照后,开始接收命令请求,并执行来自master缓冲区的写命令


增量同步


一般在slave初始化后开始正常工作时master将发生的写操作同步到从服务器的过程


增量复制的过程主要是master每执行一个写命令就会向slave发送相同的写命令,slave接收并执行收到的写命令


一般同步策略


主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。

当然,如果有需要,slave在任何时候都可以发起全量同步 

redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求slave进行全量同步


增量同步其实是以全量同步为基础(得到复制ID),用复制积压缓冲区中的缓存命令做命令重放的增量同步逻辑,不过受制于复制积压缓冲区的容量,它可容忍的范围是有限的。这与持久化机制的AOF混合持久化如出一辙,也与mysql中主从复制的Binlog思路不谋而合


部署



master配置


vim /etc/redis/redis.confbind 0.0.0.0protected-mode noport 6379tcp-backlog 511timeout 0tcp-keepalive 300daemonize yessupervised systemdpidfile "/var/run/redis.pid"loglevel noticelogfile "/var/log/redis/redis.log"databases 16save 900 1save 300 10save 60 10000stop-writes-on-bgsave-error yesrdbcompression yesrdbchecksum yesdbfilename "dump.rdb"dir "/var/lib/redis"slave-serve-stale-data yesslave-read-only yesrepl-diskless-sync norepl-diskless-sync-delay 5repl-disable-tcp-nodelay noslave-priority 100


slave1配置


vim /etc/redis/redis.confbind 0.0.0.0protected-mode noport 6379tcp-backlog 511timeout 0tcp-keepalive 300daemonize yessupervised systemdpidfile "/var/run/redis.pid"loglevel noticelogfile "/var/log/redis/redis.log"databases 16save 900 1save 300 10save 60 10000stop-writes-on-bgsave-error yesrdbcompression yesrdbchecksum yesdbfilename "dump.rdb"dir "/var/lib/redis"slave-serve-stale-data yesslave-read-only yesrepl-diskless-sync norepl-diskless-sync-delay 5repl-disable-tcp-nodelay noslave-priority 100appendonly noappendfilename "appendonly.aof"appendfsync everysecno-appendfsync-on-rewrite noauto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mbaof-load-truncated yeslua-time-limit 5000slowlog-log-slower-than 10000slowlog-max-len 128latency-monitor-threshold 0notify-keyspace-events ""hash-max-ziplist-entries 512hash-max-ziplist-value 64list-max-ziplist-size -2list-compress-depth 0set-max-intset-entries 512zset-max-ziplist-entries 128zset-max-ziplist-value 64hll-sparse-max-bytes 3000activerehashing yesclient-output-buffer-limit normal 0 0 0client-output-buffer-limit slave 256mb 64mb 60client-output-buffer-limit pubsub 32mb 8mb 60hz 10aof-rewrite-incremental-fsync yesslaveof 192.168.149.128 6379


slave2配置


vim /etc/redis/redis.confbind 0.0.0.0protected-mode noport 6379tcp-backlog 511timeout 0tcp-keepalive 300daemonize yessupervised systemdpidfile "/var/run/redis.pid"loglevel noticelogfile "/var/log/redis/redis.log"databases 16save 900 1save 300 10save 60 10000stop-writes-on-bgsave-error yesrdbcompression yesrdbchecksum yesdbfilename "dump.rdb"dir "/var/lib/redis"slave-serve-stale-data yesslave-read-only yesrepl-diskless-sync norepl-diskless-sync-delay 5repl-disable-tcp-nodelay noslave-priority 100appendonly noappendfilename "appendonly.aof"appendfsync everysecno-appendfsync-on-rewrite noauto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mbaof-load-truncated yeslua-time-limit 5000slowlog-log-slower-than 10000slowlog-max-len 128latency-monitor-threshold 0notify-keyspace-events ""hash-max-ziplist-entries 512hash-max-ziplist-value 64list-max-ziplist-size -2list-compress-depth 0set-max-intset-entries 512zset-max-ziplist-entries 128zset-max-ziplist-value 64hll-sparse-max-bytes 3000activerehashing yesclient-output-buffer-limit normal 0 0 0client-output-buffer-limit slave 256mb 64mb 60client-output-buffer-limit pubsub 32mb 8mb 60hz 10aof-rewrite-incremental-fsync yesslaveof 192.168.149.128 6379


配置文件字段解读(挑重点)


## 默认yes,开启之后保护你的redis实例,只能本地使用,外网不允许连接和操作protected-mode no
## 是否以守护进程方式启动daemonize yes
## no:开机不会自启动;systemed:开机自启动supervised systemd
## RDB持久化配置save 900 1save 300 10save 60 10000stop-writes-on-bgsave-error yes ## 当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据rdbcompression yes ## 对于存储到磁盘中的快照,可以设置是否进行压缩存储rdbchecksum yes ## 在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验
## salve配置,指定哪台服务器是masterslaveof 192.168.149.128 6379
## 默认redis使用的是rdb方式持久化appendonly no


三台服务器配置之后我们开启redis服务


systemctl start redis-server


我们验证一下,我们在master上登陆redis查看下主从信息


[root@master ~]# redis-cli -p 6379127.0.0.1:6379> info Replication# Replicationrole:masterconnected_slaves:2slave0:ip=192.168.149.129,port=6379,state=online,offset=169,lag=0slave1:ip=192.168.149.130,port=6379,state=online,offset=169,lag=0master_repl_offset:169repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:2repl_backlog_histlen:168


可以看到master下有两台slave,分别是192.168.149.129、192.168.149.130


我们随便登上一台slave的Redis查看一下


[root@slave1 ~]# redis-cli -p 6379127.0.0.1:6379> info replication# Replicationrole:slavemaster_host:192.168.149.128master_port:6379master_link_status:upmaster_last_io_seconds_ago:1master_sync_in_progress:0slave_repl_offset:267slave_priority:100slave_read_only:1connected_slaves:0master_repl_offset:0repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0


我们在master上进行写操作,观察slave有没有同步数据


# master操作192.168.149.128:6379> set name pythonOK192.168.149.128:6379> get name"python"
# slave同步数据192.168.149.129:6379> get name"python"
192.168.149.130:6379> get name"python"


我们需要注意的是,slave只能读数据,不能写数据


192.168.149.130:6379> set name1 java(error) READONLY You can't write against a read only slave.



原文作者:咸鱼运维杂谈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
最新的技术文章首先发布在微信公众号:咸鱼运维杂谈 擅长Linux系统维护、开源软件维护、自动化运维等领域,博客主要偏向于学习笔记及经历分享

注册时间:2021-05-29

  • 博文量
    193
  • 访问量
    84244