Redis 在现在互联网应用中已非常流行,在整个缓存技术领域占了很大的比重,大的互联网应用甚至部署上千个 Redis 实例。
Redis 官网,Redis 中文网,国内还有一些关于 Redis 的站点,不过描述的 Redis 版本都偏低。
工作有些年,做过的项目几乎都有用到 Redis, 零零散散也写过一些笔记,比较碎片而不成体系,现在 Redis 4.0.x 版本已稳定,新的 5.0 rc 版本也已发布,而 Redis 4.0.x 版本的一些新特性并没有系统了解和实践,知识需要演进,围绕 4.0.x版本,在实践中理解和学习。
Redis 介绍
Redis(REmote DIctionary Server) 是一个开源的基于内存键值对数据结构的服务器;可以用作数据库、缓存、消息代理。Redis 支持多种数据类型和强大的API功能,可以搭建集群和持久化数据。
Redis 基于内存的数据存储,最大程度利用了单线程、非阻塞、多路复用的I/O模型来快速处理请求,具有性能高的优点, 在高并发、低延迟的系统中使用越来越广。某些情况下也会创建线程或子线程来处理某些任务。
Redis 包含了一个简单但强大的异步事件库,称为 ae
。该库中封装了不同操作系统的polling
机制(即非阻塞I/O相关机制),如epoll, kqueue, select
等。
Redis事件模型
以 Linux 中 I/O 多路复用模型的 epoll
为例,这也是 Redis 默认使用的方式。
- 首先,调用
epoll_create
通知操作系统内核要使用epoll。 - 然后,调用
epoll_ctl
把文件描述符(FD)和关注的事件类型传给内核。 - 之后,调用
epoll_wait
等待通过epoll_ctl所设置的文件描述符上发生所关注的事件。当文件描述符被更新时,内核会向应用程序发送通知。 - 应用层唯一需要做的是为关注的事件创建事件处理函数/回调函数。
I/O多路复用:一个线程,通过记录 I/O 流的状态来同时管理多个 I/O。在polling
的过程中没有线程或子进程的创建和交互。因此,该模型的关键优点就在于它是一个轻量级上下文切换的 I/O 模型,在上下文切换上花费的代价不大。
常见应用场景
会话存储
在 Web应用服务集群部署的架构中,Session
通常需要存储在外部存储系统中,共享给集群应用。对 Redis 的访问延迟非常低,Spring Session 默认就支持 Redis 来保存 Session 数据,只需极简单的配置即可使用;Redis 对键过期的支持天然地适用于会话的超时时间管理,所以 Redis 堪称是完美的会话存储机制。
计数统计
Redis 还可用于分析和统计的场景。例如,统计在线用户数,创建 Session 时使用INCR
命令增加计数器,Session 销毁时使用DECR
命令减少计数器即可。Redis 命令都是原子的,所以无需担心竞态。
基于HASH、Sort Set、HyperLoglog
等数据类型,可还可构建更高级的计数器或统计数据捕获系统。
示例:
- 统计视频播放数,用户每播放一次视频,对应的视频播放数就自增 1。
- 真实的计数系统还需要考虑防作弊、按不同维度计数、持久化。
限速
限速场景的使用实际是计数统计的的场景扩展。例如为防止短信接口不被频繁访问,可以限制用户每分钟获取验证码的频率,如一分钟不能超过5次。
//伪代码
isExists = redis.set(key,1,"ex 60","nx");
if(isExists != null || redis.incr(key) <= 5){
//通过
}else{
//限速
}
排行榜
Redis 的有序集合数据类型可以轻构地实现一个排行榜,例如可以将投票数、购买数、收藏数、好评数等作为权重来对数据进行排序,可以使用ZREVRANGE
命令按照升序或降序返回列表,这可比诸如 MySQL 关系数据库中的实现高效的多了。
队列
Redis 的列表(list)类型支持左右两端插入和删除的操作,非常适用于实现简单的对列。还可使用RPOPLPUSH
命令实现可靠的队列(注:可靠是相对的)。
缓存
Redis 是基于内存的数据存储系统,可以用于关系数据库的前面作为缓存来使用,在查关系数据库之前先从 Redis 缓存取数据,若 Redis 中不存再从关系数据库中查询数据,并存入到 Redis 中以供下次使用,降低关系数据库的压力。
Redis 作为缓存使用,数据的大小受限于内存的大小,为了限制缓存的大小和高效地利用内存空间,可以对缓存中的记录设置过期时间或应用诸如最少使用(LRU:Least Recently Used)的收回策略。
示例:
- 先从 Redis 中获取数据,如果没有,执行第二步,有则返回。
- 如果没有,再从数据库中获取,并回写到 Redis。
- 如果回写的数据需要过期限制则加上过期时间。
最新的 N 个记录
Redis 的列表类型提供了 LTRIM
命令,可以限制列表始终包含 N 条数据:ltrim key start stop
。
相关参考
注意:本文归作者所有,未经作者允许,不得转载