美文网首页程序员
redis设计与实现-集群

redis设计与实现-集群

作者: 求索 | 来源:发表于2020-03-08 22:51 被阅读0次

    概念

    redis集群指由多个redis节点组合的分布式redis服务器群,redis 节点间两两通过握手通信。

    特性

    • 多个节点通过握手通信
    • 共有16384个槽
    • 每个槽都必须分派到具体节点,否则集群起不来
    • 每个节点都记录了整个集群所有的槽分派情况
    • 在redis键值归属的槽不属于当前切片(槽)时会发生moved错误
    • moved 错误在客户端以集群模式访问时,会携带指引客户端跳转到负责当前槽的节点的信息
    • 迁移过程中会发生ASK错误,ASK错误指示数据库继续查找键值
    • 重新分片,在数据量不断变大时,可以重新分片。
    • 集群中的每个节点可以通过主从模式构建高可用性。主节点下线后,集群会从其从节点中选择一个作为主节点,并接收原理主节点的所有槽。
    • 集群中的节点通过发送和接收消息来进行通信,常见的消息包括MEET、PING、PONG、PUBLISH、FAIL五种。

    设计原理

    redis 集群通过切片方式实现,整个集群由16384个槽,通clusterState状态记录每个槽的使用情况,clusterState[i]=nil 表示当前槽未分派给指定节点。

    节点实现数据结构:

    struct clusterNode {
        //创建节点的时间
        mstime_t ctime;
        //节点的名字,由40个十六进制字符组成
        //例如68eef66df23420a5862208ef5b1a7005b806f2ff
        char name[REDIS_CLUSTER_NAMELEN];
        //节点标识
        //使用各种不同的标识值记录节点的角色(比如主节点或者从节点),
        //以及节点目前所处的状态(比如在线或者下线)。
        int flags;
        //节点当前的配置纪元,用于实现故障转移
        uint64_t configEpoch;
        //节点的IP地址
        char ip[REDIS_IP_STR_LEN];
        //节点的端口号
        int port;
        //保存连接节点所需的有关信息
        clusterLink *link;
        // ...
    };
    

    节点状态数据结构

    typedef struct clusterState {
        //指向当前节点的指针
        clusterNode *myself;
        //集群当前的配置纪元,用于实现故障转移
        uint64_t currentEpoch;
        //集群当前的状态:是在线还是下线
        int state;
        //集群中至少处理着一个槽的节点的数量
        int size;
        //集群节点名单(包括myself节点)
        //字典的键为节点的名字,字典的值为节点对应的clusterNode结构
        dict *nodes;
        // ...
    } clusterState;
    

    命令

    1. 查看集群

      • CLUSTER INFO 打印集群的信息
      • CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
      redis-cli -c -p 6379 cluster nodes
      redis-cli -c -p 6379 cluster info
      redis-trib.rb  check  10.26.25.115:6379
      redis-trib.rb info 10.26.25.115:6379
      
    2. 节点命令

      • CLUSTER MEET <ip> <port> 添加节点
      • redis-trib.rb add-node <ip> <port> 10.25.157.78:7022
      • CLUSTER FORGET <node_id>
      • redis-trib.rb del-node <ip> <port> <node_id>
    3. 设置主从节点

      • CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
    4. 槽命令

      • CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
      • CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。
      • CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
      • CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
      • CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
        -CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
      • CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
    5. 键命令

      • CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
      • CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
      • CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。

    redis集群三种方式

    • 主从复制是用于实现高可用性的,
    • 哨兵模式是主从模式的扩展,争强其高可用性。
    • 集群是用户扩展数据库的,用于解决空间问题。

    java 代码

    Set<HostAndPort> hostAndPortSet = new HashSet();
    hostAndPortSet.add(new HostAndPort("192.168.1.99", 9001));
    hostAndPortSet.add(new HostAndPort("192.168.1.99", 9002));
    hostAndPortSet.add(new HostAndPort("192.168.1.99", 9003));
    JedisCluster  cluster = new JedisCluster(hostAndPortSet);
    
    cluster.set("name", "redis cluster");
    String name = cluster.get("name");
    System.out.println(name);
    
    

    相关文章

      网友评论

        本文标题:redis设计与实现-集群

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