Redis使用场景
1缓存
作为key-value形态的内存数据库,使用Redis缓存数据非常简单,只需要通过String
类型将序列化后的对象存起来即可。
序列化(Serialization):是将对象的状态信息转化为可以存储或传输的形式的过程。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
不过也有需要注意的地方:
- 必须保证不同对象的key不可以重复,并且key尽量短,一半使用类名加主键拼接而成。
- 选择一个有序的序列化方式也很重要,目的是提高序列化效率和减少内存占用。
- 缓存期间的数据一致性。一半有两种做法:
- 只在数据库查询后将对象放入缓存,如果对象发生了删除或者修改操作,直接清除对应缓存(或者设置为过期)
- 在数据库新增和查询后将对象放入缓存,修改后更新缓存,删除后清除对应缓存,或者设置为过期。
2消息队列
Redis中的list
的数据结构实现的是双向链表,所以可以非常便捷的应用于消息队列(生产者/消费者模型)。消息的生产者只需要通过lpush将消息放入list,消费者可以通过rpop取出该消息,并且保证消息的有序性。
如果需要实现带有优先级的消息队列也可以选择sorted list
。而pub/sub
也可以作为发布者/订阅者模型的消息。由于Redis带有持久化功能,无需担心由于服务器故障导致消息丢失的情况发生。
有序集合的对象编码可以是ziplist或者skiplist
3时间轴
list作为双向链表,不光可以作为队列使用,如果将它用作栈便可以成为一个公用的时间轴。当用户发完微博后,都通过lpush将它存放在一个key为LATEST_WEIBO的list中。之后便可以通过lrange取出最新的微博。
4排行榜
使用sortedset可以轻松打造一个热度排行榜,zrevrangebyscore可以得到以分数倒序排列的序列,zrank可以得到成员在该排行榜中的作用。
5计数器
计数功能应该是最适合redis的使用场景之一,高频率读写特性完全可以发挥redis作为内存数据库的高效。在Redis的数据结构中,string, hash, 和sorted set都提供了incr方法用于原子性自增操作,下面举例说明它们各自的应用场景:
如果应用需要显示每天注册用户数,便可以使用
String
作为计数器,设定一个名为REGISTERED_COUNT_TODAY
的 key,并在初始化时给它设置一个到凌晨 0 点的过期时间,每当用户注册成功后便使用incr
命令使该 key 增长 1,同时当每天凌晨 0 点后,这个计数器都会因为 key 过期使值清零。每条微博都有点赞数,评论数,转发数和浏览数四条属性,这是用
hash
进行计数会更好,该计数器的key设为为weibo:weibo_id
,hash
的 field 为like_number
、comment_number
、forward_number
和view_number
,在对应操作后通过hincrby
使hash 中
的 field 自增。如果应用有一个发帖排行榜的功能,便选择
sorted set
吧,将集合的 key 设为POST_RANK
。当用户发帖后,使用zincrby
将该用户 id 的 score 增长 1。sorted set
会重新进行排序,用户所
在排行榜的位置也就会得到实时的更新。
6好友关系
一篇介绍微博Redis应用的PPT中,其中提到微博的Redis主要用在计数和好友关系两方面,
《Redis设计与实现》中作者最开始使用Redis中的set
是因为传统数据库无法计算集合的交集。
对于一个用户A,将它的关注和粉丝的用户id都存放到两个set中:
A:follow
:存放A所有关注的用户idA:follower
:存放A所有粉丝的用户id那么通过
sinter
命令便可以根据A:follow
和A:follower
的交集得到与 A 互相关注的用户。当 A 进入另一个用户 B 的主页后,A:follow
和B:follow
的交集便是 A 和 B 的共同专注,A:follow
和B:follower
的交集便是 A 关注的人也关注了 B。
7分布式锁
在Redis2.6.12版本开始,string
的set命令增加了三个参数:
Ex
:设置键的过期时间(s)Px
: 设置键的过期时间(ms)NX
|XX
:当设置为NX
时,仅当key存在才进行操作,设置为xx时,仅当key不存在才会进行操作,这个操作是原子性的,可以简单实现一个分布式锁,例如:1
set key "lock" Ex 1 xx
如果操作返回false,说明key的添加不成功,即当前有人占用这把锁,而如果返回true,说明得到了锁,可以继续进行操作,操作后通过
del
释放掉锁,并且即使程序因为某些原因没有释放锁,设置了过期时间,所以该锁也会在1秒后自动释放。
8倒排索引
倒排索引是构造搜索功能的最常见的方式,Redis中也可以通过set建立倒排索引,这里以简单的拼音+前缀搜索城市功能举例:
假设一个城市北京
,通过拼音词库将北京
转为beijing
,再通过前缀分词将这两个词分为若干个前缀索引,有:北
、北京
、b
、be
…beijin
和beijing
。将这些索引分别作为set
的 key(例如:index:北
)并存储北京
的 id,倒排索引便建立好了。接下来只需要在搜索时通过关键词取出对应的set
并得到其中的 id 即可。