使用redis实现系统消息

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,嘻嘻,不喜勿喷!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值