1. 缓存分页处理
1.1.1. 分析
- String: 主要用于存储字符串,显然不支持分页和排序。
- Hash: 主要用于存储key-value型数据,评论模型中全是key-value型数据,所以在这里Hash无疑会用到。
List: 主要用于存储一个列表,列表中的每一个元素按元素的插入时的顺序进行保存,如果我们将评论模型按createDate排好序后再插入List中,似乎就能做到排序了,而且再利用List中的LRANGE key start stop指令还能做到分页。嗯,到这里List似乎满足了我们分页和排序的要求,但是评论还会被删除,就需要更新Redis中的数据,如果每次删除评论后都将Redis中的数据全部重新写入一次,显然不够优雅,效率也会大打折扣,如果能删除指定的数据无疑会更好,而List中涉及到删除数据的就只有LPOP和RPOP这两条指令,但LPOP和RPOP只能删除列表头和列表尾的数据,不能删除指定位置的数据,(备注:其实还有 LREM命令可以做到删除,但是非常不方便),而且当存在接口高并发访问时,这个list可能会无限延长,且里面的数据会存在很多重复,这就会影响到正常的业务,所以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在这里是最适合的(时间复杂度O(log(N)))。
所以,需要用到的数据类型有SortSet和Hash,SortSet用于做分页排序,Hash用于存储具体的键值对数据。SortSet结构中将每个主题的topicId作为set的key,将与该主题关联的评论的createDate和commentId分别作为set的score和member,commentId的顺序就根据createDate的大小进行排列。
1.2. Code Demo
//插入订单数据
\RedisDB::hset($CacheKey, $order_id, json_encode($orderData));
\RedisDB::zadd($CacheKey . '_s', $score, $order_id);
public function funcDemo ($login, $limit, $offset)
{
$CacheKey = "{$login}:3";
$orderIds = \Redis::zrevrange($CacheKey . '_s', 0, -1, ['limit' => [$limit, $offset]]);
$lists = \Redis::hmget($CacheKey, $orderIds);
foreach ($lists as &$val) {
$val = json_decode($val, 1);
}
return $lists;
}
- zrevrange 根据权重值 范围倒序取值 支持 limit
- hmget 取出多个值 无对应值 会返回对应位置 null
- hexists($key,$s) 检查 val 是否存在
- hdel($key,[$s1,$s2]) 删除 某个值