redis的常见使用场景


一、显示最新的项目列表redis

下面这个语句经常使用来显示最新项目,随着数据多了,查询毫无疑问会愈来愈慢。算法

SELECT * FROM foo WHERE ... ORDER BY time DESC LIMIT 10数据库

在Web应用中,“列出最新的回复”之类的查询很是广泛,这一般会带来可扩展性问题。这使人沮丧,由于项目原本就是按这个顺序被建立的,但要输出这个顺序却不得不进行排序操做。缓存

相似的问题就能够用Redis来解决。好比说,咱们的一个Web应用想要列出用户贴出的最新20条评论。在最新的评论边上咱们有一个“显示所有”的连接,点击后就能够得到更多的评论。服务器

咱们假设数据库中的每条评论都有一个惟一的递增的ID字段。并发

咱们可使用分页来制做主页和评论页,使用Redis的模板,每次新评论发表时,咱们会将它的ID添加到一个Redis列表:异步

LPUSH latest.comments <ID>函数

 

咱们将列表裁剪为指定长度,所以Redis只须要保存最新的5000条评论:高并发

LTRIM latest.comments 0 5000性能

每次咱们须要获取最新评论的项目范围时,咱们调用一个函数来完成(使用伪代码):

FUNCTION get_latest_comments(start, num_items):  
    id_list = redis.lrange("latest.comments",start,start+num_items - 1)  
    IF id_list.length < num_items  
        id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")  
    END  
    RETURN id_list  
END


     

 

这里咱们作的很简单。在Redis中咱们的最新ID使用了常驻缓存,这是一直更新的。可是咱们作了限制不能超过5000个ID,所以咱们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才须要去访问数据库。

咱们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其余类型数据库)只是在用户须要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。

二、删除与过滤

咱们可使用LREM来删除评论。若是删除操做很是少,另外一个选择是直接跳过评论条目的入口,报告说该评论已经不存在。

有些时候你想要给不一样的列表附加上不一样的过滤器。若是过滤器的数量受到限制,你能够简单的为每一个不一样的过滤器使用不一样的Redis列表。毕竟每一个列表只有5000条项目,但Redis却可以使用很是少的内存来处理几百万条项目。

三、排行榜相关

另外一个很广泛的需求是各类数据库的数据并不是存储在内存中,所以在按得分排序以及实时更新这些几乎每秒钟都须要更新的功能上数据库的性能不够理想。

典型的好比那些在线游戏的排行榜,好比一个Facebook的游戏,根据得分你一般想要:

- 列出前100名高分选手

- 列出某用户当前的全球排名

这些操做对于Redis来讲小菜一碟,即便你有几百万个用户,每分钟都会有几百万个新的得分。

模式是这样的,每次得到新得分时,咱们用这样的代码:

ZADD leaderboard <score> <username>

你可能用userID来取代username,这取决于你是怎么设计的。

获得前100名高分用户很简单:ZREVRANGE leaderboard 0 99。

用户的全球排名也类似,只须要:ZRANK leaderboard <username>。

四、按照用户投票和时间排序

排行榜的一种常见变体模式就像Reddit或Hacker News用的那样,新闻按照相似下面的公式根据得分来排序:

score = points / time^alpha

所以用户的投票会相应的把新闻挖出来,但时间会按照必定的指数将新闻埋下去。下面是咱们的模式,固然算法由你决定。

模式是这样的,开始时先观察那些多是最新的项目,例如首页上的1000条新闻都是候选者,所以咱们先忽视掉其余的,这实现起来很简单。

每次新的新闻贴上来后,咱们将ID添加到列表中,使用LPUSH + LTRIM,确保只取出最新的1000条项目。

有一项后台任务获取这个列表,而且持续的计算这1000条新闻中每条新闻的最终得分。计算结果由ZADD命令按照新的顺序填充生成列表,老新闻则被清除。这里的关键思路是排序工做是由后台任务来完成的。

五、处理过时项目

另外一种经常使用的项目排序是按照时间排序。咱们使用unix时间做为得分便可。

模式以下:

- 每次有新项目添加到咱们的非Redis数据库时,咱们把它加入到排序集合中。这时咱们用的是时间属性,current_time和time_to_live。

- 另外一项后台任务使用ZRANGE…SCORES查询排序集合,取出最新的10个项目。若是发现unix时间已通过期,则在数据库中删除条目。

六、计数

Redis是一个很好的计数器,这要感谢INCRBY和其余类似命令。

我相信你曾许屡次想要给数据库加上新的计数器,用来获取统计或显示新信息,可是最后却因为写入敏感而不得不放弃它们。

好了,如今使用Redis就不须要再担忧了。有了原子递增(atomic increment),你能够放心的加上各类计数,用GETSET重置,或者是让它们过时。

例如这样操做:

INCR user:<id> EXPIRE

user:<id> 60

你能够计算出最近用户在页面间停顿不超过60秒的页面浏览量,当计数达到好比20时,就能够显示出某些条幅提示,或是其它你想显示的东西。

七、特定时间内的特定项目

另外一项对于其余数据库很难,但Redis作起来却垂手可得的事就是统计在某段特色时间里有多少特定用户访问了某个特定资源。好比我想要知道某些特定的注册用户或IP地址,他们到底有多少访问了某篇文章。

每次我得到一次新的页面浏览时我只须要这样作:

SADD page:day1:<page_id> <user_id>

固然你可能想用unix时间替换day1,好比time()-(time()%3600*24)等等。

想知道特定用户的数量吗?只须要使用SCARD page:day1:<page_id>。

须要测试某个特定用户是否访问了这个页面?SISMEMBER page:day1:<page_id>。

八、实时分析正在发生的状况,用于数据统计与防止垃圾邮件等

咱们只作了几个例子,但若是你研究Redis的命令集,而且组合一下,就能得到大量的实时分析方法,有效并且很是省力。使用Redis原语命令,更容易实施垃圾邮件过滤系统或其余实时跟踪系统。

九、Pub/Sub

Redis的Pub/Sub很是很是简单,运行稳定而且快速。支持模式匹配,可以实时订阅与取消频道。

十、队列

你应该已经注意到像list push和list pop这样的Redis命令可以很方便的执行队列操做了,但能作的可不止这些:好比Redis还有list pop的变体命令,可以在列表为空时阻塞队列。

现代的互联网应用大量地使用了消息队列(Messaging)。消息队列不只被用于系统内部组件之间的通讯,同时也被用于系统跟其它服务之间的交互。消息队列的使用能够增长系统的可扩展性、灵活性和用户体验。非基于消息队列的系统,其运行速度取决于系统中最慢的组件的速度(注:短板效应)。而基于消息队列能够将系统中各组件解除耦合,这样系统就再也不受最慢组件的束缚,各组件能够异步运行从而得以更快的速度完成各自的工做。

此外,当服务器处在高并发操做的时候,好比频繁地写入日志文件。能够利用消息队列实现异步处理。从而实现高性能的并发操做。

相关文章
相关标签/搜索