LOADING

加载过慢请开启缓存,浏览器默认开启

database redis

2023/3/21 database redis

1.特点
a.kv存储,底层使用unordered_map,可以达到O(1)存储。

b.封装了epoll,高效的网络io模型

c.高效的线程模型

d.接收客户端请求->解析请求 ->进行数据读写等操作->发生数据给客户端是单线程的

2.封装一个键值对的数据结构叫做一个entry。

所有的键先对key完成一次hash,然后对hash table的长度进行求模,然后存放对应的指针

使用链表法来解决冲突,使用头插法

3.redis的扩容,当链表过长需要扩容,然后重哈希(渐进式重哈希)

不需要一次性搬完,后台一点一点搬,等到老数据全都到新的,然后再释放老的,新元素要插入需要插入到新的hash table中

4.key的类型

key的长度可以很大

类别 可以的类型
value Stringlist,zset,hash,stree
key 可以是任意数据类型,文件、音频,最终服务器会变成string

5.Redis类型的设计

类型 特点
string 1.定义一个len(长度),一个free(多的空间)还有一个char[],有一个flag,前3位表示类型,后面5位表示长度(hdr5)
2.扩容的时候成倍地去扩容
3.

值最终都会放在redis object中

6.底层的实现

面经部分

Redis到底是单线程还是多线程?

6.0版本前网络I/O和键值对的读写都由一个线程完成。6.0后核心命令还是单线程,但是网络I/O使用了多CPU的多线程,所以还是并发安全的。(持久化、数据同步等都还是多线程)

1.Redis单线程为什么还能这么快

1.命令基于内存操作

2.命令执行是单线程操作,没有线程切换的开销

3.基于IO多路复用机制提升Redis的I/O效率(基于epoll)

4.高效的数据存储结构:全局hash表、跳表、压缩列表、链表

3.Redis底层数据如何用跳表存储

对于zset来说,可以用跳表实现

跳表怎么做的:

1.把链表每2个元素做一个冗余元素,继续向上,做成索引.

2.对于查找来说,我们从最高的索引来查找,复杂度差不多为O(logn),类似二分的思想

2.Redis key过期了为什么内存没释放

1.修改值的时候要带上过期时间,不然永远不过期

2.Redis对过期key的策略,有惰性删除和定时删除,所以可能出现过期了还没被删除的情况(默认定期删除)

3.Redi key没设置过期时间为什么被主动删除了

Redis内存淘汰策略:

当Redis超过内存最大限制的时候,会触发主动清理策略(lru\lfu删除)

4.Redis淘汰算法 LRU和LFU的区别

最近最少使用和最近被访问次数最少的,当存在大量的热点缓存数据的时候,可能LFU比较好

5.删除key的命令会阻塞Redis吗

DEL key [k..]

删除给定的一个或多个key

删除耽搁列表、集合、有序函数或者哈希表的key,时间复杂度为O(M),M为以上数据结构内的元素数量

6.Redis主从、哨兵、集群

主从模式 1.数据从主节点备份到从节点,主节点挂了,从节点变为主节点
哨兵模式 1.增加一些哨兵节点(本质也是redis实例)
2.对每一个redis主从进行监听
3.如果主节点挂了,哨兵感知到,然后重新选举出一个新的节点
4.随后客户端可以访问新的主节点
5.可以自动化,但是主从切换比较慢
提供服务只有一个节点支持,无法满足大并发
Redis单节点不要超过10G,不然影响恢复
集群模式 1.多个小的主从节点统一成一个大的来对外处理
2.不会把所有数据放在一个节点,而是分片存储
不要超过1000个节点

7.Redis集群数据哈希分片算法

集群客户端有一个哈希分片算法,逻辑上划分为16384个槽位,然后每个节点分别划分一片槽位

HASH_SLOT=CRC16(key) mod 16384

8.Redi执行命令阻塞循环

Random KEY,如果有大量的key过期了,然后又有可能都拿到过期的

slave上执行random key,因为slave不会主动删除,需要master同步之后再会删除

9.Redis主从切换导致缓存雪崩

假设主节点的机器时钟比从节点走的很慢,这个时候发生主从切换之后,在主节点认为没过期的可能从节点过期了,切换之后,出问题。

10.Redis持久化

方法名称 特点 优点 缺点
RDB快照持久化 在指定的时间内,把内存中的数据库快照写入磁盘,实际的过程是fork一个子进程,先把数据写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储 1.整个数据库只包括一个文件dump.rdb,方便与持久化
2.容灾性好,方便备份
3.性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化,主进程不会进行任何IO操作
1.数据安全性低,RDB是间隔一段时间进行持久化,如果持久化期间redis发生故障,会发生数据丢失
2.由于RDB借助fork来完成持久化工作,所以如果数据集比较大,会导致整个服务停止1秒
AOF(append file) 以日志的形式,类似redolog 1.数据安全。2.通过append模式写文件,即使宕机也不会破坏已经存在的内容。3.定期对AOF进行重写,达到压缩的目的 1.AOF文件比RDB文件大2.比rdb启动效率低。3.运行效率没有RDB高

11.Redis主从复制风暴

主节点可能要一次性连多个从节点来传输快照,导致压力比较大

12.主从频繁切换

网络抖动导致频繁的主从切换,需要使用timeout来进行主从切换的判断

13.Redis集群为什么至少需要3个master节点

3个以上才能选举成功

14.Redis集群为什么需要奇数个节点

新master的选举需要半数同意

15.Redis批量操作命令

必须落在同一个节点,不然会报错

16.缓存穿透,缓存击穿、缓存雪崩

对于一个请求来说,如果redis中存在,直接返回,否则去数据库中查,然后添加入redis

布隆过滤器:不在一定不在,在可能有问题(有碰撞),只能加数据不能减数据

类别 特点 策略
缓存穿透 1.缓存中查不到,数据库中也查不到。然后不断地拿这条sql来攻击 1.进行参数校验。
2.把数据库中没有查到结果的数据也写入缓存
3.引入布隆过滤器(可以判断是否在集合当中,通过哈希散列来做),在访问redis前对query进行校验
缓存击穿 DB中有,缓存中没有,一般出现在缓存失效或者过期的情况,高并发场景下数据库压力瞬间增大 1.设置缓存热点数据永不过期,在逻辑上设置一个过期时间
2.加载db的时候需要防止并发,每次只有一个线程可以写
缓存雪崩 1.缓存大面积过期,导致请求都被转发到DB 1.把缓存的失效时间分散开
2.对热点数据设置永不过期

17. Redis的partition

Redis 的分区(partition)是指将 Redis 数据库中的数据分散到多个物理节点或者服务器上,以提高数据库的性能、可扩展性和可用性。

Redis 支持多种分区模式,包括:

哈希分区:Redis 将键值对根据键名进行哈希,然后将哈希结果分散到多个物理节点或者服务器上。这种分区模式可以将键值对均匀分布到多个节点上,从而提高性能和可扩展性。但是,这种分区模式不能保证数据在所有节点上的复制,也不能保证数据在所有节点上的一致性。

范围分区:Redis 将数据按照键名的范围进行分区,每个节点或者服务器负责一定范围内的键值对。这种分区模式可以保证数据在所有节点上的复制和一致性,但是在键名分布不均匀时,可能会导致节点负载不均衡的问题。

副本分区:Redis 将数据进行复制,并将复制品存储在多个物理节点或者服务器上。这种分区模式可以保证数据的高可用性和容错性,但是可能会增加存储和网络带宽的开销。

Redis 分区可以在多个物理节点或者服务器上同时进行读写操作,从而提高数据库的并发性能和可用性。但是,在分区模式下,数据的管理和维护变得更加复杂,需要进行节点之间的数据同步、负载均衡、故障恢复等操作。因此,在设计和实现 Redis 分区时,需要考虑到数据库的特性、数据的分布和访问模式、节点的规模和配置等因素。