Redis的使用场景

Redis使用场景

1缓存

作为key-value形态的内存数据库,使用Redis缓存数据非常简单,只需要通过String类型将序列化后的对象存起来即可。

序列化(Serialization):是将对象的状态信息转化为可以存储或传输的形式的过程。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

不过也有需要注意的地方:

  • 必须保证不同对象的key不可以重复,并且key尽量短,一半使用类名加主键拼接而成。
  • 选择一个有序的序列化方式也很重要,目的是提高序列化效率和减少内存占用。
  • 缓存期间的数据一致性。一半有两种做法:
    1. 只在数据库查询后将对象放入缓存,如果对象发生了删除或者修改操作,直接清除对应缓存(或者设置为过期)
    2. 在数据库新增和查询后将对象放入缓存,修改后更新缓存,删除后清除对应缓存,或者设置为过期。
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_idhash的 field 为like_numbercomment_numberforward_numberview_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所有关注的用户id

  • A:follower:存放A所有粉丝的用户id

    那么通过sinter命令便可以根据A:followA:follower的交集得到与 A 互相关注的用户。当 A 进入另一个用户 B 的主页后,A:followB:follow的交集便是 A 和 B 的共同专注,A:followB: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,再通过前缀分词将这两个词分为若干个前缀索引,有:北京bbebeijinbeijing。将这些索引分别作为set的 key(例如:index:北)并存储北京的 id,倒排索引便建立好了。接下来只需要在搜索时通过关键词取出对应的set并得到其中的 id 即可。

参考文献

Redis应用场景

Redis在新浪微博中的应用