redis常见面试题
redis是一个高性能的key-value 数据库,它可以用来存储字符串,哈希,列表,集合,有序集合。
1. redis常见数据结构
1 String
String 是redis中最基础的数据结构,主要用在常规计数,如:统计网站访问数据量,当前在线人数等
1.应用场景
1 单值缓存
1 |
|
2 计数器
1 |
|
3. 分布式系统全局序列号
INCRBY orderId 1000 //redis批量生成序列号提升性能
1 |
|
4. 分布式锁(redisson)
- SETNX product:10001
- 执行业务操作。。。
- DEL product:10001。 //执行完业务释放锁
- SET product:10001 true ex 10 nx //防止程序意外终止导致死
SETNX( SET if Not eXists )
在指定的 key 不存在时,为 key 设置指定的值,这种情况下等同 SET 命令。当
key
存在时,什么也不做。返回值
1
如果key被设置了0
如果key没有被设置
2. hash
Hash是一个field 和value 的映射表,特别适合存储对象,比如存储用户信息,商品信息等。
1. 优缺点:
- 优点
- 同类数据归类整合储存,方便数据管理
- 相比string操作消耗内存与cpu更小
- 相比string储存更节省空间
- 缺点
- 过期功能不能使用在field上,只能用在key上
2. 应用场景
1 对象缓存
1 |
|
2 电商购物车
- 以用户id为key; 商品id为field; 商品数量为value;
- 购物车操作
- 添加商品
hset cart:user2 "apple" 1
- 增加数量
hincrby cart:user2 "apple" 3
- 商品总数
hlen cart:user2
- 删除商品
hdel cart:user2 "apple"
- 获取购物车所有商品
hgetall cart:user2
- 添加商品
3. list
list是一个链表结构,主要功能是push和pop(添加和弹出集合元素),获取一个范围的值等。常用于:粉丝列表,最新消息排行。
1. 应用场景
1. 微博消息和微信公号消息
张三关注了2 个订阅号,美食专栏和娱乐周边
美食专栏发推送
lpush msg:zhangSan "apple is yammy!"
娱乐周边发推送.
lpush msg:zhangSan "YangMi is beautiful!"
查看张三关注的最新订阅号消息.
lrange msg:zhangSan 0 5
4 set
Redis 中的set集合是无序且不可重复的,它最大的优势可以进行交集,丙级,差集等,常用来求共同好友等。
1. 应用场景
1 微信抽奖小程序
- 点击参与抽奖加入集合
sadd iphone13 zhangsan
- 查看参与抽奖所有用户
smembers iphone13
抽取count名中奖者
返回集合中2个随机数.
srandmember iphone13 2
移除并返回集合中的2个随机元素
spop iphone13 2
2. 微信微博点赞,收藏,标签
- 点赞
SADD like:{消息ID} {用户ID} - 取消点赞
SREM like:{消息ID} {用户ID} - 检查用户是否点过赞
SISMEMBER like:{消息ID} {用户ID} - 获取点赞的用户列表
SMEMBERS like:{消息ID} - 获取点赞用户数
SCARD like:{消息ID}
2.集合操作
- 交集:SINTER set1 set2 set3
- 并集:SUNION set1 set2 set3
- 差集:SDIFF set1 set2 set3
1 |
|
5 zset
在set的基础上,增加了一个权重系数score,使集合中的元素可以按照score进行有序排列,常用于实现排行榜。
1. 应用场景
1. Zset集合操作实现排行榜
点击新闻
1
ZINCRBY hotNews:20190819 1 守护香港
展示当日排行前十
1
ZREVRANGE hotNews:20190819 0 10 WITHSCORES
七日搜索榜单计算
1
2ZUNIONSTORE hotNews:20190813-20190819 7
hotNews:20190813 hotNews:20190814... hotNews:20190819[ZUNIONSTORE destination numkeys key key …]
计算给定的一个或多个有序集的并集,并存储在新的 key 中展示七日排行前十
ZREVRANGE hotNews:20190813-20190819 0 10 WITHSCORES
[ ZREVRANGE key start stop WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到低
2. redis 为什么快
Redis 是一个高性能的键值存储数据库,以其快速的读写速度而著称。其速度主要得益于以下几个关键因素:
1. 内存存储
Redis 将所有数据存储在内存中(RAM),而不是传统数据库那样存储在磁盘上。内存的读写速度远远快于磁盘,因此 Redis 的操作速度非常快。
2. 简单的数据结构
Redis 提供了一些简单且高效的数据结构,例如字符串、哈希、列表、集合、有序集合、位图、HyperLogLog、地理空间索引和流。每种数据结构都经过优化,可以快速地执行常见操作。
3. 单线程架构
Redis 使用单线程模型处理客户端请求。这种设计避免了多线程环境中的上下文切换和竞态条件,从而减少了复杂性和开销。尽管单线程可能看起来是个瓶颈,但由于 Redis 的核心操作非常快且大部分是在内存中完成的,因此单线程模型在大多数情况下性能非常高。
4. 非阻塞 I/O
Redis 使用了基于事件驱动的 I/O 多路复用机制(如 epoll 和 kqueue),使得它能够同时处理大量客户端连接而不会出现阻塞。这种非阻塞 I/O 模型使得 Redis 能够有效地处理并发请求。
5. 紧凑的内存管理
Redis 对内存使用进行了高度优化。例如,它使用了一种高效的内存分配机制来最小化内存碎片,并提供了一些数据压缩选项(如 ziplist 和 quicklist)来节省内存空间。
6. 高效的序列化和反序列化
Redis 的 RDB 和 AOF 两种持久化机制都经过优化,可以快速地将数据从内存保存到磁盘并恢复。这种高效的序列化和反序列化过程减少了持久化操作对性能的影响。
7. 高效的网络协议
Redis 使用了一个简单、高效的二进制协议 RESP(Redis Serialization Protocol),来进行客户端和服务器之间的数据交换。这个协议设计简单,解析速度非常快,进一步提高了 Redis 的性能。
8. 本地化的数据处理
Redis 提供了丰富的原子操作,可以在服务器端完成复杂的数据处理任务,减少了网络往返次数。例如,可以在 Redis 内部执行复杂的集合操作,而不需要将数据传输到客户端进行处理。
9. 数据分片(Sharding)
虽然 Redis 本身是单线程的,但它支持数据分片(sharding),即将数据分布在多个 Redis 实例上。通过这种方式,Redis 能够水平扩展,处理更大的数据量和更高的并发请求。
3. Redis 内存淘汰策略
在 Redis 中,淘汰策略(也称为内存回收策略)决定了在 Redis 实例达到内存限制时,应该如何处理新写入的数据。主要包括以下几种:
noeviction:对于写请求不再提供服务,会直接返回错误。这是默认策略。
allkeys-random:从所有key中随机移除某个键。
volatile-random:从设置了过期时间的键中随机移除某个键。
volatile-ttl:从设置了过期时间的键中移除剩余寿命最短的键(即将过期的键)。
allkeys-lru:使用LRU(Least Recently Used,最近最少使用)算法,从所有key中选取使用最少的进行淘汰。
volatile-lru:使用LRU(Least Recently Used,最近最少使用)算法,从设置了过期时间的key中移除最近最少使用的键。
allkeys-lfu: 使用LFU(Least Frequently Used,最不经常使用),从所有key中选择某段时间之内使用频次最少的键值对清除
volatile-lfu: 使用LFU(Least Frequently Used,最不经常使用),从设置了过期时间的key中选择某段时间之内使用频次最小的键值对清除掉
Redis 的淘汰算法有多种:
- 随机
- TTL: 从设置了过期时间的 Keys 中获取最早过期的 一批 Keys
- LRU (Least Recently Used) 算法: 所有的 Keys 都根据最后被访问的时间来进行排序的,所以在淘汰时只需要按照所有 Keys 的最后被访问时间,由小到大来进行即可
- LFU(Least Frequently Used)算法: 照被访问次数降序排列,访问次数相同的按最近访问时间降序排列,链表满的时候从链表尾部移出数据。
4. Redis 常见使用场景
- 缓存: DB缓存,减轻DB服务器压力, 提高系统响应。需保证缓存内容与数据库的一致性
- 分布式锁:利用Redis的
SETNX key value
这个命令获取锁,并设置过期时间。需处理:a.增加ID的复杂性,满足安全性 b.合理设置一个超时时间, 不要太长或太短,还需考虑锁续命。推荐使用第三方库redisson
- 分布式ID:利用Redis的原子性递增操作,生成分布式唯一ID。优点速度快,缺点需保证redis的高可用和持久化
- 计数器:利用incr方法,实现文章的阅读量,微博点赞数,IP限流等
- 排行榜:利用zset, 记录条目的同时,记录成绩
- 实现消息队列:利用list/set