为了账号安全,请及时绑定邮箱和手机 立即绑定

Redis缓存列表类数据总结与分析

标签:
MySQL 大数据 Redis

文章简介

本文总结个人在使用Redis存储列表数据业务场景下的一些思路。平常在使用数据查询时,我们一般会将查询出来的数据使用json_encode()序列化一下,然后根据数据ID存储到Redis中。这样针对列表类的数据,或许就不是很好的实现了(因为涉及到分页计算)。本文使用String和zset类型实现这样的功能。
Snipaste_2021-02-27_13-54-42

数据存储结构

Snipaste_2021-02-27_13-52-33
上图为zset缓存数据ID,和String缓存实际信息的一个映射关系。

  1. zset中的分数和值都是数据的ID,是因为数据的ID是唯一的,zset中的值和分数也是唯一的。正好符合这种关系。

  2. String存储实体信息。缓存key则以数据ID作为键名,值为序列化后的数据信息。

  3. zset中的值和String缓存中的key一一映射。

接口数据处理

接口获取数据一般就是传递一个页码(page)和一个分页大小(size)。我们先去zset中获取对应的ID。然后根据ID依次获取String中的数据。如何根据分页去读取zset中的ID呢?可以根据下面的公式:

// 开始位置
$start = ($page - 1) * $size;
// 结束位置
$end   = $start + $size;
// 获取ID
$idArray = $redis->zRange($key, $start, $end);
var_dump($idArray);
// output
[1, 2, 4, 5, 6]
// 根据ID向Redis获取数据
$returnArray = [];
foreach ($idArray as $key => $value) {
    $returnArray[$key] = json_decode('cache:' . $value, true);
}

return $returnArray;

后台数据维护

用户端获取数据解决了,如果后台数据变更了,该如何处理呢?这里只要我们对后台的数据做了操作,去操作对应的缓存即可。整体思路如下:
Snipaste_2021-02-27_13-54-56

代码演示

Redis连接

class RedisConnection
{
    public $redisConnection;

    public function __construct()
    {
        $redis = new Redis();
        $redis->connect('192.168.2.102', 6379, 1);
        $redis->auth(6379);
        $this->redisConnection = $redis;
    }
}

MySQL连接

class DBConnection
{
    /**
     * 数据库类型
     * @var string
     */
    private $dbms = 'mysql';

    /**
     * 主机地址
     * @var string
     */
    private $host = 'mysql5';

    /**
     * 端口号
     * @var int
     */
    private $port = 3306;

    /**
     * 数据库名称
     * @var string
     */
    private $dbName = 'tools';

    /**
     * 用户名称
     * @var string
     */
    private $user = 'root';

    /**
     * 密码
     * @var string
     */
    private $pass = '123456';

    /**
     * 连接对象
     * @var PDO
     */
    public $dbConnection;

    public function __construct()
    {
        try {
            $dbh                = new PDO("{$this->dbms}:host={$this->host};port:{$this->port};dbname={$this->dbName}",
                $this->user,
                $this->pass, [
                    PDO::ATTR_PERSISTENT => true
                ]);
            $this->dbConnection = $dbh;
        } catch (Exception $exception) {
            var_dump('MySQL连接异常:' . $exception->getMessage());
        }
    }
}

管理端

class Manage
{
    /**
     * Redis连接对象
     * @var Redis
     */
    private $redis;

    /**
     * MySQL连接对象
     * @var PDO
     */
    private $db;

    public function __construct()
    {
        $this->db = (new DBConnection())->dbConnection;

        $this->redis = (new RedisConnection())->redisConnection;
    }

    /**
     * 数据增加
     * @return void
     */
    public function insert()
    {
        // 添加的数据
        $data = [];
        // 1. 插入数据库
        $insertId = 0;
        // 2. 插入Redis
        // 2.1 插入string
        $this->redis->set('cache:' . $insertId, json_encode($data));
        // 2.2 插入zset
        $this->redis->zAdd('list', [], $insertId, $insertId);
    }

    /**
     * 数据更新
     * @return void
     */
    public function update()
    {
        // 更新数据
        $data = [];
        // 1. 更新数据库
        $updatedId = 0;
        // 2. 更新Redis
        $this->redis->set('cache:' . $updatedId, json_encode($data));
    }

    /**
     * 数据删除
     * @return void
     */
    public function delete()
    {
        // 1.删除数据id
        $deleteId = 0;
        // 2.删除Redis
        // 2.1删除string
        $this->redis->del('cache:' . $deleteId);
        // 2.2删除zset
        $this->redis->zDelete('list', $deleteId);
    }
}

接口端

class Api
{
    /**
     * Redis连接对象
     * @var Redis
     */
    private $redis;

    public function __construct()
    {

        $this->redis = (new RedisConnection())->redisConnection;
    }

    /**
     * 获取列表
     * @return array
     */
    public function list()
    {
        /**
         * 这里罗列普通的查询
         * 如果涉及到条件查询,可以先根据条件去MySQL中查询到主表的ID。在根据ID走这样的逻辑。
         */
        // 页码
        $page = 1;
        // 分页大小
        $size = 10;
        // 1.先根据分页获取zset中的id(分数)
        $start   = ($page - 1) * $size;
        $idArray = $this->redis->zRange('list', $start, $size + $start);
        // 2.根据获取到的id,去string中查找
        $returnArray = [];
        foreach ($idArray as $key => $value) {
            $returnArray[$key] = json_decode('cache:' . $value, true);
        }

        return $returnArray;
    }

    // 获取详情
    public function find()
    {
        // 客户端请求的,数据id
        $id = 1;

        return json_decode($this->redis->get('cache:' . $id), true);
    }

}

问题总结

  1. 列表参数化查询如何处理?

列表数据一般都是有传递用户查询参数,这时候我们可以实现根据条件去数据库筛选出对应的数据ID,并且只查询ID即可,然后根据ID去执行上面的逻辑。

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中

卡二条

PHP开发工程师
手记
粉丝
56
获赞与收藏
375

关注作者,订阅最新文章

阅读免费教程

  • MySQL 进阶教程
    32个小节 49456 922
  • MySQL 入门教程
    32个小节 124240 1539
  • 后端通用面试教程
    41个小节 28709 323
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 分销返利 帮助中心 APP下载
官方微信
返回顶部

举报

0/150
提交
取消

代做工资流水公司西安查询银行流水修改中山代开企业银行流水重庆查入职工资流水九江银行流水账代做淄博入职流水代办芜湖流水账单多少钱宜昌车贷流水价格海口企业流水打印多少钱武汉查企业对私流水台州入职工资流水模板南昌入职银行流水价格赣州代做贷款工资流水济南流水开具徐州个人流水模板上饶开个人工资流水台州打印工资流水咸阳公司流水查询许昌在职证明宜昌开工资流水湘潭房贷流水打印金华对公账户流水价格南通代开签证工资流水铜陵公司银行流水公司海口背调银行流水样本鞍山房贷收入证明打印宁波企业对公流水图片襄阳转账银行流水报价无锡银行流水账单襄阳工资证明制作常州办理自存流水香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

代做工资流水公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化