ans: 最新的Redis采用并发安全的单线程的数据持久化,和高效率的多线程的网络请求和数据操作。
Redis6.0以前是单线程。这的单线程是说其网络I/O和键值对读写是由一个线程完成的。所以Redis是并发安全的。
Redis6.0引入了多线程,是对网络请求过程采用了多线程(利用CPU的多核实现),而其键值对读写依然采用并发安全的单线程处理。
所以Redis依然是并发安全的。
也就是说只有网络请求模块和数据操作模块是单线程的,而其数据持久化和集群数据同步是由额外的线程执行的。
---request---> <---request---
Redis客户端01 Redis服务器 Redis客户端02
<---response--- ---response--->
ans: 采用高效数据存储结构,基于内存操作,命令单线程操作,基于高效的I/O多路复用机制。
(1)Redis基于纯内存操作,一条命令在内存里操作时间是几十纳秒
(2)Redis命令的执行是单线程操作,没有线程切换开销
(3)Redis基于I/O多路复用机制来提升I/O利用率
(4)Redis具有高效的数据存储结构: 全局Hash表,以及跳表,压缩列表,链表等多种高效数据结构。
Hash表由一维的数组和二维的链表组成,
时间复杂度是一个常量O(1),是一种效率相当高的一种存储结构。
ans: 跳表是类似于折半查找的优化的链表
跳表: 由有序链表优化而来,每两个元素使用第一个元素作为冗余元素,索引元素。
索引元素也每两个找第一个作为索引,直到生成第一层是第一个元素的唯一索引
从跳表最左侧的冗余元素开始查。
类似于折半查找。
ans: 修改未设置过期时间导致过期时间丢失
使用Redis时常使用SET命令,
SET命令除了可以设置键值对key-value以外,还可以设置key的过期时间:
- > SET fhe kiri lulu EX 120
-
- OK
-
- >TTL fhe
-
- 117
此时如果你想修改key的值,但是只是单纯使用SET命令,而没有加上过期时间参数,那么这个key的过期时间就会被擦除,也就是这个key永远不过期了。
- >SET fhe fhe123
- OK
- > TTL fhe
- -1 // 改值不设置过期时间,那么这个key永远不会过期了!
所以,导致这个问题的原因在于:SET命令如果不设置过期时间,那么Redis会默认擦除该key的工期时间。
如果你发现Redis的内存持续增长,而且很多key原来设置了过期时间,后来发现过期时间丢失,就很可能是修改时没有设置过期时间导致其过期时间被擦除。
这时,你的Redis中就会存在大量不过期的key,从而会消耗过多的内存资源。
所以你在使用SET命令时,如果刚开始就设置了过期时间,那么之后修改了这个key,则也要务必加上过期时间的参数,避免过期时间丢失问题。