设为首页 收藏本站
查看: 1023|回复: 0

[经验分享] 金庸武功之“独孤九剑”--redis一主三从配置

[复制链接]

尚未签到

发表于 2018-11-3 07:17:49 | 显示全部楼层 |阅读模式
  redis-server说明
  服务器A:192.168.1.131:8000(主)
  服务器B:192.168.1.135:8000
  服务器C:192.168.1.231:8000
  服务器D:192.168.1.241:8000
  redis-sentinel说明
  服务器A:192.168.1.131:6800
  服务器B:192.168.1.135:6800
  服务器C:192.168.1.231:6800
  服务器D:192.168.1.241:6800
  2.搭建redis系统
  yum  install  -y  gcc*  tcl
  首先下载安装redis
  cd /usr/local
  wget http://download.redis.io/releases/redis-3.2.11.tar.gz
  tar zxvf redis-3.2.11.tar.gz
  mv redis-3.2.11  redis
  cd redis
  make && make install
  如果编译安装过程中,出现报错:
  zmalloc.h:51:31: error: jemalloc/jemalloc.h: No such file or directory
  原因:一些编译依赖或原来编译遗留出现的问题
  解决方案:make distclean 清理一下,然后再make
  或者直接  make MALLOC=libc  && make install
  [root@localhost redis]# cd src
  [root@localhost src]#  cp redis-server redis-cli redis-check-aof redis-check-rdb redis-sentinel redis-trib.rb /usr/local/bin/
  [root@localhost src]# mkdir /etc/redis
  [root@localhost src]# mkdir /var/redis
  [root@localhost src]# mkdir  /var/redis/{log,run,redis}
  [root@localhost src]  cd ..
  [root@localhost redis]#  cp redis.conf /etc/redis/redis.conf
  [root@localhost redis]#  vi  /etc/redis/redis.conf
  修改如下:
  port  8000           #修改端口是安全的第一步
  daemonize  yes
  bind  0.0.0.0
  pidfile    /var/run/redis-8000.pid
  logfile    /var/redis/log/redis_8000.log
  dir /var/redis/redis             //工作目录,dump文件所在目录
  slaveof  192.168.1.131  8000    #从redis比主redis多这一行
  ########################################################
  redis默认的持久化方式是RDB,数据写入到dump文件中。如果要启用AOF持久化,就在redis.conf文件中配置如下:
  appendonly yes         #启用AOF持久化方式
  appendfilename "appendonly.aof"       #AOF文件的名称,默认为appendonly.aof
  # appendfsync always        #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。
  appendfsync everysec        #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。
  # appendfsync no         #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。
  ########################################################
  [root@localhost redis]#  redis-server /etc/redis/redis.conf
  设置开机启动
  [root@dev ~]# echo "/usr/local/bin/redis-server /etc/redis/redis.conf" >> /etc/rc.local
  关闭redis服务
  [root@dev ~]# redis-cli shutdown //默认是6379端口
  如果端口变化可以指定端口
  [root@dev ~]# redis-cli -p 8000 shutdown
  ########################################################
  还可以通过如下方法,设置redis服务启动脚本及开机自启动
  将redis解压包下utils下redis启动脚本redis_init_script拷贝至/etc/init.d/,并修改脚本名称(也可不修改)为redis
  [root@dev ~]# cp /usr/local/src/redis-stable/utils/redis_init_script /etc/init.d/redis
  [root@dev ~]# chmod +x /etc/init.d/redis
  修改脚本pid及conf路径为实际路径
  [root@dev ~]# vim /etc/init.d/redis
  ......
  REDISPORT=6379
  EXEC=/usr/local/bin/redis-server
  CLIEXEC=/usr/local/bin/redis-cli
  PIDFILE=/var/redis/run/redis_6379.pid
  CONF="/etc/redis/redis.conf"
  ......
  这样,就可以直接用下面的命令关闭和启动redis服务了
  [root@dev ~]# /etc/init.d/redis stop
  Stopping ...
  Redis stopped
  [root@dev ~]# lsof -i:6379
  [root@dev ~]# /etc/init.d/redis start
  Starting Redis server...
  [root@dev ~]# lsof -i:6379

  COMMAND PID USER FD TYPE DEVICE>  redis-ser 9372 root 4u IPv4 58648940 0t0 TCP localhost:6379 (LISTEN)
  设置自启动
  [root@dev ~]# chkconfig redis on
  redis 服务不支持 chkconfig
  这是因为没有在启动脚本/etc/init.d/redis里加入redis启动优先级信息,可添加如下红色字体的两行:
  [root@dev ~]# vim /etc/init.d/redis
  #!/bin/sh
  #
  # chkconfig: 2345 90 10                                                     //注意:后面的英文空格
  # description: Redis is a persistent key-value database          //注意:后面的英文空格
  # Simple Redis init.d script conceived to work on Linux systems
  # as it does use of the /proc filesystem.
  REDISPORT=6379
  EXEC=/usr/local/bin/redis-server
  CLIEXEC=/usr/local/bin/redis-cli
  PIDFILE=/var/redis/run/redis_6379.pid
  CONF="/etc/redis/redis.conf"
  .......
  [root@dev ~]# chkconfig redis on
  [root@dev ~]# chkconfig --list|grep redis
  redis 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭
  ########################################################
  验证:
  在A服务器(主)
  [root@localhost ~]#   redis-cli -h 192.168.1.131 -p 8000 info replication
  [root@localhost ~]#    redis-cli -h 192.168.1.131 -p 8000 info replication
  # Replication
  role:master
  connected_slaves:3
  slave0:ip=192.168.1.231,port=8000,state=online,offset=462,lag=0
  slave1:ip=192.168.1.241,port=8000,state=online,offset=462,lag=1
  slave2:ip=192.168.1.135,port=8000,state=online,offset=462,lag=1
  master_repl_offset:462
  repl_backlog_active:1
  repl_backlog_size:1048576
  repl_backlog_first_byte_offset:2
  repl_backlog_histlen:461
  #############################################################################
  [root@localhost ~]#   redis-cli -h 192.168.1.131 -p 8000
  [root@localhost ~]#   192.168.1.131:8000> get name thb      (主,1.131)
  [root@localhost redis]# redis-cli -h 192.168.1.135 -p 8000      (从。1.135)
  192.168.1.135:8000> get name
  "thb"
  192.168.1.135:8000>
  ############################################################################
  配置哨兵sentinel
  [root@localhost redis]#  cd /usr/local/redis
  [root@localhost redis]#  mkdir /etc/sentinel
  [root@localhost redis]#  cp -a sentinel.conf /etc/sentinel
  [root@localhost redis]#   vi /etc/sentinel/sentinel.conf   (之前的都删掉,就保留下面的内容)
  bind  0.0.0.0
  daemonize yes
  port  6800
  logfile  /var/log/sentinel.log
  pidfile  /var/run/sentinel.pid
  sentinel monitor master8000 192.168.1.131 8000 2
  #5秒内master6800没有响应,就认为SDOWN
  sentinel down-after-milliseconds master8000 5000
  sentinel failover-timeout  master8000 15000
  [root@localhost redis]#  redis-sentinel  /etc/sentinel/sentinel.conf
  [root@localhost redis]#  echo "/usr/local/bin/redis-sentinel /etc/sentinel/sentinel.conf" >> /etc/rc.local
  四个redis-sentinel服务启动完毕后,连接任意sentinel服务可以获知当前主redis服务信息
  [root@localhost ~]# redis-cli -h 192.168.1.131 -p 6800 info sentinel
  # Sentinel
  sentinel_masters:1
  sentinel_tilt:0
  sentinel_running_scripts:0
  sentinel_scripts_queue_length:0
  sentinel_simulate_failure_flags:0
  master0:name=master8000,status=ok,address=192.168.1.131:8000,slaves=3,sentinels=3
  测试
  1.把主redis停掉
  [root@localhost ~]# redis-cli -h 192.168.1.131 -p 8000 shutdown
  [root@localhost ~]# netstat -ntpl
  Active Internet connections (only servers)
  Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
  tcp        0      0 0.0.0.0:58566               0.0.0.0:*                   LISTEN      1235/rpc.statd
  tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      1213/rpcbind
  tcp        0      0 0.0.0.0:6800                0.0.0.0:*                   LISTEN      1685/redis-sentinel
  tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1447/sshd
  tcp        0      0 127.0.0.1:631               0.0.0.0:*                   LISTEN      1290/cupsd
  tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      1526/master
  tcp        0      0 :::111                      :::*                        LISTEN      1213/rpcbind
  tcp        0      0 :::52913                    :::*                        LISTEN      1235/rpc.statd
  tcp        0      0 :::22                       :::*                        LISTEN      1447/sshd
  tcp        0      0 ::1:631                     :::*                        LISTEN      1290/cupsd
  tcp        0      0 ::1:25                      :::*                        LISTEN      1526/master
  2.查看redis-sentinel的监控状态
  [root@localhost ~]# redis-cli -h 192.168.1.131 -p 6800 info sentinel
  # Sentinel
  sentinel_masters:1
  sentinel_tilt:0
  sentinel_running_scripts:0
  sentinel_scripts_queue_length:0
  sentinel_simulate_failure_flags:0
  master0:name=master8000,status=ok,address=192.168.1.231:8000,slaves=3,sentinels=6
  发现231这台redis-server提升为主库。
  在1.231 这台上查看
  [root@session1 ~]# redis-cli -h 192.168.1.231 -p 8000 info replication
  # Replication
  role:master
  connected_slaves:2
  slave0:ip=192.168.1.241,port=8000,state=online,offset=36416,lag=1
  slave1:ip=192.168.1.135,port=8000,state=online,offset=36558,lag=0
  master_repl_offset:36842
  repl_backlog_active:1
  repl_backlog_size:1048576
  repl_backlog_first_byte_offset:2
  repl_backlog_histlen:36841
  发现role已经是master了
  至此,redis的高可用方案已经搭建完成。
  六、客户端程序
  客户端程序(如PHP程序)连接redis时需要ip和port,但redis-server进行故障转移时,主redis是变化的,所以ip地址也是变化的。客户端程序如何感知当前主redis的ip地址和端口呢?redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name 就能得到当前主redis的ip和port。
  [root@localhost ~]# redis-cli -h 192.168.1.131 -p 6800
  192.168.1.131:6800> sentinel get-master-addr-by-name master8000
  1) "192.168.1.231"
  2) "8000"
  192.168.1.131:6800>
  获取当前主redis的ip和port
  客户端每次连接redis前,先向sentinel发送请求,获得主redis的ip和port,然后用返回的ip和port连接redis。
  这种方法的缺点是显而易见的,每次操作redis至少需要发送两次连接请求,第一次请求sentinel,第二次请求redis。
  php请求sentinel程序代码可参见:https://github.com/huyanping/redis-sentinel
  更好的办法是使用VIP,当然这对配置的环境有一定的要求,比如redis搭建在阿里云服务器上,可能不支持VIP。
  VIP方案是,redis系统对外始终是同一ip地址,当redis进行故障转移时,需要做的是将VIP从之前的redis服务器漂移到现在新的主redis服务器上。
  比如:当前redis系统中主redis的ip地址是192.168.56.101,那么VIP(192.168.56.250)指向192.168.56.101,客户端程序用VIP(192.168.56.250)地址连接redis,实际上连接的就是当前主redis,这样就避免了向sentinel发送请求。
  当主redis宕机,进行故障转移时,192.168.56.102这台服务器上的redis提升为主,这时VIP(192.168.56.250)指向192.168.56.102,这样客户端程序不需要修改任何代码,连接的是192.168.56.102这台主redis。

  VIP指向192.168.1.131

  故障转移后,VIP漂移指向192.168.1.231
  七、漂移VIP
  那么现在的问题是,如何在进行redis故障转移时,将VIP漂移到新的主redis服务器上。
  这里可以使用redis sentinel的一个参数client-reconfig-script,这个参数配置执行脚本,sentinel在做failover的时候会执行这个脚本,并且传递6个参数、 、 、 、 、  、,其中是新主redis的IP地址,可以在这个脚本里做VIP漂移操作。
  sentinel client-reconfig-script master8000   /opt/notify_master6800.sh
  修改三个服务器的redis-sentinel配置文件/etc/sentinel.conf,增加上面一行。然后在/opt/目录下创建notify_master6800.sh脚本文件,这个脚本做VIP漂移操作,内容如下:
  #notify_master6800.sh脚本内容
  #!/bin/bash
  MASTER_IP=$6  #第六个参数是新主redis的ip地址
  LOCAL_IP='192.168.1.231'  #其他三个服务器上为192.168.1.131,192.168.56.135,192.168.1.241
  VIP='192.168.1.251'
  NETMASK='24'
  INTERFACE='eth0'
  if [ ${MASTER_IP} = ${LOCAL_IP} ];then
  /sbin/ip  addr  add ${VIP}/${NETMASK}  dev ${INTERFACE}  #将VIP绑定到该服务器上
  /sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE}
  exit 0
  else
  /sbin/ip  addr del  ${VIP}/${NETMASK}  dev ${INTERFACE}   #将VIP从该服务器上删除
  exit 0
  fi
  exit 1  #如果返回1,sentinel会一直执行这个脚本
  现在当前主redis是192.168.1.231,需要手动绑定VIP到该服务器上。
  /sbin/ip  addr add 192.168.1.251/24 dev eth0
  /sbin/arping -q   -c 3 -A 192.168.1.251 -I eth0
  然后,去另一个服务器上通过VIP地址连接redis-server和redis-sentinel。
  [root@localhost opt]# ifconfig
  eth0      Link encap:Ethernet  HWaddr 00:0C:29:34:43:27
  inet addr:192.168.1.131  Bcast:192.168.1.255  Mask:255.255.255.0
  inet6 addr: fe80::20c:29ff:fe34:4327/64 Scope:Link
  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
  RX packets:3830849 errors:0 dropped:0 overruns:0 frame:0
  TX packets:3406249 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1000
  RX bytes:444297730 (423.7 MiB)  TX bytes:416136987 (396.8 MiB)
  [root@localhost opt]# redis-cli -h 192.168.1.251 -p 8000 info replication
  # Replication
  role:master
  connected_slaves:3
  slave0:ip=192.168.1.241,port=8000,state=online,offset=18468111,lag=1
  slave1:ip=192.168.1.135,port=8000,state=online,offset=18468111,lag=0
  slave2:ip=192.168.1.131,port=8000,state=online,offset=18468111,lag=0
  master_repl_offset:18468111
  repl_backlog_active:1
  repl_backlog_size:1048576
  repl_backlog_first_byte_offset:17419536
  [root@localhost opt]# redis-cli -h 192.168.1.251 -p 6800 info sentinel
  # Sentinel
  sentinel_masters:1
  sentinel_tilt:0
  sentinel_running_scripts:0
  sentinel_scripts_queue_length:0
  sentinel_simulate_failure_flags:0
  master0:name=master8000,status=ok,address=192.168.1.231:8000,slaves=3,sentinels=4
  通过VIP连接redis
  从上面也可以看出当前主redis是192.168.1.231。
  下面关闭这台redis服务,看看VIP是否漂移到另一台服务器上。
  [root@session1 opt]# redis-cli -h 192.168.1.231 -p 8000 shutdown
  [root@session1 opt]# redis-cli -h 192.168.1.231 -p 6800 info sentinel
  # Sentinel
  sentinel_masters:1
  sentinel_tilt:0
  sentinel_running_scripts:0
  sentinel_scripts_queue_length:0
  sentinel_simulate_failure_flags:0
  master0:name=master8000,status=ok,address=192.168.1.135:8000,slaves=3,sentinels=4
  [root@localhost opt]# redis-cli -h 192.168.1.251 -p 6800 info sentinel
  # Sentinel
  sentinel_masters:1
  sentinel_tilt:0
  sentinel_running_scripts:0
  sentinel_scripts_queue_length:0
  sentinel_simulate_failure_flags:0
  master0:name=master8000,status=ok,address=192.168.1.135:8000,slaves=3,sentinels=4
  通过访问VIP连接redis,发现VIP确实指向了192.168.1.135。
  这里要注意脚本里的ip和网卡名称(eth)不能错,要不飘移不成功。
  八、总结
  通过上面的操作,使用redis主从 + 哨兵(sentinel)+ 漂移VIP的方案搭建了一个redis高可用系统,但这个系统保证的是单个redis实例的高可用,所以适合业务比较小的应用。如果业务比较大,并发量比较高,建议搭建redis集群,比如官方redis cluster,还有开源的codings集群。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-629995-1-1.html 上篇帖子: Redis 数据结构与内存管理策略(下) 下篇帖子: redis--基本用法(1)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表