前段韶光在项目中须要将每个主题下的用户的评论组装好写入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中达到了分页和排序的目的。