Redis 是一个高效的内存数据库,它支持包括 String 、 List 、 Set 、 SortedSet 和 Hash 等数据类型的存储,在 Redis 中通常根据数据的 key 查询其 value 值, Redis 没有条件查询,在面对一些需要分页或排序的场景时(如评论,时间线), Redis 就不太好不处理了。
前段时间在项目中需要将每个主题下的用户的评论组装好写入 Redis 中,每个主题会有一个 topicId ,每一条评论会和 topicId 关联起来,得到大致的数据模型如下:
{
topicId: 'xxxxxxxx',
comments: [
{
username: 'niuniu',
createDate: 1447747334791,
content: '在 Redis 中分页',
commentId: 'xxxxxxx',
reply: [
{
content: 'yyyyyy'
username: 'niuniu'
},
...
]
},
...
]
}
将评论数据从 MySQL 查询出来组装好存到 Redis 后,以后每次就可以从 Redis 获取组装好的评论数据,从上面的数据模型可以看出数据都是 key-value 型数据,无疑要采用 hash 进行存储,但是每次拿取评论数据时需要分页而且还要按 createDate 字段进行排序, hash 肯定是不能做到分页和排序的。
那么,就挨个看一下 Redis 所支持的数据类型:
**String: **主要用于存储字符串,显然不支持分页和排序。 **Hash: **主要用于存储 key-value 型数据,评论模型中全是 key-value 型数据,所以在这里 Hash 无疑会用到。 **List: **主要用于存储一个列表,列表中的每一个元素按元素的插入时的顺序进行保存,如果我们将评论模型按 createDate 排好序后再插入 List 中,似乎就能做到排序了,而且再利用 List 中的 LRANGE key start stop 指令还能做到分页。嗯,到这里 List 似乎满足了我们分页和排序的要求,但是评论还会被删除,就需要更新 Redis 中的数据,如果每次删除评论后都将 Redis 中的数据全部重新写入一次,显然不够优雅,效率也会大打折扣,如果能删除指定的数据无疑会更好,而 List 中涉及到删除数据的就只有 LPOP 和 RPOP 这两条指令,但 LPOP 和 RPOP 只能删除列表头和列表尾的数据,不能删除指定位置的数据,所以 List 也不太适合。 **Set: **主要存储无序集合,无序!排除。 **SortedSet: 主要存储有序集合, SortedSet 的添加元素指令ZADD key score member [[score,member]...]会给每个添加的元素 member 绑定一个用于排序的值 score , SortedSet 就会根据 score 值的大小对元素进行排序,在这里就可以将 createDate 当作 score 用于排序, SortedSet 中的指令ZREVRANGE key start stop又可以返回指定区间内的成员,可以用来做分页, SortedSet 的指令 ZREM key member 可以根据 key 移除指定的成员,能满足删评论的要求,所以, SortedSet 在这里是最适合的。
所以,我需要用到的数据类型有 SortSet 和 Hash , SortSet 用于做分页排序, Hash 用于存储具体的键值对数据,我画出了如下的结构图:
在上图的 SortSet 结构中将每个主题的 topicId 作为 set 的 key ,将与该主题关联的评论的 createDate 和 commentId 分别作为 set 的 score 和 member , commentId 的顺序就根据 createDate 的大小进行排列。 当需要查询某个主题某一页的评论时,就可主题的 topicId 通过指令zrevrange topicId (page-1)×10 (page-1)×10+perPage这样就能找出某个主题下某一页的按时间排好顺序的所有评论的 commintId 。 page 为查询第几页的页码, perPage 为每页显示的条数。 当找到所有评论的 commentId 后,就可以把这些 commentId 作为 key 去 Hash 结构中去查询该条评论对应的内容。 这样就利用 SortSet 和 Hash 两种结构在 Redis 中达到了分页和排序的目的。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.