为什么要学习? 还不是因为打工需要......

本文主要学习自:Redis 核心技术与实战

学到生无可恋之 Redis(上)

1 Redis 缓存过期和淘汰策略

Redis 缓存使用内存来保存数据,避免业务应用从后端数据库中读取数据,可以提升应用的响应速度。那么,如果我们把所有要访问的数据都放入缓存,是不是一个很好的设计选择呢?其实,这样做的性价比反而不高。

举个例子吧。MySQL 中有 1TB 的数据,如果我们使用 Redis 把这 1TB 的数据都缓存起来,虽然应用都能在内存中访问数据了,但是,这样配置并不合理,因为性价比很低。一方面,1TB 内存的价格大约是 3.5 万元,而 1TB 磁盘的价格大约是 1000 元。另一方面,数据访问都是有局部性的,也就是我们通常所说的“八二原理”,80% 的请求实际只访问了 20% 的数据。所以,用 1TB 的内存做缓存,并没有必要。

为了保证较高的性价比,缓存的空间容量必然要小于后端数据库的数据总量。不过,内存大小毕竟有限,随着要缓存的数据量越来越大,有限的缓存空间不可避免地会被写满。此时,该怎么办呢?

解决这个问题就涉及到缓存系统的一个重要机制,即缓存数据的淘汰机制。简单来说,数据淘汰机制包括两步:

1)根据一定的策略,筛选出对应用访问来说“不重要”的数据;

2)将这些数据从缓存中删除,为新来的数据腾出空间,

1.1 设置多大的缓存容量合适?

缓存容量设置得是否合理,会直接影响到使用缓存的性价比。我们通常希望以最小的代价去获得最大的收益,所以,把昂贵的内存资源用在关键地方就非常重要了。

下面有一张图,图里有红、蓝两条线,显示了不同比例数据贡献的访问量情况。蓝线代表了“八二原理”表示的数据局部性,而红线则表示在当前应用负载下,数据局部性的变化。

蓝线表示的就是“八二原理”,有 20% 的数据贡献了 80% 的访问了,而剩余的数据虽然体量很大,但只贡献了 20% 的访问量。这 80% 的数据在访问量上就形成了一条长长的尾巴,我们也称为“长尾效应”。

所以,如果按照“八二原理”来设置缓存空间容量,也就是把缓存空间容量设置为总数据量的 20% 的话,就有可能拦截到 80% 的访问。

为什么说是“有可能”呢?这是因为,“八二原理”是对大量实际应用的数据访问情况做了统计后,得出的一个统计学意义上的数据量和访问量的比例。具体到某一个应用来说,数据访问的规律会和具体的业务场景有关。对于最常被访问的 20% 的数据来说,它们贡献的访问量,既有可能超过 80%,也有可能不到 80%。

我们再通过一个电商商品的场景,来说明下“有可能”这件事儿。一方面,在商品促销时,热门商品的信息可能只占到总商品数据信息量的 5%,而这些商品信息承载的可能是超过 90% 的访问请求。这时,我们只要缓存这 5% 的数据,就能获得很好的性能收益。另一方面,如果业务应用要对所有商品信息进行查询统计,这时候,即使按照“八二原理”缓存了 20% 的商品数据,也不能获得很好的访问性能,因为 80% 的数据仍然需要从后端数据库中获取。

接下来,我们再看看数据访问局部性示意图中的红线。近年来,有些研究人员专门对互联网应用(例如视频播放网站)中,用户请求访问内容的分布情况做过分析,得到了这张图中的红线。

在这条红线上,80% 的数据贡献的访问量,超过了传统的长尾效应中 80% 数据能贡献的访问量。原因在于,用户的个性化需求越来越多,在一个业务应用中,不同用户访问的内容可能差别很大,所以,用户请求的数据和它们贡献的访问量比例,不再具备长尾效应中的“八二原理”分布特征了。也就是说,20% 的数据可能贡献不了 80% 的访问,而剩余的 80% 数据反而贡献了更多的访问量,我们称之为重尾效应。

正是因为 20% 的数据不一定能贡献 80% 的访问量,我们不能简单地按照“总数据量的 20%”来设置缓存最大空间容量。在实践过程中,我看到过的缓存容量占总数据量的比例,从 5% 到 40% 的都有。这个容量规划不能一概而论,是需要结合应用数据实际访问特征和成本开销来综合考虑的。

系统的设计选择是一个权衡的过程:大容量缓存是能带来性能加速的收益,但是成本也会更高,而小容量缓存不一定就起不到加速访问的效果。一般来说,建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销。

对于 Redis 来说,一旦确定了缓存最大容量,比如 4GB,你就可以使用下面这个命令来设定缓存的大小了:

CONFIG SET maxmemory 4gb

不过,缓存被写满是不可避免的。即使精挑细选,确定了缓存容量,还是要面对缓存写满时的替换操作。缓存替换需要解决两个问题:决定淘汰哪些数据,如何处理那些被淘汰的数据。

1.2 Redis 缓存有哪些淘汰策略?

1.2.1 noeviction

noeviction 是默认的策略,即 Redis 在使用的内存空间超过 maxmemory 值时,也不会淘汰数据。一旦缓存被写满,再有写请求来时,Redis 不再提供服务,而是直接返回错误。Redis 用作缓存时,实际的数据集通常都是大于缓存容量的,总会有新的数据要写入缓存,而这个策略本身不淘汰数据,也就不会腾出新的缓存空间,一般不用于缓存。

1.2.2 在设置了过期时间的数据中进行淘汰

使用 EXPIRE 命令对一批键值对设置了过期时间后,无论是这些键值对的过期时间是快到了,还是 Redis 的内存使用量达到了 maxmemory 阈值,Redis 都会进一步按照 volatile-ttl、volatile-random、volatile-lru、volatile-lfu 这四种策略的具体筛选规则进行淘汰。

1)volatile-ttl:根据过期时间的先后进行删除,越早过期的越先被删除

2)volatile-random:进行随机删除

3)volatile-lru:使用 LRU 算法筛选设置了过期时间的键值对

4)volatile-lfu:使用 LFU 算法选择设置了过期时间的键值对

1.2.3 在所有数据中进行淘汰

allkeys-lru、allkeys-random、allkeys-lfu 这三种淘汰策略的备选淘汰数据范围,就扩大到了所有键值对,无论这些键值对是否设置了过期时间

1)allkeys-random:从所有键值对中随机选择并删除数据;

2)allkeys-lru:使用 LRU 算法在所有数据中进行筛选。

3)allkeys-lfu:使用 LFU 算法在所有数据中进行筛选。

这也就是说,如果一个键值对被删除策略选中了,即使它的过期时间还没到,也需要被删除。当然,如果它的过期时间到了但未被策略选中,同样也会被删除。

1.2.4 LRU (Least Recently Used)算法

按照最近最少使用的原则来筛选数据。LRU 会把所有的数据组织成一个链表,链表的头和尾分别表示 MRU 端和 LRU 端,分别代表最近最常使用的数据和最近最不常用的数据,如下

数据 20 和 3 被先后访问,然后从现有的链表位置移到 MRU 端,而链表中在它们之前的数据则相应地往后移一位。LRU 算法选择删除数据时,都是从 LRU 端开始,所以把刚刚被访问的数据移到 MRU 端,就可以让它们尽可能地留在缓存中。

但是,如果有大量数据被访问,就会带来很多链表移动操作,会很耗时,进而会性能。

1.2.5 Redis 的 LRU 数据淘汰机制

在 Redis 中,LRU 算法被做了简化,以减轻数据淘汰对缓存性能的影响。

Redis 通过 RedisObject 的 lru 字段来记录每个对象最近一次访问的时间戳,第一次淘汰数据时会随机选出 N 个数据,把它们作为一个候选集合,把 lru 字段值最小的数据从缓存中淘汰出去(也就是访问时间最久的数据)。

Redis 提供了一个配置参数 maxmemory-samples,这个参数就是 Redis 选出的数据个数 N。

# 选出 100 个数据作为候选数据集
CONFIG SET maxmemory-samples 100

当需要再次淘汰数据时,Redis 需要挑选数据进入第一次淘汰时创建的候选集合。这儿的挑选标准是:能进入候选集合的数据的 lru 字段值必须小于候选集合中最小的 lru 值。当有新数据进入候选数据集后,如果候选数据集中的数据个数达到了 maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。

这样一来,Redis 缓存不用为所有的数据维护一个大链表,也不用在每次数据访问时都移动链表项,提升了缓存的性能。但还是会有缺点,如果冷数据突发访问,抵抗能力差,可能会淘汰热数据。

1.2.6 LFU (Least Frequently used)算法

LFU 是在 LRU 的基础上,为每个数据增加了一个计数器,来统计这个数据的访问次数。当使用 LFU 筛选淘汰数据时,会先把访问次数最低的数据淘汰。如果两个数据的访问次数相同,则比较这两个数据的访问时效性,把距离上一次访问时间更久的数据淘汰。

Redis 在实现 LFU 策略的时候,把原来 24bit 大小的 lru 字段,又进一步拆分成了两部分:

1)ldt 值:lru 字段的前 16bit,表示数据的访问时间戳;

2)counter 值:lru 字段的后 8bit,表示数据的访问次数。

当 LFU 策略筛选数据时,Redis 会在候选集合中,根据数据 lru 字段的后 8bit 选择访问次数最少的数据进行淘汰。当访问次数相同时,再根据 lru 字段的前 16bit 值大小,选择访问时间最久远的数据进行淘汰。

LFU 通常被应用于缓存污染问题,那什么是缓存污染呢?

在一些场景下,有些数据被访问的次数非常少,甚至只会被访问一次。当这些数据服务完访问请求后,如果还继续留存在缓存中的话,就只会白白占用缓存空间。这种情况,就是缓存污染。

1.2.7 淘汰策略总结

1)优先使用 allkeys-lru 策略,尤其是业务数据中有明显的冷热数据区分。这样,可以充分利用 LRU 这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。

2)如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分,建议使用 allkeys-random 策略,随机选择淘汰的数据就行。

3)如果业务中有置顶的需求,比如置顶新闻、置顶视频,那么,可以使用 volatile-lru 策略,同时不给这些置顶数据设置过期时间。这样一来,这些需要置顶的数据一直不会被删除,而其他数据会在过期时根据 LRU 规则进行筛选。

2 缓存异常

2.1 缓存和数据库的数据不一致

2.1.1 缓存和数据库的数据不一致是如何发生的

数据一致性包含了两种情况:

1)缓存中有数据,那么,缓存的数据值需要和数据库中的值相同;

2)缓存中本身没有数据,那么,数据库中的值必须是最新值。

不符合这两种情况的,就属于缓存和数据库的数据不一致问题了。

新增数据

如果是新增数据,数据会直接写到数据库中,不用对缓存做任何操作,此时,缓存中本身就没有新增数据,而数据库中是最新值,这种情况符合我们刚刚所说的一致性的第 2 种情况,所以,此时,缓存和数据库的数据是一致的。

删改数据

如果发生删改操作,应用既要更新数据库,也要在缓存中删除数据。这两个操作如果无法保证原子性,也就是说,要不都完成,要不都没完成,此时,就会出现数据不一致问题。

1)应用先删除缓存,再更新数据库

如果缓存删除成功,但是数据库更新失败,那么,应用再访问数据时,缓存中没有数据,就会发生缓存缺失。然后,应用再访问数据库,但是数据库中的值为旧值,应用就访问到旧值了。

2)先更新数据库,再删除缓存中的值

应用先完成了数据库的更新,但是,在删除缓存时失败了,那么,数据库中的值是新值,而缓存中的是旧值,这肯定是不一致的。这个时候,如果有其他的并发请求来访问数据,按照正常的缓存访问流程,就会先在缓存中查询,但此时,就会读到旧值了。

在更新数据库和删除缓存值的过程中,无论这两个操作的执行顺序谁先谁后,只要有一个操作失败了,就会导致客户端读取到旧值。

2.1.2 如何解决数据不一致问题

利用重试机制保证最终一致性

1)自定义重试组件

2)当应用没能成功地更新缓存值或更新数据库值时,基于重试组件进行重试处理,设置重试的时间间隔,最大重试次数。如果重试超过最大的次数,还是没有成功,就需要向业务层发送报错信息。

当这两个操作第一次执行都成功时,在有并发请求时,应用还是有可能读到不一致的数据。

情况 1:先删除缓存,再更新数据库,写+读并发

假设线程 A 删除缓存值后,还没有来得及更新数据库(比如说有网络延迟),线程 B 就开始读取数据了,那么这个时候,线程 B 会发现缓存缺失,就只能去数据库读取。这会带来两个问题:

  • 线程 B 读取到了旧值;
  • 线程 B 是在缓存缺失的情况下读取的数据库,所以,它还会把旧值写入缓存,这可能会导致其他线程从缓存中读到旧值。

等到线程 B 从数据库读取完数据、更新了缓存后,线程 A 才开始更新数据库,此时,缓存中的数据是旧值,而数据库中的是最新值,两者就不一致了。

情况 2:先更新缓存,再更新数据库,写+写并发

线程A和线程B同时更新同一条数据,更新缓存的顺序是先A后B,但是更新数据库的顺序是先B后A,导致数据库和缓存的值不一致。

情况 3:先更新 DB,再删除缓存,写+读并发

如果线程 A 删除了数据库中的值,但还没来得及删除缓存值,线程 B 就开始读取数据了,那么此时,线程 B 查询缓存时,发现缓存命中,就会直接从缓存中读取旧值。不过,在这种情况下,如果其他线程并发读缓存的请求不多,那么,就不会有很多请求读取到旧值。而且,线程 A 一般也会很快删除缓存值,这样一来,其他线程再次读取时,就会发生缓存缺失,进而从数据库中读取最新值。

情况 4:先更新 DB,再更新缓存,写+写并发

线程A和线程B同时更新同一条数据,更新数据库的顺序是先A后B,但更新缓存时顺序是先B后A,这会导致数据库和缓存的不一致。

写+读并发对业务的影响较小,而写+写并发时,会造成数据库和缓存的不一致,需要配合分布式锁使用。写请求进来时,针对同一个资源的修改操作,先加分布式锁,这样同一时间只允许一个线程去更新数据库和缓存,没有拿到锁的线程把操作放入到队列中,延时处理。用这种方式保证多个线程操作同一资源的顺序性,以此保证一致性。

2.2 购物车如何保证数据一致性

购物车为了保证接口性能,对于购物车的所有增删改查操作,都是基于缓存(主要是购物车加购商品即使丢失,影响也比较小),缓存失效,再从DB中重新加载。

异步落库方式有两种:
(1)异步线程执行落库。
(2)发送mq后消费异步落库。

短期内可以使用异步线程方式,长远来看,使用MQ异步消费落库更好。

2.2.1  MQ 消费不一致会导致什么问题

2.2.2 怎么解决 MQ 顺序消费问题

利用版本号,在购物车Hash中维护一个变量 timeStamp,用于记录当前购物车的修改时间戳。每次发送MQ时,将当前时间戳记录到消息体中,在消费的时候,对比该版本。

// todo 待完善

2.2 缓存雪崩、击穿、穿透

2.2.1 缓存雪崩

缓存雪崩是指大量的应用请求无法在 Redis 缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增。

缓存雪崩一般是由两个原因导致的,应对方案也有所不同

原因 1:缓存中大量数据同时过期,导致大量请求无法得到处理

当数据保存在缓存中,并且设置了过期时间时,如果在某一个时刻,大量数据同时过期,此时,应用再访问这些数据的话,就会发生缓存缺失。紧接着,应用就会把请求发送给数据库,从数据库中读取数据。如果应用的并发请求量很大,那么数据库的压力也就很大,这会进一步影响到数据库的其他正常业务请求处理。

解决方案 1:避免给大量的数据设置相同的过期时间

在用 EXPIRE 命令给每个数据设置过期时间时,给这些数据的过期时间增加一个较小的随机数(例如,随机增加 1~3 分钟),这样一来,不同数据的过期时间有所差别,但差别又不会太大,既避免了大量数据同时过期,同时也保证了这些数据基本在相近的时间失效,仍然能满足业务需求。

解决方案 2:服务降级

  • 当业务应用访问的是非核心数据(例如电商商品属性)时,暂时停止从缓存中查询这些数据,而是直接返回预定义信息、空值或是错误信息;
  • 当业务应用访问的是核心数据(例如电商商品库存)时,仍然允许查询缓存,如果缓存缺失,也可以继续通过数据库读取。

原因 2:Redis 实例发生故障宕机了,导致大量请求一下子积压到数据库

一般来说,一个 Redis 实例可以支持数万级别的请求处理吞吐量,而单个数据库可能只能支持数千级别的请求处理吞吐量,它们两个的处理能力可能相差了近十倍。由于缓存雪崩,Redis 缓存失效,所以,数据库就可能要承受近十倍的请求压力,从而因为压力过大而崩溃。

解决方案 1:在业务系统中实现服务熔断或请求限流机制

所谓的服务熔断,是指在发生缓存雪崩时,为了防止引发连锁的数据库雪崩,甚至是整个系统的崩溃,我们暂停业务应用对缓存系统的接口访问。再具体点说,就是业务应用调用缓存接口时,缓存客户端并不把请求发给 Redis 缓存实例,而是直接返回,等到 Redis 缓存实例重新恢复服务后,再允许应用请求发送到缓存系统。

服务熔断虽然可以保证数据库的正常运行,但是暂停了整个缓存系统的访问,对业务应用的影响范围大。为了尽可能减少这种影响,可以进行请求限流,即控制每秒进入系统的请求数,触发限流的请求直接返回请求失败。

解决方案 2:

通过主从节点的方式构建 Redis 缓存高可靠集群。如果 Redis 缓存的主节点故障宕机了,从节点还可以切换成为主节点,继续提供缓存服务,避免了由于缓存实例宕机而导致的缓存雪崩问题。

 2.2.2 击穿

缓存击穿是指,针对某个访问非常频繁的热点数据的请求,无法在缓存中进行处理,紧接着,访问该数据的大量请求,一下子都发送到了后端数据库,导致了数据库压力激增,会影响数据库处理其他请求。缓存击穿的情况,经常发生在热点数据过期失效时。

解决方案 1:对于访问特别频繁的热点数据,不设置过期时间

解决方案 2:使用分布式锁,等待第一个请求构建完缓存之后,再释放锁,使得同一时间同一个key 只能有一个连接回源 DB 查询,其他请求都要等待锁释放后查询缓存

2.2.3 穿透

缓存穿透是指要访问的数据既不在 Redis 缓存中,也不在数据库中,导致请求在访问缓存时,发生缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据。此时,应用也无法从数据库中读取数据再写入缓存,来服务后续请求,这样一来,缓存也就成了“摆设”,如果应用持续有大量请求访问数据,就会同时给缓存和数据库带来巨大压力。

缓存穿透会发生在什么时候?

1)业务层误操作:缓存中的数据和数据库中的数据被误删除了,所以缓存和数据库中都没有数据;

2)恶意攻击:专门访问数据库中没有的数据。

解决方案 1:缓存空值或缺省值

一旦发生缓存穿透,可以针对查询的数据,在 Redis 中缓存一个空值或是和业务层协商确定的缺省值(例如,库存的缺省值可以设为 0)。紧接着,应用发送的后续请求再进行查询时,就可以直接从 Redis 中读取空值或缺省值,返回给业务应用了,避免了把大量请求发送给数据库处理,保持了数据库的正常运行。

解决方案 2:使用布隆过滤器快速判断数据是否存在

2.2.3.1 布隆过滤器

布隆过滤器底层基于 hash 来实现,为0一定是不存在的,为1可能是不存在的却被判成存在了,此时要进行进一步判断。

它的优点是空间效率和查询时间都远远超过⼀一般的算法,缺点是有⼀一定的误识别率和删除困难。

2.3 Big Key

大 key 指的是存储的值(Value)非常大,常见场景:

  • 热门话题下的讨论
  • 大V的粉丝列表
  • 序列化后的图片
  • 没有及时处理的垃圾数据
  • .....

2.3.1 大 key 的影响

  • 大key会大量占用内存,在集群中无法均衡
  • Redis的性能下降,主从复制异常
  • 在主动删除或过期删除时会操作时间过长而引起服务阻塞

2.3.2 如何发现大 key

1)redis-cli --bigkeys命令。可以找到某个实例5种数据类型(String、hash、list、set、zset)的最大
key。但如果Redis 的key比较多,执行该命令会比较慢。

2)获取生产Redis的rdb文件,通过rdbtools分析rdb生成csv文件,再导入MySQL或其他数据库中进行分析统计,根据size_in_bytes统计bigkey

3)利用 iStore 平台

4)监控平台定期调用腾讯云 API 的 Redis 集群进行 Big Key 扫描,Big Key大小可配置化,默认1M 为 Big Key

2.3.3 大 key 的处理

1)单个简单的 key 存储的 value 很大,可以尝试将对象分拆成几个 key-value, 使用 mget 获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多次操作中,降低对 redis 的 IO影响。

如 商品信息以 string 方式存储在 redis 上;由于商品信息内容过大,为避免大key出现,将整个缓存的 value 按商品不同的属性维度拆分成 8 份,并将这 8 个key存储在redis上;查询一个商品信息时,通过pipline的方式将8个key查询出来后聚合返回。

2)hash, set,zset,list 中存储过多的元素,可以将这些元素分拆。
3)删除大key时不要使用 del,因为 del 是阻塞命令,删除时会影响性能。
4)使用 lazy delete (unlink命令)

删除指定的key(s),若key不存在则该key被跳过。但是,相比DEL会产生阻塞,该命令会在另一个线程中回收内存,因此它是非阻塞的。 这也是该命令名字的由来:仅将 keys 从 key 空间中删除,真正的数据删除会在后续异步操作。

3 Redis 高可用方案

3.1 主从复制

“高可用性”(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。

单机的Redis是无法保证高可用性的,当Redis服务器宕机后,它在恢复期间,是无法服务新来的数据存取请求的。

可以采用 Redis 多机和集群的方式来保证 Redis 的高可用性,将一份数据同时保存在多个实例上。即使有一个实例出现了故障,需要过一段时间才能恢复,其他实例也可以对外提供服务,不会影响业务使用。

多实例保存同一份数据,听起来好像很不错,但是,我们必须要考虑一个问题:这么多副本,它们之间的数据如何保持一致呢?数据读写操作可以发给所有的实例吗?

实际上,Redis 提供了主从库模式,以保证数据副本的一致,主从库之间采用的是读写分离的方式。

  • 读操作:主库、从库都可以接收;
  • 写操作:首先到主库执行,然后,主库将写操作同步给从库。

3.1.1 主从库同步是如何完成的呢

1)配置主从关系

当启动多个 Redis 实例的时候,它们相互之间就可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系,之后会按照三个阶段完成数据的第一次同步。

例如,现在有实例 3 (ip:172.16.19.3)和实例 5(ip:172.16.19.5),我们在实例 5 上执行以下这个命令后,实例 5 就变成了实例 3 的从库,并从实例 3 上复制数据:

replicaof  172.16.19.3  6379

2)建立 socket 连接

3.2 哨兵模式

主从库集群模式下,如果从库发生故障了,客户端可以继续向主库或其他从库发送请求,进行相关的操作,但是如果主库发生故障了,那就直接会影响到从库的同步,因为从库没有相应的主库可以进行数据复制操作了。

哨兵机制登场!

在 Redis 主从集群中,哨兵机制是实现主从库自动切换的关键机制,它有效地解决了主从复制模式下故障转移的问题。

3.2.1 哨兵机制的基本流程

哨兵其实就是一个运行在特殊模式下的 Redis 进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。

1)监控

监控是指哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。如果从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会把它标记为“下线状态”;同样,如果主库也没有在规定时间内响应哨兵的 PING 命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。

2)选主

主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库。这一步完成后,现在的集群里就有了新主库。

3)通知

在执行通知任务时,哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。

3.3 集群与分区

分区是将数据分布在多个Redis实例(Redis主机)上,以至于每个实例只包含一部分数据。

采用一致性hash算法对数据做分区

学到生无可恋之 Redis(下)相关推荐

  1. 学到生无可恋之 Redis(上)

    一把年纪了还是这么菜 本文主要学习自:Redis 核心技术与实战 学到生无可恋之 Redis(下) 1 Redis 是啥 Redis 是一个高性能的 Key-Value 数据库,key 的类型是字符串 ...

  2. 生无可恋的一叶知秋#百度刘超事件#

    郑昀 20160705(微博:http://weibo.com/yunzheng) 一,一叶知秋 就百度刘超事件,有百度人反思『六年前,一些外来的空降兵带来了不一样的价值观』. 如果就这个『六年前』的 ...

  3. CentOS7 闹心巴拉到生无可恋

    终于成功的在两个虚拟机(名字分别为StudyLinux.CentOs 64bit)上查看了,各自的IP,纪念一下.... StudyLinux是快照创建出来的,发现两个快照的两个好处,一个是创建虚拟机 ...

  4. 致学生:你让我生无可恋,我让你深陷其中!

    (一)事情的发生是这样的 我为学生准备了一组要在课堂上通过上机观察.完善的代码,提前一天,放在QQ群中让学生下载. 我给压缩文件加了一个密码,目的是需要时他们再看,好按我设计的教学目标去做事.另外,也 ...

  5. 约束你的git操作,让你生无可恋。

    用Node构建工具来约束你的git操作,让你生无可恋. 一.前言 今天看到小伙伴写的<你可能会忽略的git提交规范>,不禁想起自己那些不忍直视的提交信息,当然也不能怪自己,谁叫我能够随意的 ...

  6. wins10 系统晚上自动重启?解决办法:一旦点击就会令程序员生无可恋的msconfig——诊断启动(重启)置之死地而后生!!!

    嗯......好久没发博了..最近喜欢早起早早坐在工位前,今儿早来发现昨晚明明开了好多的文件程序,却消失不见,桌面整洁如新.. 于是怀疑是否是电脑晚上自动重启了,于是询了一下度娘,基本解决办法都类似, ...

  7. 大数据学习心得、技术路径、生无可恋的朋友加油吧!明天就是你的天下

    申明: 本文旨在为普通程序员(Java程序员最佳)提供一个入门级别的大数据技术学习路径,不适用于大数据工程师的进阶学习,也不适用于零编程基础的同学. 前言: 一.背景介绍 二.大数据介绍 正文: 一. ...

  8. Kubernetes CrashLookBackOff的问题让我生无可恋

    事情是这样的,有个客户找到我们要查看具体的日期和时间,而我们项目目前只显示了日期,我觉得这个修改很简单呐,于是就决定改完立刻部署上线让客户使用. 改代码是很简单呐, 但是部署一到关键时刻就出问题. 昨 ...

  9. 国庆的人山人海,生无可恋脸

    由中国统计网举办的投票活动正在火热进行中,本次投票活动的前五名将获得免费书籍,一起来学习吧! 如何参加:点击阅读原文,进入报名和投票界面. 点击"我要参赛" 上传照片和信息 可以手 ...

最新文章

  1. 《SQL入门经典》学习笔记
  2. 个人在 laravel 开发中使用到的一些技巧(持续更新)
  3. Jquery的跨域传输数据(JSONP)
  4. Android 进程常驻(0)----MarsDaemon使用说明
  5. Google Java编程风格指南中文版
  6. ThinkJava-复用类
  7. python的datetime模块
  8. 服务器禁止修改目录,目录服务器限制 (Sun Java System Directory Server Enterprise Edition 6.2 发行说明)...
  9. 2016蓝桥杯C++A:快速排序(详解版,很快掌握)
  10. java有没有友元函数_c++中友元函数理解与使用
  11. We FALL ASleep At Night, We Do REST Right
  12. MyEclipse开启服务器时总是进入Debug模式
  13. js 使用闭包来创建私有变量
  14. 海康、大华设备搜索大概实现原理
  15. ### LinuxCBT VBOX Edition ###
  16. 一次搞懂什么是大数据
  17. 计算机一级表格减法,怎么把表格的数字全部加减
  18. Jsp(二)——简单的Jsp程序
  19. normal + lognormal
  20. java bitwise_java – Bitwise不对一串位操作

热门文章

  1. JQuery 多选下拉列表左右移动
  2. oracle9i新建数据库的用户有哪些,oracle9i新建数据库
  3. 技术领导之路:如何从开发人员转变为团队负责人
  4. zigbee学习参考(1~42 )
  5. 用友盟社会化组件,分享到微信和新浪微博
  6. thinkphp查询条件被叠加
  7. 什么是RDD?RDD的特点?RDD与Dataframe的关系?
  8. 开课吧项目的总结以及读《图解HTTP》的总结
  9. 十多天的鸭子得了心包积液是什么原因鸭摇头晃脑不吃食怎么治疗
  10. superset二次开发