s

时间线(timeline)

应用

在有些应用程序中,数据通常带有一个时间值,程序以时间为单位操作数据(可以是一个时间范围,或者是单独的一个时间点):比如求一个博客在6月至8月的所有日志,或者是今天写博客的文章数。

还有一些微博客,只显示最近两天的内容,等等。

定义

一个时间线对象最少有两个属性

  1. 时间值
  2. 数据内容

针对时间线对象的操作通常都是一些范围型的操作:比如求某个时间点起到另一个时间点内的所有数据,或者是统计某个时间点起到另一个时间点内的数据数目,等等。

实现

在Redis中我们可以用sorted_set_struct表示时间线。

当增加一个新条目时,我们将条目内容作为有序集元素的member参数,使用当前时间的UnixTime格式,作为有序集元素的score值。

比如一条在2011年8月22日时47分7秒发出的信息,会被储存为:

ZADD tweet 1313981227.681918 "hello my friend"

其中tweet是时间线的key1313981227.681918UnixTime格式的UTC时间,而"hello my friend"则是条目内容。

这样一来,就可以用ZREVRANGE进行按条目数读取(比如读出最新10条数据),使用ZREVRANGEBYSCORE进行时间范围型的读取操作(比如读出2011年8月20日到2011年8月22日的所有数据),用ZREM对单条数据进行删除,用ZREMRANGEBYRANKZREMRANGEBYSCORE进行时间范围型的删除操作。

# coding: utf-8

# file: ./s/timeline/sorted_set_implement.py

from redis import Redis
from time import time

# Redis有序集边界
LEFTMOST = 0
RIGHTMOST = -1

class Timeline:

    def __init__(self, name, client=Redis()):
        self.name = name
        self.client = client

    def append(self, content):
        # time()函数生成当前时间的unixtime值
        self.client.zadd(self.name, score=time(), value=content)

    def range(self, start=LEFTMOST, stop=RIGHTMOST, display_time=False):
        # 使用zrevrange命令,读出最新的数据
        return self.client.zrevrange(self.name, start, stop, withscores=display_time)

    def range_between_time(self, min, max, display_time=False):
        # min和max也必须是unixtime值
        # 注意zrevrangebyscore命令参数的摆放是max先而min后
        return self.client.zrevrangebyscore(self.name, max, min, withscores=display_time)

    def delete(self, content):
        return self.client.zrem(self.name, content)

    def delete_between_time(self, min, max):
        # min和max也必须是unixtime值
        return self.client.zremrangebyscore(self.name, min=min, max=max)

    def length(self):
        return self.client.zcard(self.name)

锁(Lock)

应用

定义

实现