1.为什么需要使用主从复制/读写分离

一般对于高并发的系统来说,搭建一个健壮的缓存系统是不可避免的。单机的reids的QPS可能只能上万,如果有再高并发的场景,单机是不能搞定的,就会有它的系统瓶颈。一般来说缓存是用来支撑高并发读,这时候我们可能就会想到读写分离;读写分离是用来处理读的并发量大,而写的并发量小的场景。 我们知道数据库可以通过主从复制,读写分离,以及分库分表来减轻流量的压力,可以看下这篇文章数据库主从复制,读写分离,分库分表;那么下面来简单介绍下redis主从复制和读写分离的原理。

2.replication的核心机制

1.redis采用异步方式复制数据到slave节点,不过redis 2.8开始,slave node会周期性地确认自己每次复制的数据量
2.一个master node是可以配置多个slave node;slave node也可以连 接其他的slave node
3.slave node做复制的时候,不会影响master node的正常工作;也不会影响对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务。
4.slave node主要用来进行横向扩容,读写分离,扩容的slave node可以提高读的吞吐量

3.主从复制的核心流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A0Vou9bw-1575470519113)(D:\TinkingCat\Redis\assets\1574933301359.png)]

1. slave服务器配置master的连接信息(slaveof属性);
2. slave连接上master,发送psync指令
3. master判断是否为全量复制:如果是全量复制,则进入下一步;否则可以看增量复制的子流程。
4. master启动一个后台线程,生成一份RDB快照文件,同时将从客户端收到的所有写命令缓存在内存中。
5. RDB文件生成完毕之后,master会将RDB发送给slave。
6. slave收到RDB文件之后,清空自己的旧数据,然后持久化到本地磁盘,再从本地磁盘加载到内存中。
7. 最后salve node保存了RDB文件之后,master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。
8. 如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF

增量复制子流程:如果全量复制过程中,master-slave网络连接断掉,salve重新连接master时,会触发增量复制;master直接从自己的backlog中获取部分丢失的数据,发送给slave node,默认backlog就是1MB;msater就是根据slave发送的psync中的offset来从backlog中获取数据的

断点续传:从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份

master node会在内存中常见一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制;如果没有找到对应的offset,那么就会执行一次full resynchronization。

5.Redis实现主从复制

  • 环境准备
系统环境:centos7.0
redis版本4.0.0
远程连接工具xshell
主从机器:
master:192.168.126.143
slave1:192.168.126.149
slave2:192.168.126.150
  • 下载地址
http://www.redis.cn/download.html
  • 历史版本地址
http://download.redis.io/releases
  • 下载4.0的版本
#没有wget
yum install wget
#获取安装包(其实可以使用网易镜像或者阿里镜像下载)
wget -P /usr/local/src/ http://download.redis.io/releases/redis-4.0.0.tar.gz
  • 下载、解压、编译Redis
#切换目录
cd /usr/local/src/
#查看
ls
#解压
tar -zxvf redis-4.0.0.tar.gz
#如果安装报错gcc:命令未cd 找到(因为redis基于c语言编写)
#先查看是否安装c++的编译器
yum -y install gcc-c++
#进行编译
cd redis-4.0.0
make
#如果报错 执行 make clean 后再次 执行 make
make clean
#致命错误:jemalloc/jemalloc.h:没有那个文件或目录
make MALLOC=libc
$ wget http://download.redis.io/releases/redis-4.0.0.tar.gz
$ tar xzf redis-4.0.0.tar.gz
$ cd redis-4.0.0
$ make
  • 启动redis
#启动redis服务端
./redis-server

#启动redis客户端
./redis-cli

#测试(查询所有的键)
keys *

#守护进程启动
[root@localhost redis-4.0.0]# cp redis.conf ./src/
vi redis.conf
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
#1)打开配置文件把下面对应的注释掉
bind 127.0.0.1
#2)Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程,设置为no
daemonize no
#3)保护模式
protected-mode no 
#启动
$ redis-server redis.conf
#将含有”redis”关键词的进程杀死:
$ ps -ef | grep redis | awk ‘{print $2}’ | xargs kill -9
#再次启动
./redis-server redis.conf
[root@localhost src]# ./redis-cli 
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> exit
#结束进程
[root@localhost src]# ps -ef | grep redis
root       5664   5645  0 17:08 pts/1    00:00:00 ./redis-cli
root       5734      1  0 17:28 ?        00:00:00 ./redis-server 127.0.0.1:6379
root       5766   1327  0 17:33 pts/0    00:00:00 grep --color=auto redis
[root@localhost src]# kill -9 5664
[root@localhost src]# kill -9 5734
[root@localhost src]# ps -ef | grep redis
root       5768   1327  0 17:34 pts/0    00:00:00 grep --color=auto redis
  • 主从关系配置
#关闭防火墙或者开放端口
systemctl stop firewalld
#查看防火墙状态
systemctl status firewalld
#配置主从信息
slaveof 192.168.126.143 6379
#重启服务
./redis-server redis.conf
#登录客户端
./redis-cli
#查看主从状态
info Replication