1. redis是单线程的吗?
单线程指的是网络请求模块使用了一个线程,也就是redis的worker线程是单线程,而io线程依旧是多线程的。
2. 为什么redis这么快?
- 基于内存,内存的读写速度非常快
- 数据结构简单,对数据的操作也简单
- 使用的是单线程,避免了线程上下文的切换
- 采用IO多路复用,可以采用并发的连接
3. 五大数据类型及其场景?
- String
是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型
场景:
- 存储字符串
- 数值计算(接口限流防刷、秒杀库存变化)
- 二进制(实现Serializable 接口,存储对象)
- hash
是一个键值(key => value)对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
- 存储部分变更数据,如用户信息等。
- 购物车
优点:同类数据归类整合存储,方便数据管理
相比string操作消耗内存和cpu更小
相比string更节省空间
缺点:过期功能不能使用在field上,只能使用在key上
redis集群架构下不适合大规模使用(数据倾斜)
- list
在底层是用一个双向链表来实现的,是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
- 关注列表,粉丝列表
- 存储热数据(一些热点评论放在redis中)
- set
是string类型的无序集合。集合是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。所以添加,删除,查找的复杂度都是O(1)。
- 随机事件,比如说微信小程序抽奖(spop)
- 推荐系统:有k1和k2两个人的好友集合
差集:推荐可能认识的人
交集:共同好友(微信的朋友圈)
并集:大家的好友圈
- zset
有序集合(用分值实现),和 set 一样也是string类型元素的集合,且不允许重复的成员。
- 微信朋友圈点赞
- 排行榜
排序是怎么实现的?
skiplist跳跃表,丢硬币决定层数K ,插入元素的时候,元素所占有的层数完全是随机的,通过随机算法产生:
int random_level()
{
K = 1;
while (random(0,1))
K++;
return K;
}
4. 什么是缓存穿透?怎么解决?
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时去数据库中查询,查不到数据则不写入缓存,这将导致这个一定不存在的数据每次都要到数据库中去查询,造成缓存穿透。
解决方案
(1)采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤
(2) 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
(3) 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
(4) 在某些特定场景下(登录),使用验证码。
5. 什么是缓存击穿,怎么解决?
一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。
解决方案
(1)设置热点数据永远不过期。
(2)加互斥锁(setnx)。
6. 什么是缓存雪崩,怎么解决?
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。
解决方案
(1)缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
(2)如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
(3)设置热点数据永远不过期。
网友评论