分析与实现
一个消息应用有如下需求:
- 需要保留用户最近24小时内的所有操作历史
- 需要频繁的显示最近的10条操作历史给用户
- 需要频繁的显示24小时内总操作次数
这是一个典型的适合应用Redis的情形。现在需要考虑的是如何具体实现,首先想到的是采用字典(哈希表)列表的方式实现,其中每一个哈希表存储操作内容和操作时间,同时包含一个过期时间。但是考虑到Redis支持设置键的过期时间,所以哈希表本身可以不用存储过期时间,而是在创建的时候设置好过期时间即可。
我们给操作历史列表取名为history
,之后每当有新的操作发生的时候我们需要在列表中新增一项,同时创建一个新的哈希表:
|
这样,当需要统计总操作数或者需要显示最近的10条记录的时候,我们需要先遍历history列表,然后删除掉其中已经过期的哈希表的键,最后再返回总条数或者最近10条记录。
为了减少网络传输时间,我们将删除过期键的功能使用Lua脚本实现并加载到Redis(>2.6.0)中。Lua脚本:
|
查看本例完整的Python实现可访问Gist。
时间复杂度
首先列出我们使用的各个操作的时间复杂度:
操作 | 时间复杂度 |
---|---|
LPUSH | O(1) |
HMSET | O(N), N 为 field-value 对的数量。 |
EXPIRE | O(1) |
EXISTS | O(1) |
LRANGE | O(S+N), S 为偏移量 start , N 为指定区间内元素的数量。 |
LLEN | O(1) |
LPOP | O(1) |
具体到我们实现的功能上来说,各个功能的时间复杂度如下:
功能 | 复杂度 |
---|---|
新增一条操作记录 | O(N),N为hash中key的数量 |
删除过期的记录 | O(N),N为本次过期条数 |
取最新的10条记录 | O(1) |