redis主从复制简单研究

时间:2022-06-05 05:18:55
配置前先看一下官方对于一些错误的建议:

he TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

这个警告大概是说somaxconn的值128设置过小,从/proc/sys/net/core/somaxconn这个路径也可大概知道这个值的设置是关于网络连接中某个最大值的限定设置,此值表示网络连接的队列大小,在配置文件redis.conf中的“tcp-backlog 511”就配置在高并发环境下的最大队列大小,此值受限于系统的somaxconn与tcp_max_syn_backlog这两个值,所以应该把这两个内核参数值调大,具体解决方法如下:

$ vim /etc/sysctl.conf
$ net.core.somaxconn = 20480  #最大队列长度,应付突发的大并发连接请求,默认为128
$ net.ipv4.tcp_max_syn_backlog = 20480  #半连接队列长度,此值受限于内存大小,默认为1024
$ sysctl -p  #使参数生效


WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

警告:过量使用内存设置为0!在低内存环境下,后台保存可能失败。为了修正这个问题,
请在/etc/sysctl.conf 添加一项 ‘vm.overcommit_memory = 1‘ ,
然后重启(或者运行命令‘sysctl vm.overcommit_memory=1‘ )使其生效。


vm.overcommit_memory不同的值说明:
0 表示检查是否有足够的内存可用,如果是,允许分配;如果内存不够,拒绝该请求,并返回一个错误给应用程序。
1 允许分配超出物理内存加上交换内存的请求
2 内核总是返回true
redis的数据回写机制分为两种

同步回写即SAVE命令。redis主进程直接写数据到磁盘。当数据量大时,这个命令将阻塞,响应时间长
异步回写即BGSAVE命令。redis 主进程fork一个子进程,复制主进程的内存并通过子进程回写数据到磁盘。
由于RDB文件写的时候fork一个子进程。相当于复制了一个内存镜像。当时系统的内存是4G,而redis占用了
近3G的内存,因此肯定会报内存无法分配。如果 「vm.overcommit_memory」设置为0,在可用内存不足的情况
下,就无法分配新的内存。如果 「vm.overcommit_memory」设置为1。 那么redis将使用交换内存。

$ vim /etc/sysctl
$ vm.overcommit_memory = 1  #末尾追加
$ sysctl -p  #参数生效

或者
[root@redis ~]# echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
[root@redis ~]# sysctl -p


注:使用交换内存并不是一个完美的方案。最好的办法是扩大物理内存。

3291:S 28 Sep 14:22:44.479 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

`Transparent Huge Pages (THP)`告警,这是一个关于透明内存巨页的话题。简单来说内存可管理的最小
单位是page,一个page通常是4kb,那1M内存就会有256个page,CPU通过内置的内存管理单元管理page表
记录。Huge Pages就是表示page的大小已超过4kb了,一般是2M到1G,它的出现主要是为了管理超大内存。
个人理解上TB的内存。而THP就是管理Huge Pages的一个抽象层次,根据一些资料显示THP会导致内存锁
影响性能,所以一般建议关闭此功能。
   “/sys/kernel/mm/transparent_hugepage/enabled”有三个值,如下:

 $ cat /sys/kernel/mm/transparent_hugepage/enabled
 
    always [madvise] never
    ####
    # always 尽量使用透明内存,扫描内存,有512个 4k页面可以整合,就整合成一个2M的页面
    # never 关闭,不使用透明内存
    # madvise 避免改变内存占用

$ vim /etc/rc.local
$ echo never > /sys/kernel/mm/transparent_hugepage/enabled  #在开机脚本里追加此命令


错误:Error condition on socket for SYNC: Connection refused

bind拒绝,添加从服务相应ip即可。

如果报错:host lost rule 等则:

关闭防火墙或者在防火墙规则中放开6379端口的访问,建议生产环境为后者

错误:Error reply to PING from master: ‘-DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients.

protected mode 设为no,或者把主服务器的redis配置中的密码验证添加上,建议为后者即:

. 权限认证密码
      主配置文件:
        # vi /usr/local/redis/conf/redis.conf
          port 6379
          requirepass redis  //打开密码 并设置为redis    ---记得设置密码后连接时要加入密码才行

      从配置文件:
        # vi /usr/local/redis/conf/redis.conf
          port 6379
          slaveof 192.168.56.10 6379  设置需要拷贝的主服务器的ip 和 端口
          masterauth redis            设置主服务器设置的密码

          requirepass redis  # 如果还有从服务器来拷贝这个从服务器(也就是这个从当一个主时)则需要设置这个,否则不需要。(这句话有待验证)--------------注意:从库需要配置本身的密码验证,还需要配置连接到主库的密码验证masterauth


一般性的错误也是上面几个没有设置好导致的。


然后说说集群中容易出现的错误:

1,    //无论是主还是从或者是集群服务器请都确保能够使用ip连接,也就是说使用./redis-cli -h 58.25.94.24 是能够连接上的
    //而不是只能使用./redis-cli -h 127.0.0.1  ,这个需要的配置是redis.conf中的bind段,添加上ip。

2,    //当开启了集群后如果在从或者主服务器使用info查看信息时提示:DENIED Redis is running in protected mode,这个需要配置sentinel.conf文件,加入protected-mode no 这一句才行,如下例:

    port 26379
    # sentinel announce-ip <ip>
    # sentinel announce-port <port>
    dir /tmp
    protected-mode no
    ################################# master001 #################################
    sentinel monitor master001 192.168.110.101 6379 2
    # sentinel auth-pass <master-name> <password>
    sentinel down-after-milliseconds master001 30000
    sentinel parallel-syncs master001 1
    sentinel failover-timeout master001 180000

   3,在集群中的服务器的protected-mode 建议都为no ,或者就麻烦一些都加入密码。而bind段都屏蔽或者就依次加入需要的ip地址


  4,如果主从服务器redis版本不一致可能出现:


4695:S 29 Sep 19:13:45.897 # Can't handle RDB format version 8
4695:S 29 Sep 19:13:45.897 # Failed trying to load the MASTER synchronization DB from disk
4695:S 29 Sep 19:13:46.870 * Connecting to MASTER 192.168.1.168:6379
4695:S 29 Sep 19:13:46.870 * MASTER <-> SLAVE sync started
4695:S 29 Sep 19:13:46.872 * Non blocking connect for SYNC fired the event.
4695:S 29 Sep 19:13:46.874 * Master replied to PING, replication can continue...
4695:S 29 Sep 19:13:46.878 * Partial resynchronization not possible (no cached master)
4695:S 29 Sep 19:13:46.882 * Full resync from master: 5be7c520f9469b2ae9f473330adbf38ea123569f:500897
4695:S 29 Sep 19:13:46.918 * MASTER <-> SLAVE sync: receiving 296 bytes from master
4695:S 29 Sep 19:13:46.919 * MASTER <-> SLAVE sync: Flushing old data
4695:S 29 Sep 19:13:46.919 * MASTER <-> SLAVE sync: Loading DB in memory
4695:S 29 Sep 19:13:46.919 # Can't handle RDB format version 8
4695:S 29 Sep 19:13:46.919 # Failed trying to load the MASTER synchronization DB from disk
4695:S 29 Sep 19:13:47.879 * Connecting to MASTER 192.168.1.168:6379

这种向上兼容不容易处理,所以务必保证版本一致



一,主服务的配置

只是简单开启主从服务的话,主服务上需要配置的东西比较少

一般也就是加上权限认证或者关闭protected_mode或者修改bind等等,根据需求来即可。


二,从服务的配置

打开slaveof ,并添加上主服务器的ip 和 端口


其实redis 的主从复制就是这么简单,,如果配置成功了可以输入info 命令查看:

# Replication
role:slave
master_host:192.168.1.154
master_port:6379
master_link_status:up

当从节点中replication段中的master_link_status的值为up时说明主从通信成功,可以进行主从复制

主节点的replication显示为:

# Replication

role:master
connected_slaves:1      --从服务的数量
slave0:ip=192.168.1.205,port=6379,state=online,offset=6281,lag=0
master_repl_offset:6281
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:6280


配置sentinel集群并启动

1.创建sentinel.conf配置文件
  1. port26379
  2. # sentinel announce-ip <ip>
  3. # sentinel announce-port <port>
  4. dir/tmp

  5. ################################# master001 #################################
  6. sentinel monitor master001192.168.110.10163792
  7. # sentinel auth-pass <master-name> <password>
  8. sentinel down-after-milliseconds master00130000
  9. sentinel parallel-syncs master0011
  10. sentinel failover-timeout master001180000
  11. # sentinel notification-script <master-name> <script-path>
  12. # sentinel client-reconfig-script <master-name> <script-path>

  13. # 可以配置多个master节点
  14. ################################# master002 #################################
配置文件说明:
1. port :当前 Sentinel服务运行的端口
 
2. dir :  Sentinel服务运行时使用的临时文件夹
 
3.sentinel monitor master001192.168.110.1016379 2 : Sentinel去监视一个名为 master001 的主redis实例,这个主实例的IP地址为本机地址 192.168 . 110.101 ,端口号为 6379 ,而将这个主实例判断为失效至少需要 2 个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行
 
4.sentinel down-after-milliseconds master001 30000 : 指定了Sentinel认为Redis实例已经失效所需的毫秒数。 当实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行
 
5.sentinel parallel-syncs master001 1 指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
 
6.sentinel failover-timeout master001 180000 如果在该时间(ms)内未能完成failover操作,则认为该failover失败
 
7.sentinel notification-script <master-name> <script-path> 指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,但是很常用
2.启动 sentinel集群
创建3个sentinel.conf配置文件: sentinel001.conf、 sentinel002.conf、 sentinel003.conf并修改端口号分别为: 26379 36379 46379 ,并启动服务:
  1. ./redis-sentinel sentinel001.conf
  2. ./redis-sentinel sentinel002.conf
  3. ./redis-sentinel sentinel003.conf
启动三个 sentinel 服务后会在其控制台看到如下信息:
./ redis - sentinel sentinel001 . conf ,端口: 26379
  1. [7743]01Oct06:20:38.162#
    Sentinel runid is ba6c42e1accc31290e11d5876275e1562564295d
  2. [7743]01Oct06:20:38.162# +monitor master master001 192.168.110.101 6379 quorum 2
  3. [7743]01Oct06:20:39.110*+slave slave 192.168.110.102:6379192.168.110.1026379@ master001 192.168.110.1016379
  4. [7743]01Oct06:20:39.111*+slave slave 192.168.110.103:6379192.168.110.1036379@ master001 192.168.110.1016379
  5. [7743]01Oct06:25:07.595*+sentinel sentinel 192.168.110.100:36379192.168.110.10036379@ master001 192.168.110.1016379
  6. [7743]01Oct06:26:11.170*+sentinel sentinel 192.168.110.100:46379192.168.110.10046379@ master001 192.168.110.1016379
./ redis - sentinel sentinel002 . conf ,端口: 36379
  1. [7795]01Oct06:25:05.538#
    Sentinel runid is 52c14768b15837fb601b26328acf150c6bd30682
  2. [7795]01Oct06:25:05.538# +monitor master master001 192.168.110.101 6379 quorum 2
  3. [7795]01Oct06:25:06.505*+slave slave 192.168.110.102:6379192.168.110.1026379@ master001 192.168.110.1016379
  4. [7795]01Oct06:25:06.515*+slave slave 192.168.110.103:6379192.168.110.1036379@ master001 192.168.110.1016379
  5. [7795]01Oct06:25:07.557*+sentinel sentinel 192.168.110.100:26379192.168.110.10026379@ master001 192.168.110.1016379
  6. [7795]01Oct06:26:11.168*+sentinel sentinel 192.168.110.100:46379192.168.110.10046379@ master001 192.168.110.1016379
./ redis - sentinel sentinel003 . conf ,端口: 46379
  1. [7828]01Oct06:26:09.076#
    Sentinel runid is c8509594be4a36660b2122b3b81f4f74060c9b04
  2. [7828]01Oct06:26:09.076# +monitor master master001 192.168.110.101 6379 quorum 2
  3. [7828]01Oct06:26:10.063*+slave slave 192.168.110.102:6379192.168.110.1026379@ master001 192.168.110.1016379
  4. [7828]01Oct06:26:10.071*+slave slave 192.168.110.103:6379192.168.110.1036379@ master001 192.168.110.1016379
  5. [7828]01Oct06:26:11.516*+sentinel sentinel 192.168.110.100:26379192.168.110.10026379@ master001 192.168.110.1016379
  6. [7828]01Oct06:26:11.674*+sentinel sentinel 192.168.110.100:36379192.168.110.10036379@ master001 192.168.110.1016379
每个sentinel服务能知道其他所有的服务!

4.测试sentinel集群

1.停止192.168.110.101主节点
停止192.168.110.101Redis主节点后,在查看 Replication 信息如下:
  1. [wch@localhost bin]$./redis-cli-h192.168.110.101
    info
    Replication
  2. Could not connect toRedis at192.168.110.101:6379:Connection refused

  3. [wch@localhost bin]$./redis-cli-h192.168.110.102 infoReplication
  4. # Replication
  5. role:slave
  6. master_host:192.168.110.103
  7. master_port:6379
  8. master_link_status:up
  9. master_last_io_seconds_ago:1
  10. master_sync_in_progress:0
  11. slave_repl_offset:29128
  12. slave_priority:100
  13. slave_read_only:1
  14. connected_slaves:0
  15. master_repl_offset:0
  16. repl_backlog_active:0
  17. repl_backlog_size:1048576
  18. repl_backlog_first_byte_offset:0
  19. repl_backlog_histlen:0

  20. [wch@localhost bin]$./redis-cli-h192.168.110.103 infoReplication
  21. # Replication
  22. role:master
  23. connected_slaves:1
  24. slave0:ip=192.168.110.102,port=6379,state=online,offset=30456,lag=1
  25. master_repl_offset:30456
  26. repl_backlog_active:1
  27. repl_backlog_size:1048576
  28. repl_backlog_first_byte_offset:2
  29. repl_backlog_histlen:30455
  30. [wch@localhost bin]$
发现 192.168.110.101Redis主节点已经不能连接, 192.168 . 110.103 成了主节点!
2.再启动 192.168.110.101主节点
再启动192.168.110.101Redis主节点后,在查看 Replication 信息如下:
  1. ### 启动脚本,仍然使用默认配置
  2. [wch@localhost bin]$./redis-server

  3. [wch@localhost bin]$./redis-cli-h192.168.110.101 infoReplication
  4. # Replication
  5. role:slave
  6. master_host:192.168.110.103
  7. master_port:6379
  8. master_link_status:up
  9. master_last_io_seconds_ago:1
  10. master_sync_in_progress:0
  11. slave_repl_offset:57657
  12. slave_priority:100
  13. slave_read_only:1
  14. connected_slaves:0
  15. master_repl_offset:0
  16. repl_backlog_active:0
  17. repl_backlog_size:1048576
  18. repl_backlog_first_byte_offset:0
  19. repl_backlog_histlen:0
  20.  
  21. [wch@localhost bin]$./redis-cli-h192.168.110.102 infoReplication
  22. # Replication
  23. role:slave
  24. master_host:192.168.110.103
  25. master_port:6379
  26. master_link_status:up
  27. master_last_io_seconds_ago:0
  28. master_sync_in_progress:0
  29. slave_repl_offset:60751
  30. slave_priority:100
  31. slave_read_only:1
  32. connected_slaves:0
  33. master_repl_offset:0
  34. repl_backlog_active:0
  35. repl_backlog_size:1048576
  36. repl_backlog_first_byte_offset:0
  37. repl_backlog_histlen:0
  38.  
  39. [wch@localhost bin]$./redis-cli-h192.168.110.103 infoReplication
  40. # Replication
  41. role:master
  42. connected_slaves:2
  43. slave0:ip=192.168.110.102,port=6379,state=online,offset=63247,lag=1
  44. slave1:ip=192.168.110.101,port=6379,state=online,offset=63247,lag=1
  45. master_repl_offset:63393
  46. repl_backlog_active:1
  47. repl_backlog_size:1048576
  48. repl_backlog_first_byte_offset:2
  49. repl_backlog_histlen:63392
  50. [wch@localhost bin]$
发现 192.168 . 110.101 节点启动后还再集群中,只不过成了从节点, 192.168 . 110.103 仍然是主节点,但是现在又有两个从节点了!
3.只留下一个sentinel服务,再停止192.168.110.103主节点,查看Redis集群是否出现新的主节点
停止sentinel服务, 只留下一个sentinel服务,再停止Redis主节点, 查看 Replication 信息如下:
  1. [wch@localhost bin]$./redis-cli-h192.168.110.101
    info
    Replication
  2. # Replication
  3. role:slave
  4. master_host:192.168.110.103
  5. master_port:6379
  6. master_link_status:down
  7. master_last_io_seconds_ago:-1
  8. master_sync_in_progress:0
  9. slave_repl_offset:184231
  10. master_link_down_since_seconds:43
  11. slave_priority:100
  12. slave_read_only:1
  13. connected_slaves:0
  14. master_repl_offset:0
  15. repl_backlog_active:0
  16. repl_backlog_size:1048576
  17. repl_backlog_first_byte_offset:0
  18. repl_backlog_histlen:0

  19. [wch@localhost bin]$./redis-cli-h192.168.110.102 infoReplication
  20. # Replication
  21. role:slave
  22. master_host:192.168.110.103
  23. master_port:6379
  24. master_link_status:down
  25. master_last_io_seconds_ago:-1
  26. master_sync_in_progress:0
  27. slave_repl_offset:184231
  28. master_link_down_since_seconds:52
  29. slave_priority:100
  30. slave_read_only:1
  31. connected_slaves:0
  32. master_repl_offset:0
  33. repl_backlog_active:0
  34. repl_backlog_size:1048576
  35. repl_backlog_first_byte_offset:0
  36. repl_backlog_histlen:0

  37. [wch@localhost bin]$./redis-cli-h192.168.110.103 infoReplication
  38. Could not connect toRedis at192.168.110.103:6379:Connection refused
发现 192.168 . 110.103 主节点已经不能连接了,也 不存在Redis主节点,集群中无主节点了!!!分析原因是:sentinel.conf 配置的 sentinel monitor master001 192.168 . 110.101 6379 2 最后一个参数是2导致,当节点此配置的最后一个参数使用1则可以成功。(此原因我已证实)
注意: 在生产环境下建议 sentinel节点的数量能在3个以上,并且最好不要在同一台机器上(使用同一网卡)。