redis主从复制原理分析,环境搭建

redis使用异步复制,支持一主多从的主从复制架构,一个master和多个slave,默认master负责处理写请求,slave负责读请求,实现redis的读写分离和高可用。

主从复制分为全量同步和增量同步,

1.全量同步:

  1.slave服务器连接master服务器,发送sync命令。

  2.master服务器收到slave发送过来的sync命令后,开始执行BGSAVE命令在后台异步保存当前数据库的数据到磁盘,然后fork一个子进程把内存数据生成的RDB快照文件,并发送给slave服务。

  3.master在子进程生成RDB快照文件时,父进程继续接受写命令并记录在缓冲区。

  4.slave接受到RDB快照文件后,清空内存数据,读取RDB文件,重建内存数据表结构。

  5.master发送完RDB文件后,把记录在缓冲区的写命令通过1建立的连接,使用redis传输协议发送给slave服务器。

  6.slave服务完成RDB快照文件的载入后,开始接受命令请求,并执行来自master服务器缓冲区的写命令,最终达到数据的一致性。

 

2.增量同步

2.8以前的版本没有增量同步,2.8以后支持增量同步

部分同步主要包含3个部分:1、复制偏移量,2、master复制积压缓冲区 3、服务器运行ID

  偏移量:master和slave会分别维护一个偏移量,主从状态一致,偏移量相同,若偏移量不一致,主从状态不一致。

  复制积压缓冲区:master会维护一个复制积压缓冲区,是一个固定大小的FIFO队列,默认大小为1M,当队列满时会弹出最早插入的数据;master进行命令传播时会把命令放入缓冲区,缓冲区分为两部分数据:偏移量和字节。slave发送同步上报偏移量给master服务器,master检查偏移量是否还在缓冲区,存在,部分同步,否则进行全量同步。

  服务器运行ID:初次同步时,master会把ID发送给slave服务,slave保存master服务ID,断线后slave把ID发送给master,用来确定是否同一个master服务器。

以下为同步日志:

48602:M 19 Mar 16:56:58.881 * Slave 127.0.0.1:6380 asks for synchronization
48602:M 19 Mar 16:56:58.881 * Full resync requested by slave 127.0.0.1:6380
48602:M 19 Mar 16:56:58.881 * Starting BGSAVE for SYNC with target: disk
48602:M 19 Mar 16:56:58.882 * Background saving started by pid 48611
48611:C 19 Mar 16:56:58.885 * DB saved on disk
48611:C 19 Mar 16:56:58.885 * RDB: 6 MB of memory used by copy-on-write
48602:M 19 Mar 16:56:58.957 * Background saving terminated with success
48602:M 19 Mar 16:56:58.957 * Synchronization with slave 127.0.0.1:6380 succeeded

48607:S 19 Mar 16:56:58.880 * DB loaded from disk: 0.000 seconds
48607:S 19 Mar 16:56:58.880 * Ready to accept connections
48607:S 19 Mar 16:56:58.880 * Connecting to MASTER 127.0.0.1:6379
48607:S 19 Mar 16:56:58.881 * MASTER <-> SLAVE sync started
48607:S 19 Mar 16:56:58.881 * Non blocking connect for SYNC fired the event.
48607:S 19 Mar 16:56:58.881 * Master replied to PING, replication can continue...
48607:S 19 Mar 16:56:58.881 * Partial resynchronization not possible (no cached master)尝试部分同步,master没有缓存对应的偏移量
48607:S 19 Mar 16:56:58.883 * Full resync from master: 736e8967ad54cf568e1f6d618b11973fda77cb73:0 全量同步
48607:S 19 Mar 16:56:58.957 * MASTER <-> SLAVE sync: receiving 175 bytes from master
48607:S 19 Mar 16:56:58.957 * MASTER <-> SLAVE sync: Flushing old data
48607:S 19 Mar 16:56:58.957 * MASTER <-> SLAVE sync: Loading DB in memory
48607:S 19 Mar 16:56:58.957 * MASTER <-> SLAVE sync: Finished with success

53849:S 20 Mar 16:15:47.581 * DB loaded from disk: 0.000 seconds
53849:S 20 Mar 16:15:47.581 * Before turning into a slave, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
53849:S 20 Mar 16:15:47.581 * Ready to accept connections
53849:S 20 Mar 16:15:47.581 * Connecting to MASTER 127.0.0.1:6379
53849:S 20 Mar 16:15:47.582 * MASTER <-> SLAVE sync started
53849:S 20 Mar 16:15:47.582 * Non blocking connect for SYNC fired the event.
53849:S 20 Mar 16:15:47.582 * Master replied to PING, replication can continue...
53849:S 20 Mar 16:15:47.582 * Trying a partial resynchronization (request fcd0a9406d079593869b65c53ca03eab2989b512:26461). 尝试部分同步
53849:S 20 Mar 16:15:47.583 * Successful partial resynchronization with master. 部分同步
53849:S 20 Mar 16:15:47.583 * MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.

另:

  全量同步要求在磁盘上创建RDB快照文件,然后将RDB从磁盘加载到内存中,发送给slave服务。如果磁盘空间有限,性能很低,那么这对master是个非常有压力的操作。

此时可以通过无盘复制来达到目的,由master直接开启一个socket将rdb文件发送给slave服务器,无需使用磁盘作为中间储存介质。

 

上面讲述了redis主从复制的流程,下面进行redis的主从复制的环境搭建。

1.下载安装包:

 http://download.redis.io/releases/redis-4.0.8.tar.gz

2.解压

 tar zxvf redis-4.0.8.tar.gz

3.编译源程序

 cd /usr/local/redis-4.0.8

 make

4.单机启动三个实例,一主两从,分别是6379、6380、6381,创建conf、log、db三个目录,并拷贝redis.conf到对应的conf目录下,

修改redis.conf配置:
daemonize yes (daemo进程运行)
pidfile /usr/local/6379/redis_6379.pid
port 6379
logfile /usr/local/6379/log/redis_6379.log
dir /usr/local/6379/db

对应目录下改成对应端口即可,从需要添加配置slaveof 127.0.0.1 6379

5.启动
cd /usr/local/redis-4.0.8/src
./redis-server /usr/local/6379/conf/redis.conf &
./redis-server /usr/local/6380/conf/redis.conf &
./redis-server /usr/local/6381/conf/redis.conf &
6.查看进程信息

  #ps-ef|grep redis

  root 48607 1 0 Mar19 ? 00:01:28 ./redis-server 127.0.0.1:6380

  root 52671 1 0 10:58 ? 00:00:31 ./redis-server 127.0.0.1:6379

  root 53849 1 0 16:15 ? 00:00:08 ./redis-server 127.0.0.1:6381

  root 54489 52445 0 19:03 pts/0 00:00:00 grep redis

 

  7.查看节点信息

  ./redis-cli -p 6379 "info"

  ./redis-cli -p 6380 "info"

  ./redis-cli -p 6381 "info"

8.master读写:

  # ./redis-cli -p 6379

  127.0.0.1:6379> set name java
  OK
  127.0.0.1:6379> get name
  "java"
  127.0.0.1:6379>

  slave读写:

  # ./redis-cli -p 6380
  127.0.0.1:6380> get name
  "java"
  127.0.0.1:6380> set sex '男'
  (error) READONLY You can't write against a read only slave.

slave设置只读,不能执行写命令

 

配置参数(redis.conf)

    daemonize:如需要在后台运行,把该项的值改为yes

  pdifile:把pid文件放在/var/run/redis.pid,可以配置到其他地址

  bind:指定redis只接收来自该IP的请求,如果不设置,那么将处理所有请求,在生产环节中最好设置该项

  port:监听端口,默认为6379

  timeout:设置客户端连接时的超时时间,单位为秒

  loglevel:等级分为4级,debug,revbose,notice和warning。生产环境下一般开启notice

  logfile:配置log文件地址,默认使用标准输出,即打印在命令行终端的端口上

  database:设置数据库的个数,默认使用的数据库是0

  save:设置redis进行数据库镜像的频率

  rdbcompression:在进行镜像备份时,是否进行压缩

  dbfilename:镜像备份文件的文件名

  dir:数据库镜像备份的文件放置的路径

  slaveof:设置该数据库为其他数据库的从数据库

  masterauth:当主数据库连接需要密码验证时,在这里设定

  requirepass:设置客户端连接后进行任何其他指定前需要使用的密码

  maxclients:限制同时连接的客户端数量

  maxmemory:设置redis能够使用的最大内存

  appendonly:开启appendonly模式后,redis会把每一次所接收到的写操作都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态

  appendfsync:设置appendonly.aof文件进行同步的频率

  vm_enabled:是否开启虚拟内存支持

  vm_swap_file:设置虚拟内存的交换文件的路径

  vm_max_momery:设置开启虚拟内存后,redis将使用的最大物理内存的大小,默认为0

  vm_page_size:设置虚拟内存页的大小

  vm_pages:设置交换文件的总的page数量

  vm_max_thrrads:设置vm IO同时使用的线程数量 

  repl-diskless-sync: 是否使用无盘复制 Diskless replication,默认是no

  slave-read-only:从2.6版本开始支持只读的slave,默认是yes的

master配置了slave,强烈建议master启用持久化。因为没有启用持久化,重启后数据会全部丢失,当slave重新连接master时,slave原有的数据也会被清空。如果真的要配置不启用持久化,最好不要设置自动启动master

 

posted on 2018-03-20 19:33  花含语  阅读(93)  评论(0编辑  收藏  举报

导航