Redis耗费空间比较大

Redis 总结03_redis

Redis 总结03_redis_02

Redis 总结03_redis_03


Redis 总结03_redis_04

Redis 总结03_redis_05

Redis 总结03_redis_06


Redis 总结03_redis_07

24 | 替换策略:缓存满了怎么办?

Redis 总结03_redis_08

Redis 总结03_redis_09

Redis 总结03_redis_10

Redis 总结03_redis_11

Redis 总结03_redis_12

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


Redis 总结03_redis_13

缓存和数据库  数据一致性

Redis 总结03_redis_14

Redis 总结03_redis_15

Redis 总结03_redis_16

Redis 总结03_redis_17

Redis 总结03_redis_18

针对大量数据同时失效带来的缓存雪崩问题,我给你提供两种解决方案。

Redis 总结03_redis_19

Redis 总结03_redis_20

Redis 总结03_redis_21

一旦发生了缓存雪崩,数据库的每秒请求数突然增加到每秒 1 万个,此时,我们就可以启动请求限流机制,在请求入口前端只允许每秒进入系统的请求数为 1000 个,再多的请求就会在入口前端被直接拒绝服务。所以,使用了请求限流,就可以避免大量并发请求压力传递到数据库层。

Redis 总结03_redis_22

Redis 总结03_redis_23

Redis 总结03_redis_24

Redis 总结03_redis_25

Redis 总结03_redis_26

Redis 总结03_redis_27

Redis 总结03_redis_28

Redis 总结03_redis_29

Redis 总结03_redis_30

Redis 总结03_redis_31

Redis 总结03_redis_32

Redis 总结03_redis_33

Redis 总结03_redis_34

Redis 总结03_redis_35

Redis 总结03_redis_36

Redis 总结03_redis_37

Redis 总结03_redis_38

Redis 总结03_redis_39

Redis 总结03_redis_40

Redis 总结03_redis_41

Redis 总结03_redis_42

Redis 总结03_redis_43

Redis 总结03_redis_44

Redis 总结03_redis_45

对于这种情况,在命令入队时,Redis 就会报错并且记录下这个错误。此时,我们还能继续提交命令操作。等到执行了 EXEC 命令之后,Redis 就会拒绝执行所有提交的命令操作,返回事务失败的结果。这样一来,事务中的所有命令都不会再被执行了,保证了原子性。

Redis 总结03_redis_46

Redis 总结03_redis_47

Redis 总结03_redis_48

Redis 总结03_redis_49

Redis 总结03_redis_50

pipeline不保证原子,lua保证

+++++++++++++++++++++++++++++++++++++++++++

 Redis 总结03_redis_51

Redis 总结03_redis_52

Redis 总结03_redis_53

Redis 总结03_redis_54


+++++++++++++++++++++++++++++++++++++++++


Redis 总结03_redis_55

Redis 总结03_redis_56

Redis 总结03_redis_57

Redis 总结03_redis_58

Redis 总结03_redis_59

Redis 总结03_redis_60


Redis 总结03_redis_61


++++++++++++++++++++++++++++++++++++++++++++

Redis秒杀

Redis 总结03_redis_62

Redis 总结03_redis_63

Redis 总结03_redis_64

++++++++++++++++++++++++++++++++++++++++++++++++++

Redis 6.0 多线程

Redis 总结03_redis_65

Redis 总结03_redis_66

Redis 总结03_redis_67


四、为什么redis6.0引入多线程?

Redis6.0中的多线程,也只是针对网络请求过程采用了多线程,而数据的读写命令仍然是单线程处理的。

为什么呢?不是多路复用技术已经大大提高IO利用率了吗?

主要对Redis有着更高的要求。

根据测算,Redis 将所有数据放在内存中,内存的响应时长大约为 100 纳秒,对于小数据包,Redis 服务器可以处理 80,000 到 100,000 QPS,这么高的对于 80% 的公司来说,单线程的 Redis 已经足够使用了。

但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的 QPS。

为了提升QPS,很多公司的做法是部署Redis集群,并且尽可能提升Redis机器数。但是这种做法的资源消耗是巨大的。

而经过分析,限制Redis的性能的主要瓶颈出现在网络IO的处理上,虽然之前采用了多路复用技术。但是我们前面也提到过,多路复用的IO模型本质上仍然是同步阻塞型IO模型

下面是多路复用IO中select函数的处理过程:

 Redis 总结03_redis_68

从上图我们可以看到,在多路复用的IO模型中,在处理网络请求时,调用 select (其他函数同理)的过程是阻塞的,也就是说这个过程会阻塞线程,如果并发量很高,此处可能会成为瓶颈。

虽然现在很多服务器都是多个CPU核的,但是对于Redis来说,因为使用了单线程,在一次数据操作的过程中,有大量的CPU时间片是耗费在了网络IO的同步处理上的,并没有充分的发挥出多核的优势。

如果能采用多线程,使得网络处理的请求并发进行,就可以大大的提升性能。多线程除了可以减少由于网络 I/O 等待造成的影响,还可以充分利用 CPU 的多核优势。

所以,Redis 6.0采用多个IO线程来处理网络请求,网络请求的解析可以由其他线程完成,然后把解析后的请求交由主线程进行实际的内存读写。提升网络请求处理的并行度,进而提升整体性能。

但是,Redis 的多 IO 线程只是用来处理网络请求的,对于读写命令,Redis 仍然使用单线程来处理。

那么,在引入多线程之后,如何解决并发带来的线程安全问题呢?

这就是为什么我们前面多次提到的"Redis 6.0的多线程只用来处理网络请求,而数据的读写还是单线程"的原因。

Redis 6.0 只有在网络请求的接收和解析,以及请求后的数据通过网络返回给时,使用了多线程。而数据读写操作还是由单线程来完成的,所以,这样就不会出现并发问题了。

场景题目 

Redis里有1亿个key,其中有10w个key是以某个固定的已知前缀开头的,如何将它们全部找出来?

   keys指令性能差,会导致单线程的Redis阻塞;所以需要使用scan指令,这个可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,做去重复就可以了。但是花费时间比keys指令长

scan命令的特点:

1、复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程;

2、提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是一个 hint,返回的结果可多可少;

3、同 keys 一样,它也提供模式匹配功能;

4、服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;

5、返回的结果可能会有重复,需要客户端去重复,这点非常重要;

6、遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;

7、单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零

Redis 总结03_redis_69

Redis 分区,则不能使用Redis事务,不能对两个集合取交集

Redis中 Jedis和Redisson对比有什么优缺点?

Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能简单,不支持字符串操作,不支持排序,事务,管道,分区等Redis特性