Redis总结篇(附Redis常见面试题)

475 阅读3分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

前言

前面几篇文章分析了Redis数据结构,Redis主从复制,哨兵模式,Cluster分片方案,本文将以问题的形式对这些内容进行一个总结。

一、Redis支持哪些数据结构,以及底层的实现

数据结构类型底层数据结构使用场景
stringsds(简单动态字符串)1、分布式锁2、缓存数据3、计数器4、全局id 5、bitmap统计数据
hasherhashtableziplist(压缩列表)1、redission存储分布式锁2、存储行数据
zsetziplistskiplist(多层级跳表)1、排行榜
setintset(存整型)hashtable(存非整型)1、用户信息2、用户点赞关注信息
listquicklist和ziplist组合1、内存级消息队列,栈
geospatial indexesgeoPoint数组存储地理位置,如经纬度
hyperloglogs基于string实现1、大数据不精确统计数据

二、Redis为什么这么快?

1、key的全部操作基于内存存储和操作

2、k/v存储结构,时间复杂度O(1)

3、单线程操作,避免线程上下文切换,上下文切换需要消耗系统资源。这里的单线程是指处理客户端的请求是单线程的,可以把它叫做主线程。单线程的好处?

  • 没有创建线程,销毁销毁线程的开销。
  • 避免了上下文切换,cpu开销。
  • 避免线程之间竞争问题,比如加锁和解锁。死锁等问题。

4、数据据结构精细化设计,比如sds的惰性回收策略,预先分配策略,三种编码类型,hashes,zset多种编码切换,基于字节层面优化存储性能,不浪费一字节内存。

5、非阻塞多路复用io模型 

三、Redis内存淘汰策略

淘汰策略淘汰key的范围
Volatile-lru设置了过期时间的最近最少使用的key,非传统lru算法,基于采样实现
All-lru所有的key里面最近最少使用key
Volatile-lfu设置了过期时间的使用频率最低的key,基于概率实现
All-lfu所有的key里面使用频率最低的key
Volatile-random设置了过期时间的随机的key
All-random所有key里面随机的key

四、Redis实现分布式锁

1、为什么需要分布式锁?

由于在分布式系统中,跨jvm进程之间对共享资源进行互斥访问时,synchronized,lock无法实现。

2、实现分布式锁需要考虑的问题?

  • 互斥
  • 防止死锁
  • 性能
  • 可重入锁方式
  • 锁续约 看门狗,一个线程,1/3的时间去续约。

3、Redission是怎么用redis实现分布式锁的?

redission加锁形式,使用hashes结构。 

通过lua脚本将value设置成加锁的次数,实现可重入锁特性。

释放锁就value减少,直到达到0后,删除key。

释放锁

加锁成功后开启续期定时任务

使用了netty中的时间轮组件来创建定时任务

Redission实现的分布式锁存在什么问题呢?

最大的问题,就是如果你对某个redis master实例,写入了myLock这种锁key的value,此时会异步复制给对应的master slave实例。但是这个过程中一旦发生redis master宕机,主备切换,redis slave变为了redis master。接着就会导致,客户端2来尝试加锁的时候,在新的redis master上完成了加锁,而客户端1也以为自己成功加了锁。此时就会导致多个客户端对一个分布式锁完成了加锁。这时系统在业务上一定会出现问题,导致脏数据的产生。所以这个就是redis cluster,或者是redis master-slave架构的主从异步复制导致的redis分布式锁的最大缺陷:在redis master实例宕机的时候,可能导致多个客户端同时完成加锁。

解决办法是什么呢?

官方是推荐使用红锁算法来解决。

五、​Redis哨兵和Cluster有哪些区别?

1、Redis哨兵弥补了Redis主从复制的缺陷,补充了自动故障转移的功能

2、Cluster则弥补了Redis哨兵机制和Redis主从复制中master单节点问题,提供了redis分片的能力​,将请求压力和存储压力分摊到多台Redis服务器上。​