一、基础知识

redis 的数据结构

参考:https://blog.csdn.net/xpsallwell/article/details/84030285
https://joonwhee.blog.csdn.net/article/details/116109674
在这里插入图片描述

  1. 字符串(String)
    redis 使用 SDS 。用来存储字符串和整形数据。对C 字符串类型的封装
    SDS结构 :char buf[] 字符数组,用于保存字符串。int len 记录buf 数组中已使用字节的数量 。int free 记录buf数组中未使用的字节数量。
    SDS的优点,1、记录的字符串的长度,查询的时间复杂度为 o(1);避免缓冲区溢出,2、可以存二进制的空字符串

  2. 列表(List)

    Redis 3.2 之前 会使用 ziplist 和 linkedlist 转换。但是3.2之后使用 quicklist。
    整体上quicklist就是一个双向链表结构,和普通的链表操作一样,插入删除效率很高,但查询的效率却是O(n)。不过,这样的链表访问两端的元素的时间复杂度却是O(1)。所以,对list的操作多数都是poll和push。
    每个quicklist节点就是一个ziplist,具备压缩列表的特性

  3. 哈希(hash)
    Hash 对象当前有两种数据结构的实现:ziplist、hashtable . 2048的值为阈值,大于等于 为hashtable ,小于为 ziplist。

    ziplist:使用压缩列表实现,每当有新的键值对要加入到哈希对象时,程序会先将保存了键的节点推入到压缩列表的表尾,然后再将保存了值的节点推入到压缩列表表尾。
    hashtable:使用字典作为底层实现,哈希对象中的每个键值对都使用一个字典键值来保存,跟 java 中的 HashMap 类似。

    hashtable查询快,但是吃内存。

  4. 集合(Set)
    redis的集合和列表都可以存储多个字符串,它们之间的不同在于,列表可以存储多个相同的字符串,而集合则通过使用散列表(hashtable)来保证自已存储的每个字符串都是各不相同的(这些散列表只有键,但没有与键相关联的值),redis中的集合是无序的。还可能存在另一种集合,那就是intset,它是用于存储整数的有序集合,里面存放同一类型的整数。

  5. 有序集合(zset)

    有序集合和散列一样,都用于存储键值对:有序集合的键被称为成员(member),每个成员都是各不相同的。有序集合的值则被称为分值(score),分值必须为浮点数。有序集合是redis里面唯一一个既可以根据成员访问元素(这一点和散列一样),又可以根据分值以及分值的排列顺序访问元素的结构。它的存储方式也有两种:

    是ziplist结构。(使用压缩列表实现,当保存的元素长度都小于64字节,同时数量小于128时,zset-max-ziplist-entries、zset-max-ziplist-value 来自定义修改)
    与上面的hash中的ziplist类似,member和score顺序存放并按score的顺序排列

    另一种是skiplist与dict的结合。

    ziplist,就是有序数组(按照score顺序),查找时间复杂度n;大数据量时是dict和skiplist,dict保存key和分值的哈希表时间复杂度1,skiplist跳表按score从小到大排序时间复杂度logN,大家都指向同一个数据块)

  6. HyperLogLog:通常用于基数统计

  7. Geo:redis 3.2 版本的新特性。可以将用户给定的地理位置信息储存起来

  8. Bitmap:位图

  9. Stream:主要用于消息队列,类似于 kafka,可以认为是 pub/sub 的改进版

memcached redis区别

1.Redis不仅仅支持简单的k/v类型的数据,同时还提供string,list,set,zset,hash等数据结构的存储
2.Redis支持数据的备份,即master-slave模式的数据备份。
3.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
4 Redis单线程(IO多路复用 内存操作 无锁) memcached多线程
5 集群(一致性hash) hashTag解决两个key分散到不同的机器上的问题

Redis 为什么是 单线程 及高并发快的原因
Redis RDB持久化,AOF持久化
redis中hash的扩容

渐进式扩容,扩容的时候 rehash 策略会保留新旧两个 hashtable 结构,查询时也会同时查询两个 hashtable,Redis会将旧 hashtable 中的内容一点一点的迁移到新的 hashtable 中,当迁移完成时,就会用新的 hashtable 取代之前的,当 hashtable 移除了最后一个元素之后,这个数据结构将会被删除(有点类似于新老库数据迁移,但是那个是复制数据只有一个在服务这个是迁移数据两个同时在服务)

redis实现分布式锁?实现事务?pipeline和mget mput的区别?大value带来的问题?

1、setnx
2、MULTI EXEC
3、pipeline是非原子的,顺序执行顺序返回结果,一次网络m次get操作,是客户端和服务端共同实现的;mget是原子的,一次网络一次mget操作,是服务端实现的
4、如果key较大,redis又是单线程,操作bigkey比较耗时,那么阻塞redis的可能性增大;也可能打满网卡;如果是集群模式下,无法做到负载均衡,导致请求倾斜到某个实例上

Redis缓存击穿面试题

Redis 分布式锁的实现
Redis 删除过期键的策略
Redis 的内存淘汰策略
Redis 的 Hash 对象底层结构
Redis 中 Hash 对象的扩容流程
Redis 的 Hash 对象的扩容流程在数据量大的时候会有什么问题吗
Redis 的持久化机制有哪几种
RDB 和 AOF 的实现原理、优缺点
AOF 重写的过程

二、集群

Redis 哨兵,复制,集群的设计原理以及区别

Redis 怎么保证高可用
Redis 的选举流程

Redis 的集群模式
Redis 集群要增加分片,槽的迁移怎么保证无损

哨兵模式的原理

三、场景

项目中使用的 Redis 版本
Redis 在项目中的使用场景

使用缓存时,先操作数据库还是先操作缓存
为什么是让缓存失效,而不是更新缓存
缓存穿透、缓存击穿、缓存雪崩
更新缓存的几种设计模式

Redis 并发竞争key的解决方案详情

第一种方案:分布式锁+时间戳

假设系统B先抢到锁,将key1设置为{ValueB 7:05}。接下来系统A抢到锁,发现自己的key1的时间戳早于缓存中的时间戳(7:00<7:05),那就不做set操作了。

第二种方案:利用消息队列

Redis 缓存穿透,缓存击穿,缓存雪崩

1.缓存穿透?缓存雪崩?缓存击穿?
缓存穿透:访问一定不存在的数据,解决方法,布隆过滤或者不存在的也缓存
缓存雪崩:缓存同时失效,解决方法通过队列排队或加锁或者随机失效时间
缓存击穿:热点key失效瞬间,解决方法设置永不失效或者队列排队或者加锁

Redis 缓存和Mysql 数据一致性的解决方案

延迟双删

Redis 缓存雪崩
热点缓存的问题

参考:
1)服务端统计出热点key,返给客户端做local-cache(失效时间30ms并且容量逐出策略),写操作强制删除本地热点key,下次读时放到local-cache中,如果有多个客户端会存在30ms的读不一致问题,注意客户端逐出这个热点key后会继续带来热点,这个时候服务端就会又返给客户端热点key了
2)服务端热点散列,每台服务端的dataServer中都划分出一个hotZone区域用来存储热点key,服务端统计出热点key返给客户端,客户端存储热点key一段时间(比如30S),要查询热点key首先随机去查一台服务端的hotZone里的这个key(以后这个客户端固定就查这个机器的hotZone),查不到再散列到该有的slot中去查然后异步写入hotZone,hotZone里的缓存数据的一致性由设置的hotZone过期时间保证;写操作不使用hotZone机制,由服务端识别出热点写key后对该key的修改进行一定时间的合并,合并后再真正写入数据

11.redis部署模式?集群模式的数据分布?

更多推荐