1、直接上代码
在redis中生成一个当前用户的容器,保存当前用户所有的系统消息,个人消息。
public static function insertMessage($user_id)
{
/**
* 用户第一次登录时,需要全部从mysql中获取,
*/
$redis = new RedisPro();
try {
//系统消息
$msg = self::where('status', 1)
->where('is_push', 1)
->where('type', 'in', '1,2,4')
->order('create_time desc')
->select();
/**
* 系统消息、分站消息、所有会员消息,是针对每一个用户都需要展示,区分用户,
* 所以,不需要在写入redis时,添加user_id字段
* 数据格式,
* 键:system_msg:10039 使用用户 system_msg结合用户的user_id当做键,及时同一时间有多个用户调用,也不会覆盖
* 值:id:{{id:id,title:title,status:status,content:content,is_read:1,type:type},,,,}
*/
if (!$msg->isEmpty()) {
//遍历系统消息
foreach ($msg as $key => $value) {
//从缓存中获取该信息
$sys_id = $redis->hGet('system_msg:' . $user_id, $value['id']);
//如果用户的缓存中,没有该消息,则新增到缓存
if (empty($sys_id)) {
$redis->hSet('system_msg:' . $user_id, $value['id'], json_encode([
'id' => $value['id'], //消息id
'title' => $value['title'], //标题
'content' => $value['content'], //内容
'type' => $value['type'], //类型
'status' => $value['status'], //状态
'create_time' => $value['create_time'],
'is_read' => 2, //已读
]) //系统消息的key
);
$redis->zAdd('system_sort:' . $user_id, [], $key, $value['id']);
}else{
$redis->zAdd('system_sort:' . $user_id, [], $key, $value['id']);
}
}
} else {
throw new dbNullException('暂无数据', 10404);
}
//个人消息
$only_msg = self::alias('sys')->field('sys.title,sys.content,sys.status,sys.type,sys.id,sys.create_time')
->join('tk_system_send sss', 'sss.sid=sys.id')
->where('sss.uid', $user_id)
->where('sys.status', 1)
->where('sys.type', 3)
->order('id desc')
->select();
//判断对象非空
if (!$only_msg->isEmpty()) {
//如果存在,遍历消息集合
foreach ($only_msg as $key => $value) {
//从redis中获取当前消息的数据
$only_id = $redis->hGet('only_msg:' . $user_id, $value['id']); //个人消息
//如果没有,则将当前消息写入redis
if (empty($only_id)) {
//个人消息的key
$redis->hSet('only_msg:' . $user_id, $value['id'], json_encode([
'id' => $value['id'], //消息id
'title' => $value['title'], //标题
'content' => $value['content'], //内容
'type' => $value['type'], //类型
'status' => $value['status'], //状态
'create_time' => $value['create_time'],
'is_read' => 2, //未读
])
);
$redis->zAdd('only_sort:' . $user_id, [], $key, $value['id']);
}else{
$redis->zAdd('only_sort:' . $user_id, [], $key, $value['id']);
}
}
} else {
throw new dbNullException('暂无数据', 10404);
}
} catch (ErrorException $e) {
throw new ErrorException('出错了');
}
}
保存到redis中的数据格式如下:
如上图所示:我使用的是hset(key,value)的方式保存个人消息,由于hash是没有顺序可言,就不能实现消息分页,所以,另外使用了一个zset集合,让无序的hash,变得有序。【不是真的变得有序,只是关联有序,需要细细体会这句话】,系统消息的保存逻辑和个人消息相同。
从redis中取出数据:
public static function msgList($type, $user_id, $index, $end)
{
$redis = new RedisPro();
$res = [];
//系统消息
if ($type == 1) {
$sys_id = $redis->zRange('system_sort:' . $user_id, $index, $end);
foreach ($sys_id as $key => $value) {
//从缓存中获取系统信息
$sys_msg = $redis->hGet('system_msg:' . $user_id, $value);
$re = json_decode($sys_msg, true);
//从数据库中获取信息,
$mysqlSysMsg = System::where('id', $value)->find();
//如果缓存中的和mysql中的系统消息数据是一样的,则可以直接展示
if ($re['title'] == $mysqlSysMsg['title'] && $re['content'] == $mysqlSysMsg['content'] && $re['status'] == $mysqlSysMsg['status']) {
$res[] = $re;
// 如果不同,说明mysql中已经改变,但是redis中没有更新,就需要更新redis
} else {
$redis->hSet('system_msg:' . $user_id, $value, json_encode([
'id' => $mysqlSysMsg['id'], //消息id
'title' => $mysqlSysMsg['title'], //标题
'content' => $mysqlSysMsg['content'], //内容
'type' => $mysqlSysMsg['type'], //类型
'status' => $mysqlSysMsg['status'], //状态
'create_time' => $re['create_time'], //创建时间不会改变
'is_read' => $re['is_read'], //是否已读,也需要从redis中获取
]) //系统消息的key
);
$res[] = [
'id' => $mysqlSysMsg['id'], //消息id
'title' => $mysqlSysMsg['title'], //标题
'content' => $mysqlSysMsg['content'], //内容
'type' => $mysqlSysMsg['type'], //类型
'status' => $mysqlSysMsg['status'], //状态
'create_time' => $re['create_time'], //创建时间不会改变
'is_read' => $re['is_read'], //是否已读,也需要从redis中获取
];
}
}
//个人消息
} else {
$only_id = $redis->zRange('only_sort:' . $user_id, $index, $end);
foreach ($only_id as $key => $value) {
$only_msg = $redis->hGet('only_msg:' . $user_id, $value);
$re = json_decode($only_msg, true);
//从数据库中获取信息,
$mysqlOnlyMsg = System::where('id', $value)->find();
//判断redis中的数据和mysql中的数据是不是一样的
if ($re['title'] == $mysqlOnlyMsg['title'] && $re['content'] == $mysqlOnlyMsg['content'] && $re['status'] == $mysqlOnlyMsg['status']) {
$res[] = $re;
// 如果不同,说明mysql中已经改变,但是redis中没有更新,就需要更新redis
} else {
$redis->hSet('only_msg:' . $user_id, $value['id'], json_encode([
'id' => $mysqlOnlyMsg['id'], //消息id
'title' => $mysqlOnlyMsg['title'], //标题
'content' => $mysqlOnlyMsg['content'], //内容
'type' => $mysqlOnlyMsg['type'], //类型
'status' => $mysqlOnlyMsg['status'], //状态
'create_time' => $re['create_time'],
'is_read' => $re['is_read'], //未读
])
);
$res[] = [
'id' => $mysqlOnlyMsg['id'], //消息id
'title' => $mysqlOnlyMsg['title'], //标题
'content' => $mysqlOnlyMsg['content'], //内容
'type' => $mysqlOnlyMsg['type'], //类型
'status' => $mysqlOnlyMsg['status'], //状态
'create_time' => $re['create_time'],
'is_read' => $re['is_read'], //未读
];
}
}
}
return $res;
}
这是消息列表返回的数据。
方式有点low,嘻嘻,不喜勿喷!!!