Redis 高级部分

作者: 运维开发_西瓜甜 | 来源:发表于2019-02-25 11:39 被阅读438次

    一、主从复制

    image.png

    Rdis 的主从复制特点

    image.png

    1. 配置主从

    实现方式同样有两种: 命令方式和配置文件方式

    命令方式

    只需要在从服务器上执行如下命令即可

    slaveof  主服务器的IP  端口号
    

    slaveof 命令是异步的,不阻塞。
    并且此时,从服务器现有的数据会先被清空,之后再同步主服务器的数据。

    停止一台从服务器的复制操作,在此台服务器上执行如下命令

    slaveof no   one
    

    配置文件的方式如下

    只需要在从服务器上配置即可

    修改配置文件
    假如主服务器 IP 是: 172.16.153.178
    端口是: 6379

    # slaveof <masterip> <masterport>
    slaveof  172.16.153.178 6379
    
    // 配置此服务器只提供读取操作
    slave-read-only yes
    

    之后重启从主机的 Redis 服务

    查看主从信息

    127.0.0.1:6379> info  replication
    

    二、主从 + Sentinel 哨兵模式

    Redis Sentinel是Redis官方的高可用性解决方案。

    Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

    • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

    • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

    • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

    Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

    虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器。

    此种模式下,客户端要访问的 服务 IP 不是主节点,而是 sentiner 服务器的 IP。

    架构图

    image.png

    Redis Sentinel 故障转移

    image.png

    架构的扩展应用

    image.png

    1. 配置主从

    a. 快速生成主节点的配置文件

    编译全新文件 /etc/redis/redis-6380.conf, 添加如下内容

    port 6380
    daemonize yes
    protected-mode no
    pidfile /var/run/redis-6380.pid
    logfile /var/log/redis-6380.log
    dir /redis/data/
    

    假如是多个主机实现的,就需要更改为 protected-mode yes
    并且添加 bind 0.0.0.0

    b. 快速生成从节点的配置文件

    [root@s1 ~]# sed 's/6380/6381/g' /etc/redis/redis-6380.conf > /etc/redis/redis-6381.conf
    [root@s1 ~]# sed 's/6380/6382/g' /etc/redis/redis-6380.conf > /etc/redis/redis-6382.conf
    
    
    

    查看配置文件内容,检验配置结果

    [root@s1 ~]# cat /etc/redis/redis-6381.conf
    port 6381
    daemonize yes
    pidfile /var/run/redis-6381.pid
    logfile /var/log/redis-6381.log
    dir /redis/data/
    [root@s1 ~]# cat /etc/redis/redis-6382.conf
    port 6382
    daemonize yes
    pidfile /var/run/redis-6382.pid
    logfile /var/log/redis-6382.log
    dir /redis/data/
    [root@s1 ~]#
    

    c. 配置主从关系

    [root@s1 ~]# echo "slaveof  172.16.153.178 6380" >> /etc/redis/redis-6381.conf
    [root@s1 ~]# echo "slaveof  172.16.153.178 6380" >> /etc/redis/redis-6382.conf
    [root@s1 ~]#
    
    
    

    d. 启动服务,并验证进程

    [root@s1 ~]# /usr/local/bin/redis-server /etc/redis/redis-6380.conf
    [root@s1 ~]# /usr/local/bin/redis-server /etc/redis/redis-6381.conf
    [root@s1 ~]# /usr/local/bin/redis-server /etc/redis/redis-6382.conf
    [root@s1 ~]# ps -ef |grep redis
    root       4335      1  0 19:30 ?        00:00:03 /usr/local/bin/redis-server *:6380
    root       4490      1  0 20:17 ?        00:00:00 /usr/local/bin/redis-server *:6381
    root       4495      1  0 20:17 ?        00:00:00 /usr/local/bin/redis-server *:6382
    root       4500   3755  0 20:17 pts/0    00:00:00 grep --color=auto redis
    [root@s1 ~]#
    
    
    

    假如日志中出现如下警告信息

    4668:S 17 Feb 20:28:42.107 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    4668:S 17 Feb 20:28:42.107 # Server initialized
    4668:S 17 Feb 20:28:42.108 # 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.
    4668:S 17 Feb 20:28:42.108 * DB loaded from disk: 0.000 seconds
    4668:S 17 Feb 20:28:42.110 * 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.
    
    解决办法

    The TCP backlog...
    方法1: 临时设置生效:

    shell> sysctl -w net.core.somaxconn=1024
    

    方法2: 永久生效:
    修改/etc/sysctl.conf文件,增加一行

    net.core.somaxconn=1024
    

    然后执行命令

    sysctl -p
    

    WARNING overcommit_memory ...

    方法1: 临时设置生效:

    shell> sysctl -w vm.overcommit_memory=1
    

    方法2: 永久生效:
    修改/etc/sysctl.conf文件,增加一行

    vm.overcommit_memory=1
    

    然后执行命令

    sysctl -p
    

    e. 查看主从复制信息

    image.png

    2. 配置 sentinel

    获取程序

    Sentinel 程序可以在编译后的 src 文档中发现, 它是一个命名为 redis-sentinel 的程序。

    运行一个 Sentinel 所需的最少配置如下所示:

    Redis 源码中包含了一个名为 sentinel.conf 的文件, 这个文件是一个带有详细注释的 Sentinel 配置文件示例。

    运行一个 Sentinel 所需的最少配置如下所示:

    // 监控一个 Redis 服务器
    // 名称为 mymaster ,IP 为 127.0.0.1 端口为 6379
    // 最后的 2  是指最少有 2 给 Sentinel 实例同意一台 redis 服务器宕机,才会执行故障转义。
    sentinel monitor mymaster 127.0.0.1 6379 2
    
    sentinel down-after-milliseconds mymaster 3000
    
    // 180 秒后开始故障自动装换
    sentinel failover-timeout mymaster 5000
    
    sentinel parallel-syncs mymaster 1
    

    各个选项的功能如下:

    down-after-milliseconds 选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
    如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。

    不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。

    将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。

    parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长。

    a. 获取并修改配置文件

    快速创建三个 sentinel 配置文件
    进入到 Redis 源码的目录下,执行如下命令


    image.png

    修改监听端口

    image.png

    之后在每个 sentinel 配置文件中添加守护进程方式运行,
    并修改dir 配置项的目录,

    daemonize yes
    dir /redis/data/
    logfile  "sentinel-${port}.log"
    

    最后别忘了修改监控的主服务器的 IP 和端口正确的 6380

    最终其中一个的配置文件应该是这样的


    image.png

    b. 启动服务并验证

    启动服务的语法:

    shell> redis-sentinel   sentinel的配置文件
    
    image.png image.png

    可以使用以下命令查看哨兵的信息

    [root@s1 ~]# redis-cli -p 27001 info
    ...略...
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=3
    [root@s1 ~]#
    
    
    

    3. 客户端如何连接使用 Sentinel

    客户端需要知道所有 Sentinel 所有节点的 IP和一个 Master Name。

    第一步从所有的 Sentinel 列表中得到一个有效的 Sentinel 节点。

    image.png

    第二步向得到的 Sentinel 节点发送查询一个已知的 Master Name 的信息到请求,并得到 Master 节点的信息

    image.png

    第三步向 Master 节点验证 Maset 角色的真实性

    image.png

    第四步 客户端 和 Sentiel 之间建立发布订阅关系。

    客户端订阅 Sentinel 的频道,一旦 Master 的 IP 信息有变化,客户端就会通过此频道发布的信息得知。


    image.png

    4. 故障演练

    停止 Master 节点的服务

    [root@s1 ~]# redis-cli -p 6380 shutdown
    

    不断的刷新其中一个 Sentinel 节点的信息,观察最后一行信息的变化

    [root@s1 ~]# redis-cli -p 27001 info
    ...略...
    master0:name=mymaster,status=ok,address=127.0.0.1:6382,slaves=2,sentinels=3
    
    
    


    三、 集群

    1. 数据分区介绍

    image.png

    a. 数据分区的方式

    image.png

    两者的对比

    image.png

    b. 哈希分区的三种方式

    • 节点取余

    • 一致性哈希

    • 虚拟槽哈希

    ① 节点取余(不推荐使用)

    image.png
    问题: 当向集群重添加一个节点时,数据迁移率太大

    迁移前

    image.png

    迁移后

    image.png
    建议添加节点时,采用多倍扩容的方式
    多倍扩容

    ② 一致性哈希分区方式

    基本规则,顺时针的方式式


    image.png

    一致性哈希的扩容

    扩容前

    image.png

    扩容后

    image.png

    特点总结

    image.png

    ③ 虚拟槽分区方式(Redis Cluster 使用了此方式)

    虚拟槽的分配
    image.png

    2.Redis 集群的优势

    自动分割数据到不同的节点上。
    整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

    特点

    主从复制

    实现了高可用

    数据分片存储

    集群节点的 meet 过程

    三个节点 六个节点

    指派槽

    image.png

    客户端和槽

    image.png

    3. Redis 集群的安装

    原生命令安装

    步骤

    1. 配置开启集群节点

    2. 配置 meet

    3. 指派槽

    4. 配置主从

    实例操作

    准备两台虚拟机:
    一台启动三个 Redis 实例作为 主节点
    另一台启动三个 Redis 实例作为 从节点

    架构图
    集群拓扑图
    实验步骤
    1. 先编辑一个集群的配置文件

    编译配置文件 /etc/redis/cluster-redis-7001.conf, 添加如下内容:

    bind 0.0.0.0
    port 7001
    daemonize yes
    
    # 允许任何地址不使用密码访问我
    protected-mode no
    dir "/redis/data/"
    logfile  "cluster-7001.log"
    dbfilename "cluster-dump-7001.log"
    cluster-enabled yes
    cluster-config-file nodes-7001.conf
    
    # 不需要集群的全部节点完好才提供服务
    cluster-require-full-coverage no
    
    
    1. 再创建其他集群的配置文件


      image.png
    [root@s1 redis]# sed 's/7001/7002/g' cluster-redis-7001.conf > cluster-redis-7002.conf
    [root@s1 redis]# sed 's/7001/7003/g' cluster-redis-7001.conf > cluster-redis-7003.conf
    [root@s1 redis]# sed 's/7001/7011/g' cluster-redis-7001.conf > cluster-redis-7011.conf
    [root@s1 redis]# sed 's/7001/7012/g' cluster-redis-7001.conf > cluster-redis-7012.conf
    [root@s1 redis]# sed 's/7001/7013/g' cluster-redis-7001.conf > cluster-redis-7013.conf
    

    拷贝从节点的配置文件到另外一台主机上

    需要保证另一台主机上有目录 /etc/redis/, 因为这里计划把所有的配置文件放在此目录下

    [root@s1 redis]# scp -r cluster-redis-701*  root@172.16.153.179:/etc/redis/
    
    
    
    1. 首先,需要启动主节点的服务进程
    [root@s1 ~]# redis-server  /etc/redis/cluster-redis-7001.conf
    [root@s1 ~]# redis-server  /etc/redis/cluster-redis-7002.conf
    [root@s1 ~]# redis-server  /etc/redis/cluster-redis-7003.conf
    
    1. 之后,再启动从节点的服务进程
    image.png
    [root@s2 ~]# mkdir -p /redis/data
    [root@s2 ~]# redis-server  /etc/redis/cluster-redis-7011.conf
    [root@s2 ~]# redis-server  /etc/redis/cluster-redis-7012.conf
    [root@s2 ~]# redis-server  /etc/redis/cluster-redis-7013.conf
    

    检查进程

    ps   -ef  | grep  redis-server
    

    假设你现在去连接到任意一个节点上执行操作会返回集群目前是没有启动的信息。

    原因是目前集群各节点之间没有进行 meet 操作,都是各自孤立的状态。

    image.png

    可以使用如下命令查看集群的相关信息

    image.png

    还可以查看某一个集群节点信息,第一列是集群节点 ID

    image.png
    1. 集群节点之间的 meet

    我们下面使用主节点 172.16.153.178:7001 去依次的 meet 其他 5 个节点。

    image.png

    查看集群信息和节点 信息

    image.png image.png
    1. 给集群节点分配 数据槽
      集群的槽号是 从 0 开始,到 16383 结束,共 16384 个。

    槽的分配是拿 16384 除以集群中主节点的个数,得到每个主节点应该被分配给槽的数量。

    所以现在的计划是:

    image.png

    命令

    redis-cli  -h 被添加的主机 IP -p 端口 cluster  addslots  槽号
    

    假如给 7001 分配 0 号槽。命令应该是:

    redis-cli  -h 172.16.153.178  -p 7001 cluster  addslots  0
    

    每次只能分配一个 槽号,所以我们可以写个脚本,当然这种方式是不会在生产环境中使用的,这里只是为了理解集群的架构关系。

    脚本

    #!/bin/sh
    
    target_host_ip=$1
    target_host_port=$2
    
    star=$3
    end=$4
    
    for slot in $(seq ${star} ${end})
    do
        echo "正在给 ${target_host_ip} ${target_host_port} 添加${slot}"
        redis-cli -h ${target_host_ip} -p ${target_host_port}  cluster addslots ${slot}
    
    done
    

    使用脚本

    sh mutil-addslots.sh 172.16.153.178 7002 5462 10922
    sh mutil-addslots.sh 172.16.153.178 7003 10923 16383
    

    多线程版

    image.png

    最后查看集群信息

    image.png

    可以发现此时集群的状态是 OK 的。

    查看节点信息

    image.png
    1. 给集群节点配置主从关系

    命令语法

    redis-cli   -p  从节点端口   cluster  replicate  主节点的 ID
    

    实操

    切换到从节点所在的主机,这样有便于操作

    先获取到集群各个节点的 ID


    image.png

    再按照计划好的进行复制关系的设置

    [root@s2 ~]# redis-cli -p 7011 cluster replicate 587b37f1bbe86dcce2b21e3890a61e9b5cdabade
    OK
    [root@s2 ~]# redis-cli -p 7012 cluster replicate 9d2617ed1892ad08d0bc66b50dada6d53901cce3
    OK
    [root@s2 ~]# redis-cli -p 7013 cluster replicate e3f9b763619c0f94ce943e57766001f0283f6c51
    OK
    

    查看集群节点信息,验证主从关系

    redis-cli   -p  7011 cluster  nodes
    
    image.png

    完全配置好后,可以观察集群的数据槽的分配情况

    redis-cli -p 7011 cluster  slots
    

    最后用客户端登录集群的方式登录到集群中的任意一个节点,设置键值对进行测试。

    image.png

    官方工具安装

    官方工具依赖于 Ruby

    1. 下载、编译、安装 Ruby

    点我到下载页面

    [root@s1 ~]# wget https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.gz
    
    

    安装依赖包

    yum  install  zlib-devel readline openssl-devel
    

    点我查看具体安装方法

    $ ./configure
    $ make
    $ sudo make install
    

    2. 安装 rubygem redis

    一个 ruby 语言实现的访问 Redis 集群的客户端

    点我到官网下载地址

     wget https://rubygems.org/rubygems/rubygems-3.0.2.tgz
     tar -xf rubygems-3.0.2.tgz
    cd rubygems-3.0.2/
    ruby setup.rb
    
    gem install redis
    

    3. 安装 redis-trib.rb

    redis-trib 位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。

    cp   ~/redis-4.0.10/src/redis-trib.rb   /url/local/bin/
    

    配置集群

    假如你完全安装这个文档做的实验的换,此时配置集群之前,需要把之前的集群进程都停掉。

    先在从节点上执行,再到主节点上执行

    ps -ef | grep redis-server | grep -v 'grep' | awk '{print $2}' |xargs  kill
    
    

    接着分别在两台主机上,把之前集群产生的数据清除

    [root@s1 ~]# rm -rf /redis/data/
    
    [root@s2 ~]# rm -rf /redis/data/
    

    再重新启动这些节点的服务进程
    先在主节点上执行


    image.png

    再在从节点上执行

    image.png

    之后使用如下命令创建集群

    redis-trib-rb  create  --replicas  主节点1IP:端口    主节点2P::端口    主节点3P::端口   从节点1P::端口    从节点2P::端口    从节点3P::端口  
    
    

    选项–replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

    redis-trib.rb create --replicas 1 172.16.153.178:7001 172.16.153.178:7002 172.16.153.178:7003 172.16.153.179:7011 172.16.153.179:7012 172.16.153.179:7013
    
    
    
    image.png
    image.png
    image.png

    4. 深入集群

    集群的伸缩

    添加节点(扩容)

    1. 准备节点


      image.png

    2.加入集群中

    image.png image.png
    1. 实例操作
    image.png image.png
    1. 完成后观察各主节点的数据槽的分配情况
    image.png

    减少节点(缩容)

    image.png

    缩容时的迁移槽

    image.png

    忘记节点操作

    image.png
    实验

    命令:

    ./redis-trib.rb  reshard --from   下线节点 ID  --to  集群中的任意主节点 ID  --slots   迁移到槽数   目前集群中任意节点 IP:端口
    

    注意:
    需要把下线节点的槽数平均迁移到剩余的所有节点,所以需要分配分次执行上面的命令。
    并且,每次都集群中的主节点应该不同。

    删除节点

    当我们使用 redis-trib.rb 工具时,只需要在目前集群中的任意一个节点中执行如下命令即可。

    注意:
    你应该始终先删除从节点,再删除主节点

    image.png

    九、缓存设计和优化

    敬请期待_

    :

    相关文章

      网友评论

        本文标题:Redis 高级部分

        本文链接:https://www.haomeiwen.com/subject/lyfwyqtx.html