我正在考虑使用 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 --pipe
和HMSET
的 redis 中?在 Redis 中使用的最佳模型是什么来存储/获取此数据(考虑访问模式(?
我找到了redis-cli --pipe
Redis 批量插入(以及一步到 Redis 的 MySQL(,但我无法找到实现我要求的最佳方法(一步从 mysql 加载所有行/列,为此最好的 redis 模型(使用 HMSET
提前致谢
克里斯蒂安。
模型
能够像以下方法一样从 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:
作为命名空间,但您可能希望使用域模型的名称重命名它。
数据插入
在 Redis 中插入 Mysql 中的新行:
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
克龙
以下是根据您的要求每天或每周必须运行的算法:
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 导入全部(或部分(数据。