Redis缓存数据库(三)

7. Redis集群

在这里插入图片描述

为什么要引入“集群”的概念和使用集群?因为Redis的单机、单节点、单实例的情况下,会存在几个问题:单点故障,内存容量有限,服务器访问压力等问题。

在这里插入图片描述

7.1 单点问题

单机、单节点、单实例存在的弊端:

  1. 单点故障;
  2. 内存容量有限;
  3. 访问压力。

只要是单点就必然存在以上这3个问题,这几个问题不仅仅存在于Redis中,尤其是单点故障,也是微服务、分布式场景下一定要考虑和解决的问题,因此以下讨论的解决方案以及涉及到原则,在分布式的场景下也是可以考虑的。

7.2 解决方案

在这里插入图片描述

针对以上单点问题,可以参考AKF可拓展模型,从3个维度去制定解决方案:

  1. X轴:全量、镜像 -> 单点故障;

    一般X轴是通过主从复制来做HA高可用的,即一主多从,主机对外提供读写服务,从机是主机的镜像,包含主机的全量数据,可以对外提供读服务(所说的读写分离)。

    在主机发生故障时,可以迅速进行自动故障转移,在从机中选择一台来代替主机继续对外提供读写服务,以达到服务一直可用(高可用)。当然这里涉及到数据一致性,如何自动故障转移等问题,后文会讨论。

  2. Y轴:业务、功能 -> 内存容量有限;

    在解决单点故障后,还要考虑在庞大数据量的情况下,单机内存容量有限的问题。因为不论如何做高可用,一台服务器所能存储的数据量是有限度的,比如一个电商系统,随着数据量不断增长,容量问题是必须解决的。

    这就需要在Y轴上根据业务、功能进行拆分(一变多),仍以电商系统为例,可以将订单业务、库存业务、会员业务等的数据拆分到不同服务器存储。

  3. Z轴:优先级、逻辑再拆分 -> 访问压力。

    在X轴和Y轴的解决方案中,也会减轻服务器的访问压力,这里单独提出来,同样不可规避的是庞大数据量的问题。上文提到,Y轴通过业务、功能拆分将不同业务数据打散到不同服务器中,是对于数据可以进行拆分的情况下,这里讨论的是数据不可拆分的情况。

    例如由于电商系统中的业务量增大,订单业务的数据就已经达到一台服务器的存储上限,Y轴业务拆分的方案已不适用,这就要在Z轴进行逻辑拆分了,即进入Sharding分片方式。如将订单数据按其主键ID进行拆分,通过某种算法,如Hash+取模,随机算法,一致性哈希算法等,将数据打散到不同服务器中。这样单台服务器的数据通过拆分,来减轻其数据访问压力。

AKF模型也是微服务、分布式中的一个解决方案,核心思想就是“一变多”,从X轴、Y轴、Z轴三个方向(维度)通过主从复制、业务拆分、Sharding分片来做HA高可用。

7.3 AKF可拓展模型

通过AKF-一变多可以带来单点问题的解决方案,同时也会带来一些新的问题,单节点到多节点(或者单体到分布式),数据一份变多份,就必然会带来数据一致性问题,即所有节点如何同步数据,如何做到数据一致。

第二个问题是主从复制实现HA高可用时,如何进行自动故障转移,以及主机挂了,通过什么**投票机制(选主机制)**在从机中选择一台去代替主机来继续提供服务。

7.3.1 数据一致性

1、强一致性
在这里插入图片描述

  • 同步阻塞方式;
  • 所有节点阻塞,直到数据全部一致;
  • 破坏可用性。

如上图所示,当客户端向Redis(主节点)写入数据时,主节点会以同步阻塞的方式去给两个从节点同步数据,直到从节点全部同步数据成功,主节点才会给客户端返回OK。在同步数据过程中,主节点一直是阻塞等待状态,期间服务是不可用的,客户端需要一直等待。

这种就是数据的强一致性方式,它破坏了Redis的可用性。我们采用一变多的方案,就是为了解决可用性问题,现在又破坏了可用性,所以Redis中不采用这种方式。

2、弱一致性
在这里插入图片描述

  • 异步非阻塞方式
  • 容忍数据丢失一部分。

如上图所示,客户端写入数据到Redis主节点,主节点会立刻给客户端返回OK,同时以异步非阻塞的方式向两个从节点同步数据。

这种方式主节点不会阻塞等待所有从节点全部同步数据完毕,期间服务一直可用,但可能会因为某个从节点数据同步失败,导致丢失数据。这就是弱一致性。

3、最终一致性
在这里插入图片描述

  • 同步阻塞方式:

    主节点通过一个中间件去给从节点同步数据,这就要求中间件响应速度足够快,是可靠的,集群方式的,比如Kafka。

  • 数据最终是一致的;

  • 数据同步过程中,其他客户端有可能会取到不一致的数据。

如上图所示,客户端向Redis主节点写入数据时,主节点会以同步阻塞的方式给所有从节点同步数据,但由于响应速度非常快,主节点会很快给客户端返回OK,客户端不会出现长时间等待状态,这就不会破坏服务的可用性。

这种就是数据的最终一致性,它是弱一致性的特例,但不会丢失数据。

这种方式可能会出现,在某一个从节点数据同步未完成时,其他客户端访问该节点,出现取到不一致的数据。针对这种情况的解决方案是:强调-强一致性,即客户端每次请求先去更新数据即可。

7.3.2 主从复制

在这里插入图片描述

  1. 对主做HA高可用;

  2. 自动故障转移:代替人;

  3. 由一个技术、程序实现。

    只要是一个程序就会有单点故障问题,这就需要一变多的集群。

在我们对单机一变多时,可以采用主备和主从的方式,Redis一般采用主从复制的方式,进行读写分离,主节点可以提供读写服务,从节点只可提供数据读取服务。

既然主节点是一台,又会出现单点故障问题,这就需要在主节点做HA高可用,出现问题时进行故障转移,由某一个从节点来替代主继续对外提供服务。我们可以由人去监控,发现主故障后手动操作,但是这往往是不可靠的(人不可能一天24小时一直盯着),我们更倾向于用某一个技术、程序去代替人进行自动故障转移。我们再继续分析,只要是一个程序仍然会有单点故障问题,所以这就要求该程序也是一个高可用的集群,既可以监控Redis主从服务状态,又可以监控自身状态,同时在主节点挂了后,可以通过某种机制重新选出一个主来继续对外提供服务。

7.3.3 投票选主

在这里插入图片描述

如上图所示,我们使用某一个程序,以集群的方式去监控Redis的主从集群(如下文提到的Sentinel哨兵,自身以集群的方式去监控Redis主节点,同时会从主节点中获取都其全部从节点的信息),当Redis主节点出现故障后,以投票的方式去重新选主。

对于投票机制,需要进行业务推导,其核心思想是-一部分给出OK,另一部分不算数:

  1. 1台或少于半数:统计不准确,不够势力范围,会出现网络分区(脑裂)问题。

    如上图所示,使用3台机器去监控Redis主节点的健康状态,当其中一台(少于半数)给出Redis主节点出现故障信息,一定就是主节点出现问题了吗?答案是不一定,实际的情况可能是其他2台监控到Redis主节点是健康的,只是这1台机器自身出现问题或者网络不同导致。

    这就是出现了网络分区(脑裂,即在同一时间监控给出Redis主节点不一样的健康状态),但是仅仅这1台或少于半数,是不足以说明Redis主节点出现故障的。

  2. n/2+1过半:成功解决脑裂问题。

    而当其中2台(过半)都监控到Redis主节点出现故障,此时就有足够的势力范围,忽略另外1台(少于半数),以半数以上票数去重新选主,进行自动故障转移,这就解决了脑裂问题。

  3. 一般使用奇数台。

    采用“过半”机制,3台监控机器允许1台出现问题,4台允许1台出现问题,同样都是允许1台出现问题,使用3台-奇数台足够又节约成本。

7.4 CAP原则

在这里插入图片描述
在这里插入图片描述

CAP原则,又称为CAP定理,即分布式存储系统的CAP原理(分布式系统的三个指标):

  1. Consistency(一致性):在分布式系统中的所有数据备份,在同一时刻是否同样的值

    对于数据分布在不同节点上的数据来说,如果某个节点更新了数据,那么在其他节点如果能读取到这个最新的数据,那么就称为强一致,如果某个节点没有读取到,那就是分布式不一致。

  2. Availability(可用性):在集群中一部分节点发生故障后,集群整体是否还能响应客户端的读写请求。(要求数据需要备份)

  3. Partition tolerance(分区容忍性):大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是,区间通信可能失败。

CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们无法避免的。所以我们只能在一致性和可用性之间进行权衡,没有系统能同时保证这三点。要么选择CP,要么选择AP。

7.4.1 BASE定理

这里我们再简单介绍下分布式实践中的一个定理–BASE定理

BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。接下来看看BASE中的三要素:

  1. Basically Available(基本可用

    基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。

    电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。

  2. Soft state(软状态)

    软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。MySQL Replication的异步复制也是一种体现。

  3. Eventual consistency(最终一致性)

    最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

BASE模型是传统ACID模型的反面,不同于ACID,BASE强调牺牲高一致性,从而获得可用性,数据允许在一段时间内的不一致,只要保证最终一致就可以了

7.5 Redis的主从复制

在这里插入图片描述

7.5.1 人工故障转移

  1. Redis使用默认的异步复制,其特点是低延迟和高性能,数据是弱一致性

  2. 从追随主的命令,Redis5.0以前是SLAVEOF,5.0以后改成了REPLICAOF。也可用配置文件进行配置。

    (1)命令使用:

    1、从追随启动:
    redis-server ./6381.conf --replicaof 127.0.0.1 6379
    
    2、当从挂机,重新执行上述命令,追随主时,不会重新落RDB。因为RDB中可以记住从曾经追随谁,ID号是多少。之后增量即可
    
    3、但命令加上 --appendaof yes 后,就要重新落RDB,从先flush old data。这是AOF和RDB的本质区别
    

    (2)主从复制配置

    replica-server-stale-data yes  
    #开启让别人查
    replica-read-only yes
    #备机是否只支持查询(只读模式)
    repl-diskless-sync no
    #是否通过磁盘传输RDB文件
    #yes 通过网络传输
    #no 走磁盘
    
    repl-backlog-size 1mb
    #增量复制,超过了触发全量
    
    min-replicas-to-write 3
    #规定最少几个写成功
    min-replicas-max-lag 10
    # 数据复制和同步的延迟不能小于多长时间(单位:秒)
    

    (3)说明下repl-diskless-sync配置项,即是否通过磁盘传输RDB文件

    ​ 第一种情况:为no时,通过磁盘IO进行传输。

    ​ 第二种情况:为yes时,直接通过网络发生RDB,走网络IO。

    ​ 当网络带宽非常大,比如几个G的带宽,而磁盘又是老式机械、传输速度很慢的硬盘时,可以选择直接通过网络发生RDB。
    在这里插入图片描述

    (4)再说明下repl-backlog-size 1mb配置项,即增量复制

    ​ 左边的主节点Redis中维护一个队列,大小即上面配置项目的大小,这里是1M。

    ​ 从节点开始追随主节点时,通过落RDB的方式,传输数据给从节点。当从节点短暂挂了又重新追随主节点后,可以通过给主节点提供一个offset,从队列中去读取数据,即增量复制。

    ​ 这种方式效率更高,不会再浪费大量时间去重新落RDB进行全量复制。但是有一点需要注意:要根据实际的业务运转情况来设置配置项的大小,而且主节点短时间内的写很多的情况,即队列以非常快的速度填满。比如当从节点重新追随主,拿offset=8想去队列中取数据时,发现队列中最小的offset=20了,这样就无法采取增量复制,而直接触发重写落RDB进行全量复制。

    在这里插入图片描述

  3. 从节点先把老数据删除,再同步主的数据。

    • Flushing old data;
    • Loading DB in memory。
  4. 从放弃追随命令:

    • replicaof noone。

7.5.2 Sentinel哨兵(自动故障转移)

  1. Sentinel哨兵,可以进行自动故障转移。

  2. 用于管理多个Redis服务器,一套哨兵可以监控多个Redis主从复制集群。

  3. 哨兵通过发布订阅发现其他哨兵(如下图所示)。

    在这里插入图片描述

  4. 启动哨兵:

    • 命令1:redis-sentinel;
    • 命令2:redis-server --sentinel。
  5. 配置文件

    • 在redis的源码目录下,有sentinel.conf配置文件,可以配置sentinel的端口号,以及要监控的Redis主节点和投票数;
    • 当主挂掉,投票选举新的主,过程中sentinel会修改自己的配置文件。

    在这里插入图片描述

7.6 容量有限解决方案(client端实现)

上面的方案中,在X轴,已经解决单点故障问题和读写分离,但是内存容量有限问题仍没有解决。

下面我们来讨论容量有限问题的解决方案,主要通过client端实现。

在这里插入图片描述

7.6.1 数据可以拆分

在这里插入图片描述

这里主要是在Y轴,数据可以分类且交集不多,就可以按照业务进行拆分,比如前面内容提到的电商系统中的订单数据、库存数据等,分别将不同类的数据放入到不同Redis服务器中即可。

7.6.2 数据不可拆分

这里主要针对Z轴,从业务数据分类,进入Sharding分片模式。

在数据没办法划分拆解的情况下,可以按照一些算法进行再细分-分片,主要有以下三种算法:

  1. modula:hash+取模;
  2. random:随机;
  3. ketama:一致性哈希。

一、modula,hash+取模算法

  1. 先对数据的key进行hash运行,得到的值取模(模数,即Redis服务器的台数),再将数据放入对应的Redis中(比如,共计10台Redis,那么模数为10,取模后的值为0~9,对应10台服务器即可);
  2. 弊端:取模的值必须固定,这就不利于分布式下的扩展。

在这里插入图片描述

二、random,随机算法

  1. 该算法是将数据随机打散到不同Redis中,如此的话写数据的client便取不出值。这种算法是有其特殊的应用场景的,如下:
    • 一个key对应的value类型是list;
    • client通过lpush存入数据,对应Redis各个服务器都会有同一个key,只是不知道具体哪些list中的元素在哪个Redis中;
    • 但这不要紧,读数据的client端可以通过rpop去获取这个key对应的list中所有数据。
  2. 这种方式就相当于一个消息队列,比如基于磁盘存储的Kafka,数据的key相当于topic,而不同Redis服务器就相当于partition。

在这里插入图片描述

三、ketama,一致性哈希算法

引入:

  1. 一致性哈希算法,是在内存中规划一个哈希环,环上的点是虚拟的。当我们规划好Redis集群后,比如开始是node01和node02这两台。先通过某种hash映射算法将这2台Redis映射到哈希环上的2个物理点;
  2. 当client写入数据data时,将对应的key进行hash后,找到离它最近的物理点,比如这里的node02,便将该数据存储到node02中。写入新数据时,以此类推。
  1. hash【映射】算法,即输出一个等宽的值,和它进行映射;

  2. 该算法没有取模操作;

  3. 数据data(即key)和 node(Redis集群中的各节点服务器) 都要参与计算;

  4. 规划一个哈希环(槽位:0~2^32 个);

    (1)虚拟节点:用来解决数据倾斜问题。

    ​ 可以将data(key)按其IP + 1,2,3,4 … 等映射更多的物理节点。

    (2)物理节点:node映射的点。

    ​ 环上的点都是虚拟的,只有node通过hash映射到环上的点才是物理的,这些物理点可放到TreeMap或其他有序集合中。

  5. data(key)经过hash,在哈希环上找到最近的物理节点;

  6. 新增节点:

    (1)优点:可以分担其他节点的压力,不会造成全局洗牌;

    (2)缺点:会造成一小部分数据不能命中:

    ​ 产生问题:造成缓存击穿,数据直接压到DB;

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

此时的Redis更倾向于做为缓存,而不是数据库!

在这里插入图片描述

7.7 Redis对Server端连接成本很高

在这里插入图片描述

7.7.1 解决方案

在上文由client端解决内存容量有限问题时,由于每个client写入的数据都可能被打散到所有Redis服务器中,就需要所有的client都要与每个Redis Server进行连接,如下图所示。实际生产中可能会使用连接池,造成Server端大量的Socket连接,不断地三次握手,四次分手等,消耗大量资源,对Redis Server端造成很大的压力,即连接成本很高。

在这里插入图片描述

为了缓解Redis Server端的压力,我们可以将client和sever进行解耦,即采用proxy代理层,如下图所示:

  1. 比如采用Nginx,所有client端与proxy连接,代理与Server连接,我们只需要关注代理层的性能,这样就减轻了服务器的压力;
  2. 这时我们也可以让client端更加轻盈,即将数据拆分的各种算法逻辑放到代理层;
  3. 由于proxy层不存储数据,是无状态的,因此可以采用多台防止单点故障问题;
  4. 如果流量过大,可以在代理层之前再加上LVS进行流量负载,对于LVS的单点问题可以使用Keepalived实现HA高可用。由于Keepalived自身的特性,既可以监控LVS的健康状态,同时可以监控proxy层服务器的健康状态;
  5. 注意:不要忽略一门技术的特性,Redis本身的特性就是快,我们使用时不要因为技术而技术,搞得越来越复杂,而影响了Redis的性能!

在这里插入图片描述

7.7.2 代理工具

Proxy代理层工具涉及很多,常见的有以下几种:

  1. twemproxy;
  2. pridixy;
  3. codis。

7.7.3 预分区

上文中提到的三个算法模式存在的弊端,无论是hash+取模会出现rehash,还是一致性哈希中部分数据不能命中问题,都决定这Redis只能做缓存,不能做数据库用。

解决方案:我们可以采取预分区的方式,如下图所示:

先设定一个模数值10,开始有2台Redis Server,预先分配映射关系:

  1. 将0, 1,2,3,4映射到redis1;
  2. 将5,6,7,8,9映射到redis2;
  3. 当增加1台redis3时,已有数据不需要rehash,只需要将redis1和redis2中的映射关系和数据迁移至redis3中即可;
  4. 而每台redis都会其他redis server的映射关系,确保每个key进行hash运算后都能分配到对应server中:
    • 共享mapping字典;
    • 重定向到目标server。
  5. 比如,当client连接redis2时,此时写入数据的key进行hash取模后值是4,此时在redis2中没有这个映射关系,redis2便会给client返回提示信息–去redis3中获取数据(这个模式也是接下来要介绍的Redis集群Cluster的方式,它会以自动路由的方式将client路由至redis3)。

在这里插入图片描述

7.8 Redis集群

在这里插入图片描述

7.8.1 集群方案

上文提到的预分区方案,就是Redis Cluster(集群)采用的方式。Redis集群的数据分片:

  1. Redis集群没有使用一致性hash,而是引入了哈希槽的概念;
  2. Redis集群共有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置在哪个槽;
  3. Redis集群的每个节点负责一部分hash槽,按hash槽进行数据迁移;
  4. Redis集群是无主模型,所有节点共享mapping字典,通过路由方式重定向到目标server。客户端连接时,可以想连谁(集群中的节点),就去连谁。

7.8.2 数据分治

  1. 数据不分开,就一定会发生事务;
  2. 数据分治的弊端:聚合操作很难实现,事务也很难实现;
  3. 解决方案:hash tag。比如有些操作徐亚依赖多个key,可以将其统一tag,如{oo}k1,{oo}k2,它们拿着相同的“oo”去hash取模,就会落到同一个节点上。

7.8.3 Redis Cluster相关实践

下文是一个Redis Cluster的基本实践,具体内容如下(实际生产中,需要按需搭建和配置):

[root@node01 create-cluster]# cd /root/soft/redis-5.0.5/utils/create-cluster/
里面有个脚本 create-cluster:
=======================================================
[root@node01 create-cluster]# ls
create-cluster  README
=======================================================

vi create-cluster
===========================修改脚本内容============================
#!/bin/bash

# Settings
PORT=30000
TIMEOUT=2000
NODES=6                //6台实例
REPLICAS=1             // 1个从机

即3主3从,6 / (1+1) = 3 
===========================修改脚本内容============================



把6个实例跑起来:
[root@node01 create-cluster]# ./create-cluster start
=======================
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006
=======================

接着分槽位:
[root@node01 create-cluster]# ./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: a3e2708453e189a7a16735f6d9ebbd0cf4973173 127.0.0.1:30001
   slots:[0-5460] (5461 slots) master
M: c854c143e91513ce585ac1e61b9a2fdd957fd86f 127.0.0.1:30002
   slots:[5461-10922] (5462 slots) master
M: 7b5d542601ec7077f3f30452f8be160e0c84943a 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
S: a03839a13b4ac9e27b415f71086cc4b0cc5578c4 127.0.0.1:30004
   replicates 7b5d542601ec7077f3f30452f8be160e0c84943a
S: e53af15537723ce0c4f338608f7b81054bb546b6 127.0.0.1:30005
   replicates a3e2708453e189a7a16735f6d9ebbd0cf4973173
S: a1a5790e690251f15d84d0994acfe5597738a3e2 127.0.0.1:30006
   replicates c854c143e91513ce585ac1e61b9a2fdd957fd86f
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: a3e2708453e189a7a16735f6d9ebbd0cf4973173 127.0.0.1:30001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: c854c143e91513ce585ac1e61b9a2fdd957fd86f 127.0.0.1:30002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: a1a5790e690251f15d84d0994acfe5597738a3e2 127.0.0.1:30006
   slots: (0 slots) slave
   replicates c854c143e91513ce585ac1e61b9a2fdd957fd86f
M: 7b5d542601ec7077f3f30452f8be160e0c84943a 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: a03839a13b4ac9e27b415f71086cc4b0cc5578c4 127.0.0.1:30004
   slots: (0 slots) slave
   replicates 7b5d542601ec7077f3f30452f8be160e0c84943a
S: e53af15537723ce0c4f338608f7b81054bb546b6 127.0.0.1:30005
   slots: (0 slots) slave
   replicates a3e2708453e189a7a16735f6d9ebbd0cf4973173
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@node01 create-cluster]#
======================================================

可以使用命令连接:
[root@node01 create-cluster]# redis-cli -p 30001
==================================================
127.0.0.1:30001> set k1 m
(error) MOVED 12706 127.0.0.1:30003
此时客户端只能以报错形式显示
==================================================


这时可以换命令连接,以cluster模式:
[root@node01 create-cluster]# redis-cli -c -p 30001
==========================================================
127.0.0.1:30001> set k1 m
-> Redirected to slot [12706] located at 127.0.0.1:30003
OK
127.0.0.1:30003>

就会跳转到30003,创建k1 (即路由模式)
==========================================================





可以通过stop命令停止cluster:
[root@node01 create-cluster]# ./create-cluster stop
==========================================================
Stopping 30001
Stopping 30002
Stopping 30003
Stopping 30004
Stopping 30005
Stopping 30006
==========================================================


可以清掉数据还原:
[root@node01 create-cluster]# ./create-cluster clean


可以使用这个命令,人工调客户端(不用脚本)去创建:
[root@node01 create-cluster]# ./create-cluster start
[root@node01 create-cluster]# redis-cli --cluster help   //这是帮助命令
// 这个命令,可以配置分布式,即不同IP不同集群(比脚本更重要):
[root@node01 create-cluster]# redis-cli --cluster create 127.0.0.1:30001 127.0.0.1:30002 127.0.0.1:30003 127.0.0.1:30004 127.0.0.1:30005 127.0.0.1:30006 --cluster-replicas 1




生产中更重要的还是重新分配 reshard 命令(解决新增节点,数据倾斜问题):
[root@node01 create-cluster]# redis-cli --cluster reshard 127.0.0.1:30001
===============================================================================
>>> Performing Cluster Check (using node 127.0.0.1:30001)
M: 0cac4c08261d4ade0eb43d5971ea98bf64c3b930 127.0.0.1:30001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 666543fe56cbcbfc798783a9a40cf8665fa8908e 127.0.0.1:30005
   slots: (0 slots) slave
   replicates 0cac4c08261d4ade0eb43d5971ea98bf64c3b930
S: ff93bb3a6e60c53aa59bfa38e6d5af571b1e355a 127.0.0.1:30004
   slots: (0 slots) slave
   replicates f4b6be939fa62c20912265d34606506b3297a8ba
M: f4b6be939fa62c20912265d34606506b3297a8ba 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: e0b41a7cb56c07ad1d4dee5dd0489f460aa4da72 127.0.0.1:30006
   slots: (0 slots) slave
   replicates 7f9203c07291afcb02d0da0ed96b173b73f2c80f
M: 7f9203c07291afcb02d0da0ed96b173b73f2c80f 127.0.0.1:30002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 2000                     //这里输入2000,表示移动2000个槽位
What is the receiving node ID? 7f9203c07291afcb02d0da0ed96b173b73f2c80f        //输入MasterID,表示移动到第2台 30002
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: 0cac4c08261d4ade0eb43d5971ea98bf64c3b930                      //输入MasterID,表示从第1台 30001 移动
Source node #2: done                                                          //可以继续选其他机器,这里输入done,即只能第1台移动

以上即【从第1台 30001 移动 2000 个槽位到 第2台机器】
===============================================================================


移动完毕,看第1台信息,移动成功:
[root@node01 create-cluster]# redis-cli --cluster info 127.0.0.1:30001
===============================================================================
127.0.0.1:30001 (0cac4c08...) -> 0 keys | 3461 slots | 1 slaves.
127.0.0.1:30003 (f4b6be93...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:30002 (7f9203c0...) -> 0 keys | 7462 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.
===============================================================================


还有个命令,检查槽位情况:
[root@node01 create-cluster]# redis-cli --cluster check 127.0.0.1:30001
===============================================================================
127.0.0.1:30001 (0cac4c08...) -> 0 keys | 3461 slots | 1 slaves.
127.0.0.1:30003 (f4b6be93...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:30002 (7f9203c0...) -> 0 keys | 7462 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:30001)
M: 0cac4c08261d4ade0eb43d5971ea98bf64c3b930 127.0.0.1:30001
   slots:[2000-5460] (3461 slots) master
   1 additional replica(s)
S: 666543fe56cbcbfc798783a9a40cf8665fa8908e 127.0.0.1:30005
   slots: (0 slots) slave
   replicates 0cac4c08261d4ade0eb43d5971ea98bf64c3b930
S: ff93bb3a6e60c53aa59bfa38e6d5af571b1e355a 127.0.0.1:30004
   slots: (0 slots) slave
   replicates f4b6be939fa62c20912265d34606506b3297a8ba
M: f4b6be939fa62c20912265d34606506b3297a8ba 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: e0b41a7cb56c07ad1d4dee5dd0489f460aa4da72 127.0.0.1:30006
   slots: (0 slots) slave
   replicates 7f9203c07291afcb02d0da0ed96b173b73f2c80f
M: 7f9203c07291afcb02d0da0ed96b173b73f2c80f 127.0.0.1:30002
   slots:[0-1999],[5461-10922] (7462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
===============================================================================

8. API

在这里插入图片描述

  1. jedis,是线程不安全的,一般使用pool连接池;

    在这里插入图片描述

  2. lettuce,支持同步异步;

  3. Spring Data Redis:

    • before:

      • 修改redis.conf:

        # 1、注释掉 bind 127.0.0.1
        # 2、修改配置项:
        protected mode no
        
        # 127.0.0.1:6379> 
        CONFIG GET *   # 获取当前实例的配置文件信息
        # 127.0.0.1:6379> 
        CONFIG SET protected-mode no  # 临时修改配置文件,允许远端访问,否则程序访问不了
        
      • 防火墙配置:

        # 编辑配置文件
        vi /etc/sysconfig/iptables
        # 添加6379端口:
        -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
        # 重启防火墙:
        service iptables restart
        
    • 使用API时,注意几个重点:

      • 如何获取Redis连接;

      • 选择使用其low level / high level 低阶/高阶API;

        1、高阶API
        RedisTemplate :序列化(字符串会乱码)
        StringRedisTemplate :操作字符串
        redisTemplate.opsForValue().set("k1", "hello");
        redisTemplate.opsForValue().get("k1");
        
        2、低阶API
        RedisConnection conn =      redisTemplate.getConnectionFactory().getConnection();
        conn.set(byte[] bytes, byte[] bytes);
        conn.set("k2".getBytes(), "hello".getBytes());  //返回值字节数组
        
      • 数据如何加工(如序列化,编解码),放入Redis。

  4. Spring Boot方式,Redis连接都是自动配置的,相对更简单了。

9. 分布式锁

  1. setnx;

  2. 过期时间;

  3. 多线程(守护进程)延迟过期时间;

  4. Redisson更好;

  5. ZooKeeper更更更好!!!

    说到分布式锁,就一定要说ZK,接下来我会继续分享关于ZK的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值