Redis字符串作为特殊数组

时间:2015-08-14 12:15:55

标签: redis

我正在创建一个由客户端(webbrowsers)通过AJAX检索的事件系统。对于事件存储,我只想使用Redis。

我了解了Redis中的一些不错的功能,例如 EXPIRE - 一个允许自动执行某种垃圾收集工作的命令,因此不需要自己实现等效的(提供)该解决方案将与Redis一样高效)。确实,非常好,我将使用它。

但是,我偶然发现了一个问题,即如何存储与Redis的字符串数据类型的unix时间戳编号相关的问题。此号码应用于:

  • 订购整个“数据集” - 所有事件
  • 最重要的是,只获取高于给定数字的事件记录(字符串)(即> given_time)

所以简而言之,我希望有一些像Strings一样的 SCORE 功能,但不一定与Redis中的排序集一起使用。而且我不喜欢这里提出的解决方案实际使用集合:Redis: possible to expire an element in an array or sorted set?

相反,我只需要创建一个非常常见的事件队列来发送给客户端。这个队列应该:

  • 将要采取的事件(通过AJAX)存储到“队列”中 - 为此我想使用简单的Redis字符串
  • 仅提供 那些相关时间戳高于上一次请求的事件
  • 在“发布”1小时后过期(删除)事件(因为否则,不必要的数据量将增加到无穷大,当然)

所以我现在的解决方案是:

  • 使用Redis Strings的“namespaced”键:EVENT:{unix-time-stamp}:eventName,value as event's content
  • 按键模式获取所有字符串(事件):EVENT:*
  • 通过一些 Redis命令获取最新的字符串(事件)(我不知道):EVENT:* WHERE“*”> given_unixtime_number

但是如何创建:

"WHERE "*" > given_unixtime_number"

参与Redis?

修改 当然,我不打算坚持上述解决方案。例如,如果需要,我可以使用非命名空间的字符串创建一个单独的Redis实例(例如,仅将{unix-time-stamp}作为键,而不使用EVENT和eventName部分)。

1 个答案:

答案 0 :(得分:1)

您确实想使用排序集,以及如何:

  

使用"命名空间" Redis字符串的键:EVENT:{unix-time-stamp}:eventName,值为事件的内容

我不确定eventName的用途是什么,但这看起来不错。您还可以跳过EVENT前缀并为每个密钥保存5个字节。如果您有大量事件,请考虑使用hash" buckets"如http://redis.io/topics/memory-optimization#using-hashes-to-abstract-a-very-memory-efficient-plain-key-value-store-on-top-of-redis所述。

  

按键模式获取所有字符串(事件):EVENT:*

这实际上是一个关键点 - 你如何有效地做到这一点?答案:不要使用KEYSSCAN,而是保留"索引"所有这些钥匙。常规(即未分类)设置对于这些是足够好的,但由于您需要基于纪元的排序,排序集是正确的选择。

我们称之为排序集 events。每当您创建新活动时,例如SET EVENT:123:foo bar,使用纪元作为得分events将该事件的关键名称添加到ZADD events 123 EVENT:123:foo

  

通过一些Redis命令获取最新的Strings(事件)(我不知道):EVENT:* WHERE" *" > given_unixtime_number

命令为ZRANGEBYSCORE(或ZREVRANGEBYSCORE,具体取决于您希望如何排序结果),如下所示:ZRANGEBYSCORE events (given_unixtime_number +inf。这将返回所有相关的关键名称,然后您需要GET它们(可能的优化是将它包装在Lua脚本中以来回保存)。请注意使用左括号(()表示独占搜索(即>而不是>=

管理:"费用"这种方法的一个方面是你必须维护events"索引"。通过在events上使用ZREMBYSCORE命令,您可以轻松删除过期的元素 - 定期(例如每1秒)或根据您的需要执行的每个操作。实际事件'密钥可以是EXPIRE d(尽管您可能会在events 已排序的设置中持续过期的密钥一段时间)或DEL已经过了&#34 ;人工"通过向处理events的到期逻辑添加循环。