Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;它的数据模型非常独特,用的是单线程。另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不需要转到Redis。

  Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;它的数据模型非常独特,用的是单线程。另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不需要转到Redis。

转向Redis当然也是可取的,许多开发者从一开始就把Redis作为首选数据库;但设想如果你的开发环境已经搭建好,应用已经在上面运行了,那么更换数据库框架显然不那么容易。另外在一些需要大容量数据集的应用,Redis也并不适合,因为它的数据集不会超过系统可用的内存。所以如果你有大数据应用,而且主要是读取访问模式,那么Redis并不是正确的选择。

  然而我喜欢Redis的一点就是你可以把它融入到你的系统中来,这就能够解决很多问题,比如那些你现有的数据库处理起来感到缓慢的任务。这些你就可以通过Redis来进行优化,或者为应用创建些新的功能。在本文中,我就想探讨一些怎样将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(&quot;latest.comments&quot;,start,start+num_items-1)
IF id_list.length &lt; num_items
id_list = SQL_DB(&quot;SELECT ... ORDER BY time LIMIT ...&quot;)
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的变体命令,能够在列表为空时阻塞队列。

缓存

  Redis的缓存部分值得写一篇新文章,我这里只是简单的说一下。Redis能够替代memcached,让你的缓存从只能存储数据变得能够更新数据,因此你不再需要每次都重新生成数据了。

Redis可以解决你的问题!

  现在你就可以用上Redis,让用户感到更轻松,让你的系统变得不再复杂,让你的网站反应更快。你不需要改变现有的数据库结构,使用Redis给你的框架带来新的东西,来完成那些从前认为不可能做到/很难做到的,或是成本太高的任务。

几点建议,让Redis在你的系统中发挥更大作用的更多相关文章

  1. 让Redis在你的系统中发挥更大作用的几点建议

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/105.html?1455868313 Redis在很多方面与其他数据库解决 ...

  2. 让Redis在你的系统中发挥更大作用

    Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储:它的数据模型非常独特,用的是单线程.另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不 ...

  3. 24、redis中的sentinel的作用?

    redis中的sentinel的作用? Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Re ...

  4. 【Azure Redis 缓存】Linux虚拟机中使用6380端口(SSL方式)连接Azure Redis (redis-cli & stunnel)

    问题描述 在Azure Redis的官方文档中,介绍了在Windows下,如何通过redis-cli.exe连接Redis, 包含如何配置stunnel使得通过 6380,SSL方式连接到Redis ...

  5. Redis 日志篇:系统高可用的杀手锏

    特立独行是对的,融入圈子也是对的,重点是要想清楚自己向往怎样的生活,为此愿意付出怎样的代价. 我们通常将 Redis 作为缓存使用,提高读取响应性能,一旦 Redis 宕机,内存中的数据全部丢失,假如 ...

  6. Redis在linux系统中的优化

    通常来看,Redis开发和运维人员更加关注的是Redis本身的一些配置优化,例如AOF和RDB的配置优化.数据结构的配置优化等,但是对于操作系统是否需要针对Redis做一些配置优化不甚了解或者不太关心 ...

  7. 如何在win7系统中安装redis

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/92.html?1455871954 如何在win7系统中安装redis​ ...

  8. Redis学习记录之Java中的初步使用

    1.关于Redis redis下载地址:<span style="font-family: Arial, Helvetica, sans-serif;">http:// ...

  9. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

随机推荐

  1. c# 数据写入三菱PLC

    public void Data_Write_Value(int[] m_write_data)        {            int lSize = 2; string[] Address ...

  2. cefsharp

    快速上手 js和C#互相调用. C#调用js比较容易.JS调用C#代码,现有两种方法.老方法的缺点是只支持单页,如果切换页面,原有创建的变量就失效了.新方法没有这些问题. 老方法: Cefsharp ...

  3. C#Datetimepicker出现问题及解决方法

    前几天公司用的物料管理系统出现了一个很奇怪的问题,具体的现象是:10月31号的那天,物流部的人因为之前的问题,需要将之前已经结转的9月份取消结转. ,当操作人员将10改变为9的时候,出现问题了.程序直 ...

  4. 【JavaScript】js 中一些需要注意的问题

    关于js中逻辑运算符 sort()方法 1. 关于js中逻辑运算符:|| 和 && 在js逻辑运算中,0."".null.false.undefined.NaN都会 ...

  5. 【BZOJ1049】 [HAOI2006]数字序列

    BZOJ1049 [HAOI2006]数字序列 dp好题? 第一问 第一问我会做!令\(b_i=a_i-i\),求一个最长不下降子序列. \(n-ans\)就是最终的答案. 第二问 好难啊.不会.挖坑 ...

  6. Android Parcelable using Kotlin

    Kotlin 有 extension 可以很方便的让类继承 Parcelable 接口. 项目中引入一个较新版本的 Kotlin 引入 Kotlin extensions classpath &quo ...

  7. ping端口是否开放(windows,macos,linux)

    windows中ping端口:tcping命令 1. tcping 非自带命令,首先安装tcping命令,也可以去官网:http://www.elifulkerson.com/projects/tcp ...

  8. odoo开发笔记--模型中常用的方法

    create方法在数据表中插入一条记录(或新建一个对象的resource)格式:def create(self,cr,uid,vals,context={})参数:vals:待新建记录的字段值,是一个 ...

  9. JIRA服务器搭建

    JJIRA服务器搭建 http://wiki.csdn.net/display/CSDN/Atlassian CSDN国内代理: http://atlassian.csdn.net/m/btc/atl ...

  10. eclipse下搭建shell脚本编辑器--安装开发shell的eclipse插件shelled

    具体请看: 亲测有效: http://www.cnblogs.com/shellshell/p/6122811.html