【问题标题】:MySQL to Redis - Import and ModelMySQL 到 Redis - 导入和建模
【发布时间】:2013-09-30 15:09:19
【问题描述】:

我正在考虑使用Redis 来缓存一些用户数据快照,以加快对该数据的访问(原因之一是因为我的 MySQL 表遭受了锁争用)和我正在寻找一步导入这样的表的最佳方法(可能包含几条记录到数百万条记录):

mysql> select * from mytable where snapshot = 1133;
+------+--------------------------+----------------+-------------------+-----------+-----------+
| id   | email                    | name           | surname           | operation | snapshot  |
+------+--------------------------+----------------+-------------------+-----------+-----------+
| 2989 | example-2989@example.com | fake-name-2989 | fake-surname-2989 |         2 |      1133 |
| 2990 | example-2990@example.com | fake-name-2990 | fake-surname-2990 |        10 |      1133 |
| 2992 | example-2992@example.com | fake-name-2992 | fake-surname-2992 |         5 |      1133 |
| 2993 | example-2993@example.com | fake-name-2993 | fake-surname-2993 |         5 |      1133 |
| 2994 | example-2994@example.com | fake-name-2994 | fake-surname-2994 |         9 |      1133 |
| 2995 | example-2995@example.com | fake-name-2995 | fake-surname-2995 |         7 |      1133 |
| 2996 | example-2996@example.com | fake-name-2996 | fake-surname-2996 |         1 |      1133 |
+------+--------------------------+----------------+-------------------+-----------+-----------+

进入 Redis 键值存储。

我可以将许多“快照”加载到 Redis 中,基本的访问模式是(类似 SQL 的语法)

  • select * from mytable where snapshot = ? and id = ?

这些快照也可以来自其他表,因此“每个快照的全局唯一 ID”是列 snapshot,例如:

mysql> select * from my_other_table where snapshot = 1134;
+------+--------------------------+----------------+-------------------+-----------+-----------+
| id   | email                    | name           | surname           | operation | snapshot  |
+------+--------------------------+----------------+-------------------+-----------+-----------+
| 2989 | example-2989@example.com | fake-name-2989 | fake-surname-2989 |         1 |      1134 |
| 2990 | example-2990@example.com | fake-name-2990 | fake-surname-2990 |         8 |      1134 |
| 2552 | example-2552@example.com | fake-name-2552 | fake-surname-2552 |         5 |      1134 |
+------+--------------------------+----------------+-------------------+-----------+-----------+

加载到 redis 中的快照永远不会改变,它们通过 TTL 只能使用一周

  • 有没有一种方法可以将这种数据(行和列)结合redis-cli --pipeHMSET 一步加载到redis 中?

  • 在 redis 中用于存储/获取这些数据的最佳模型是什么(考虑访问模式)?

我找到了redis-cli --pipeRedis Mass Insertion(还有MySQL to Redis in One Step),但我无法找到满足我要求的最佳方法(一步从mysql加载所有行/列,最好的redis模型这个)使用HMSET

提前致谢

克里斯蒂安。

【问题讨论】:

  • 是随手添加快照而旧快照永远不会改变,或者更新模式是什么?
  • @JoachimIsaksson 快照永远不会改变,它们只需要一个 TTL(比如 1 周),之后数据就可以被丢弃。
  • 然后(无论如何都不是专家,只是一个用户),我会为每个快照添加一个哈希,使用id 作为键。如果从不查询其余数据,则可以简单地使用数据的 JSON 编码作为值。
  • @CristianPorta 我建议了一个数据模型,告诉我你的想法!

标签: mysql nosql redis key-value-store


【解决方案1】:

型号

为了能够以与以下相同的方式从 Redis 查询您的数据:

select * from mytable where snapshot = ?
select * from mytable where id = ?

你需要下面的模型。

注意:select * from mytable where snapshot = ? and id = ? 在这里没有多大意义,因为它与select * from mytable where id = ? 相同。

键类型和命名

[Key Type] [Key name pattern]
HASH       d:{id}
ZSET       d:ByInsertionDate
SET        d:BySnapshot:{id}

注意:我使用 d: 作为命名空间,但您可能希望使用域模型的名称重命名它。

数据插入

从 Mysql 中将新行插入 Redis:

hmset d:2989 id 2989 email example-2989@example.com name fake-name-2989 ... snapshot 1134
zadd d:ByInsertionDate {current_timestamp} d:2989
sadd d:BySnapshot:1134 d:2989

另一个例子:

hmset d:2990 id 2990 email example-2990@example.com name fake-name-2990 ... snapshot 1134
zadd d:ByInsertionDate {current_timestamp} d:2990
sadd d:BySnapshot:1134 d:2990

Cron

以下是必须根据您的要求每天或每周运行的算法:

for key_name in redis(ZREVRANGEBYSCORE d:ByInsertionDate -inf {timestamp_one_week_ago})

 // retrieve the snapshot id from d:{id}
 val snapshot_id = redis(hget {key_name} snapshot)

 // remove the hash (d:{id})
 redis(del key_name)

 // remove the hash entry from the set
 redis(srem d:BySnapshot:{snapshot_id} {key_name})

// clean the zset from expired keys
redis(zremrangebyscore d:ByInsertionDate -inf {timestamp_one_week_ago})

用法

select * from my_other_table where snapshot = 1134; 将是:

{snapshot_id} = 1134
for key_name in redis(smembers d:BySnapshot:{snapshot_id})
  print(redis(hgetall {keyname}))

或者编写一个 lua 脚本直接在 redis 端执行此操作。最后:

select * from my_other_table where id = 2989; 将是:

{id} = 2989
print(redis(hgetall d:{id}))

导入

这部分很简单,只需阅读表格并遵循上述模型即可。根据您的要求,您可能希望使用每小时/每天/每周 cron 导入所有(或部分)数据。

【讨论】:

    猜你喜欢
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 2014-12-03
    • 2011-02-28
    • 2014-08-17
    • 2013-08-23
    • 2013-02-21
    相关资源
    最近更新 更多