zoukankan      html  css  js  c++  java
  • Redis学习笔记八:集群模式

    作者:Grey

    原文地址:Redis学习笔记八:集群模式

    前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是用来解决Redis的单点容量问题。

    如何来解决Redis单点容量问题呢?

    如果数据可以拆分,我们可以让不同业务的客户端打到不同的Redis实例中。

    如果数据不能拆分,我们有如下方式:

    方案2-1 modula方式

    可以通过Hash加上取模的方式来定位打到哪个Redis实例中。

    这种方式的弊端在于:模数值固定,会影响分布式下的扩展性。

    方案2-2 random方式

    即每次请求redis的实例是随机的,一部分客户端负责push数据,一部分客户端负责消费数据,这样的场景可以适用于消息队列。

    方案2-3 ketama方式

    这种方式是通过一致性Hash算法(没有取模),规划成一个环形,环形上有很多虚拟节点,每次选择的实例通过hash算法对应到具体的一个节点。模型如下:

    Client1~Client4通过Hash分别找到了环上A~B四个点

    image

    这种方式的优点在于:增加节点的时候可以分担其他节点的压力,不会造成全局洗牌。

    缺点在于:新增节点造成一小部分数据不能命中,会使得缓存击穿,压到mysql

    解决方案:取离我最近的2个物理节点

    modula,random和ketama方式都是从客户端入手,因为每个客户端都需要与redis实例建立连接,所以,这种情况会导致连接的成本很高。如何解决这个问题呢?

    我们可以在客户端和Redis之间增加一个代理层,通过代理层去实现原先在客户端要实现的三个方案。

    image

    此时,代理层就容易成为一个单点故障。所以代理可以做集群,然后最前端通过LVS来做负载均衡,防止LVS挂掉,可以通过KeepAlived来调配LVS,同时,KeepAlived也可以作为代理层健康检查的工具。整个架构图如下:

    image

    这三种模式的弊端都在于:只能让Redis做缓存,无法做数据库。(因为数据会丢失)

    要解决这个问题,可以通过预分区的方式,增加槽位的概念:http://www.redis.cn/topics/cluster-tutorial.html

    可以通过redis-cluster 模式(无主模型)来解决。

    image

    客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis节点。Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个redis节点转发到另一个redis节点,而是在客户端的帮助下直接redirected到正确的redis节点。

    但是数据分治的时候,会带来一个问题,无法做聚合操作,怎么解决呢?

    我们可以使用hash tag,让同一组key打到同一个redis实例上面,并且对同一hash tag下的key可以进行聚合操作。

    Twemproxy实战

    Twemproxy 也叫 nutcraker。是 Twitter 开源的一个 Redis 和 Memcache 代理服务器,主要用于管理 Redis 和 Memcached 集群,减少与Cache 服务器直接连接的数量。

    启动3个redis服务实例:假设为:

    • 6379
    • 6381
    • 6380

    image

    在/usr/local/src目录下,下载最新的twemproxy的源码包

    cd /usr/local/src
    
    ## 下载源码
    wget https://github.com/twitter/twemproxy/archive/refs/tags/v0.4.1.tar.gz
    
    ## 解压
    tar xf v0.4.1.tar.gz
    
    ## 重命名
    mv twemproxy-0.4.1/ twemproxy/
    

    接下来按照官方步骤编译安装

    yum install  automake  libtool -y
    cd /usr/local/src/twemproxy/
    
    autoreconf -fvi
    
    ./configure --enable-debug=full
    
    make
    
    src/nutcracker -h
    
    
    ## 安装成服务
    
    cp nutcracker.init /etc/init.d/nutcracker
    
    chmod +x /etc/init.d/nutcracker
    mkdir /etc/nutcracker
    cp /usr/local/src/twemproxy/conf/* /etc/nutcracker/
    cp /usr/local/src/twemproxy/src/nutcracker /usr/bin
    

    接下来修改twemproxy的配置文件

    vi /etc/nutcracker/nutcracker.yml
    

    修改为:

    alpha:
      listen: 127.0.0.1:22121
      hash: fnv1a_64
      distribution: ketama
      auto_eject_hosts: true
      redis: true
      server_retry_timeout: 2000
      server_failure_limit: 1
      servers:
       - 127.0.0.1:6379:1
       - 127.0.0.1:6380:1
       - 127.0.0.1:6381:1
    
    

    启动

    service nutcracker start
    

    连接到代理:

    redis-cli -p  22121
    
    127.0.0.1:22121> set k1 1
    OK
    127.0.0.1:22121> get k1
    "1"
    
    

    不支持的一些操作。

    127.0.0.1:22121> keys *
    Error: Server closed the connection
    127.0.0.1:22121> watch k1
    Error: Server closed the connection
    127.0.0.1:22121> mult
    Error: Server closed the connection
    127.0.0.1:22121> multi
    Error: Server closed the connection
    

    predix实战

    Predixy 是一款高性能全特征redis代理,支持redis-sentinel和redis-cluster。

    我们配置一套哨兵来监控两套主从复制集群,并用predix作为代理。

    环境准备

    第一套主从:
    主:6380
    从:6379

    第二套主从:
    主:16380
    从:16379

    启动这两套实例

    哨兵26379

    配置为:

    port 26379
    sentinel monitor mymaster1 127.0.0.1 6380 2
    sentinel monitor mymaster2 127.0.0.1 16380 2
    

    哨兵26380

    配置为

    port 26380
    sentinel monitor mymaster1 127.0.0.1 6380 2
    sentinel monitor mymaster2 127.0.0.1 16380 2
    
    

    启动哨兵

    [root@redis01 sentinel]# ps -ef|grep redis
    root       1456   1443  0 20:34 pts/1    00:00:00 redis-server 127.0.0.1:6380
    root       1474   1463  0 20:35 pts/2    00:00:00 redis-server 127.0.0.1:6379
    root       1505   1488  0 20:39 pts/3    00:00:00 redis-server 127.0.0.1:16380
    root       1525   1512  0 20:39 pts/4    00:00:00 redis-server 127.0.0.1:16379
    root       1574   1559  0 20:44 pts/5    00:00:00 redis-server *:26380 [sentinel]
    root       1592   1581  0 20:44 pts/6    00:00:00 redis-server *:26379 [sentinel]
    

    配置predixy

    cd /usr/local
    
    ## 下载predixy的二进制安装包
    wget https://github.com/joyieldInc/predixy/releases/download/1.0.5/predixy-1.0.5-bin-amd64-linux.tar.gz
    
    ## 解压
    tar xf predixy-1.0.5-bin-amd64-linux.tar.gz
    
    ## 重命名
    mv predixy-1.0.5 predixy
    
    cp /usr/local/predixy/bin/predixy /usr/bin/
    

    修改配置

    vi /usr/local/predixy/conf/predixy.conf
    

    打开如下两个配置

    Bind 0.0.0.0:7617
    
    ## 默认try.conf,注释掉,打开sentinel.conf
    # Include cluster.conf
    Include sentinel.conf
    #Include try.conf
    
    

    修改sentinel.conf配置文件

    vi /usr/local/predixy/conf/sentinel.conf
    

    增加如下配置项

    SentinelServerPool {
        Databases 16
        Hash crc16
        HashTag "{}"
        Distribution modula
        MasterReadPriority 60
        StaticSlaveReadPriority 50
        DynamicSlaveReadPriority 50
        RefreshInterval 1
        ServerTimeout 1
        ServerFailureLimit 10
        ServerRetryTimeout 1
        KeepAlive 120
        Sentinels {
            + 127.0.0.1:26379
            + 127.0.0.1:26380
        }
        Group mymaster1 {
        }
        Group mymaster2 {
        }
    }
    
    

    启动

    predixy /usr/local/predixy/conf/predixy.conf
    

    测试

    [root@redis01 conf]# redis-cli -p 7617
    127.0.0.1:7617> set k1 aaa
    OK
    127.0.0.1:7617> get k1 
    "aaa"
    

    注:predixy的事务只支持单group

    redis-cluster实验

    redis自带的模式,我们可以通过如下方式来搭建一个redis-cluster

    # 进入redis源码目录
    cd /usr/local/src/redis/utils/create-cluster
    
    执行start
    
    ```sh
    [root@redis01 create-cluster]# ./create-cluster start
    Starting 30001
    Starting 30002
    Starting 30003
    Starting 30004
    Starting 30005
    Starting 30006
    

    执行create

    ./create-cluster create
    >>> Performing hash slots allocation on 6 nodes...
    Master[0] -> Slots 0 - 5460
    Master[1] -> Slots 5461 - 10922
    Master[2] -> Slots 10923 - 16383
    Adding replica 127.0.0.1:30005 to 127.0.0.1:30001
    Adding replica 127.0.0.1:30006 to 127.0.0.1:30002
    Adding replica 127.0.0.1:30004 to 127.0.0.1:30003
    >>> Trying to optimize slaves allocation for anti-affinity
    [WARNING] Some slaves are in the same host as their master
    M: 7be080333e7acc60e207374f27d6f86f15d3c466 127.0.0.1:30001
       slots:[0-5460] (5461 slots) master
    M: 8e3d9ca761726e57af2c4ca5c092599e6977a8a8 127.0.0.1:30002
       slots:[5461-10922] (5462 slots) master
    M: 71755fb0c3fcb771432467155585b40efafae80b 127.0.0.1:30003
       slots:[10923-16383] (5461 slots) master
    S: 8eb1de8a35bdfced30ef70d6faedae5cf76b8dda 127.0.0.1:30004
       replicates 7be080333e7acc60e207374f27d6f86f15d3c466
    S: f4d69a577b0992191517e1fbb71ee7598a0b8527 127.0.0.1:30005
       replicates 8e3d9ca761726e57af2c4ca5c092599e6977a8a8
    S: 4138b3e66c71ededf9362327bb5b2562da688155 127.0.0.1:30006
       replicates 71755fb0c3fcb771432467155585b40efafae80b
    Can I set the above configuration? (type 'yes' to accept): yes
    >>> Nodes configuration updated
    >>> Assign a different config epoch to each node
    >>> Sending CLUSTER MEET messages to join the cluster
    Waiting for the cluster to join
    ..
    >>> Performing Cluster Check (using node 127.0.0.1:30001)
    M: 7be080333e7acc60e207374f27d6f86f15d3c466 127.0.0.1:30001
       slots:[0-5460] (5461 slots) master
       1 additional replica(s)
    S: 4138b3e66c71ededf9362327bb5b2562da688155 127.0.0.1:30006
       slots: (0 slots) slave
       replicates 71755fb0c3fcb771432467155585b40efafae80b
    M: 71755fb0c3fcb771432467155585b40efafae80b 127.0.0.1:30003
       slots:[10923-16383] (5461 slots) master
       1 additional replica(s)
    M: 8e3d9ca761726e57af2c4ca5c092599e6977a8a8 127.0.0.1:30002
       slots:[5461-10922] (5462 slots) master
       1 additional replica(s)
    S: f4d69a577b0992191517e1fbb71ee7598a0b8527 127.0.0.1:30005
       slots: (0 slots) slave
       replicates 8e3d9ca761726e57af2c4ca5c092599e6977a8a8
    S: 8eb1de8a35bdfced30ef70d6faedae5cf76b8dda 127.0.0.1:30004
       slots: (0 slots) slave
       replicates 7be080333e7acc60e207374f27d6f86f15d3c466
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    
    

    客户端连接30001~30004任意一个服务都可以。

    Redis 用作分布式锁

    1. setnx
    2. 过期时间
    3. 多线程(守护线程)用于延长过期时间

    redisson

  • 相关阅读:
    Srt字幕文件解析
    有意思的一些处理
    CMSampleBufferRef转换
    不知为什么的警告和报错
    X Postgres copy命令导入导出数据
    X Oracle打Patch报错Missing command :fuser
    X wal_segment_size参数的理解与调优
    X PostgreSQL 11、12 开启归档日志
    X 手动安装postgresql扩展插件
    P1501 [国家集训队]Tree II
  • 原文地址:https://www.cnblogs.com/greyzeng/p/14825742.html
Copyright © 2011-2022 走看看