社区,相信很多人开发人员都接触过,1级,2级...,N级。那就聊聊1级评论的设计方法,仅供参考。
这里我是采用redis进行存储和排序查询的,怎样查询第一级评论内容
1、第一缓存key
//存储回复id
private $redis_post_id = 'thread_{post_info_hash_%d}'; //帖子id
//回复hash方式存储
private $redis_post_info_hash = '{post_info_hash_%d}_%d'; //存储回复信息 帖子id,回复id
为什么缓存key需要{....},这是由于在集群redis中使用hash tag
分片,就是一个hash的过程:对key做md5,sha1等hash算法,根据hash值分配到不同的机器上。
为了实现将key分到相同机器,就需要相同的hash值,即相同的key(改变hash算法也行,但不简单)。
但key相同是不现实的,因为key都有不同的用途。例如user:user1:ids保存用户的tweets ID,user:user1:tweets保存tweet的具体内容,两个key不可能同名。
仔细观察user:user1:ids和user:user1:tweets,两个key其实有相同的地方,即user1。能不能拿这一部分去计算hash呢?
这就是hash tag 。允许用key的部分字符串来计算hash。
当一个key包含 {} 的时候,就不对整个key做hash,而仅对 {} 包括的字符串做hash。
假设hash算法为sha1。对user:{user1}:ids和user:{user1}:tweets,其hash值都等同于sha1(user1)。
private function addToRedisHash($threadId = 0, $postInfo = array(), $update = 0)
{
if(empty($threadId) || empty($postInfo))return false;
$redis = Cache::getInstance('Redis');
$id_key = sprintf($this->redis_post_id, $threadId);
$info_key = sprintf($this->redis_post_info_hash, $threadId, $postInfo['id']);
$res = $redis->sAdd($id_key, $postInfo['id']);
if($res || $update == 1){
$data = [
'id' => $postInfo['id'],
'pid' => $postInfo['pid'],
'thread_id' => $postInfo['thread_id'],
'user_id' => $postInfo['user_id'],
'content' => $postInfo['content'],
'created_time' => $postInfo['created_time'],
'reply_num' => $postInfo['reply_num'],
'zan_num' => $postInfo['zan_num'],
'toid' => $postInfo['toid'],
'latest_post_time' => $postInfo['latest_post_time']
];
$redis->hMset($info_key, $data);
//处理缓存时间
$redis->expire($id_key, $this->redis_post_list_time_out);
$redis->expire($info_key, $this->redis_post_list_time_out);
}
return $res;
}
帖子回复所有id存储在list中($redis_post_id),所有内容存储在hash中($redis_post_info_hash)
3、按指定条件查询
private function sortPostListByHash($threadId = 0, $by = 'zan', $limit = 10)
{
if(empty($threadId) || empty($by))return [];
$id_key = sprintf($this->redis_post_id, $threadId);
$redis = Cache::getInstance('Redis');
/**
* 按score从大到小排序,取得id
*/
//缓存key
$key = C('DATA_CACHE_PREFIX').'{post_info_hash_'.$threadId.'}_';
$sort = array('SORT' => 'DESC');
if($by == 'id'){
//默认按id从大小
}elseif($by == 'zan'){
$sort['BY'] = $key.'*->zan_num'; //点赞从多到少排序
}elseif($by == 'time'){
$sort['BY'] = $key.'*->latest_post_time'; //更新时间从大到小排序
}
$count = $redis->sCard($id_key);
if($count == 0)return ['list'=>[], 'totalPage'=>0, 'count'=>0, 'cache'=>0];
$page = new \Think\Page($count, $limit);
$totalPage = ceil($count/$limit);
$sort['limit'] = [$page->firstRow,$page->listRows];
$lists = $redis->sort($id_key, $sort);
return ['list'=>$lists, 'totalPage'=>$totalPage, 'count'=>$count, 'cache'=>1];
}
此处使用到的是list中sort函数,sort中的BY可以指定hash中某个字段。从而实现按指定条件(id,时间,赞等)排序,并获取回复id,再根据id取hash中的数据显示。
仅供参考,二级内容可以更加一级ID查询缓存。帖子回复的更新、删除、增加就不进行说明了。