首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis实现列表数据查询设计

Redis实现列表数据查询设计

作者头像
Mandy的名字被占用了
发布2021-03-16 10:54:38
1.2K0
发布2021-03-16 10:54:38
举报

文章简介

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

数据存储结构

上图为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;

后台数据维护

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

代码演示

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去执行上面的逻辑。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 卡二条的技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章简介
  • 数据存储结构
  • 接口数据处理
  • 后台数据维护
  • 代码演示
    • Redis连接
      • MySQL连接
        • 管理端
          • 接口端
          • 问题总结
          相关产品与服务
          云数据库 Redis
          腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档