[译] 迁移 MySQL 的表到 Redis
原文链接:https://www.mortensi.com/2021/12/migrate-a-mysql-table-to-redis/
原文作者:Admin
在这篇文章中,我将列出一些从MySQL逻辑复制一张表到Redis的一些选项。我将使用经典的world
数据库运行示例。 world
数据库可以在这里下载 ,所以如果您想尝试这些示例,只需将它导入到您的MySQL实例中。
1 | mysql> use world; |
有多种方法可以将表格导入Redis,让我们来看看其中的几种。在下面的例子中,我将选择一个Hash 数据类型,最类似于Redis的传统表行。
Redis哈希是字符串字段和字符串值之间的映射,所以它们是表示对象的完美数据类型(例如,一个用户有许多字段,如名字、姓氏、年龄等)
使用 SELECT INTO OUTFILE 导出CSV格式,使用Python导入
为了从MySQL导出数据并将其导入Redis,我们可以使用MySQL SELECT into OUTFILE 功能,它可以生成一个格式化的输出文件。特别是,我将确保字段用逗号分隔。让我们试一试:
1 | mysql> SELECT * INTO OUTFILE '/tmp/city.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY 'n' FROM world.city; |
噢,MySQL默认配置禁止导出数据到文件系统。让我们在配置文件my.cnf中修复它:
1 | [mysqld] |
现在我可以导出:
1 | mysql> SELECT * INTO OUTFILE '/tmp/city.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY 'n' FROM world.city; |
这是示例:
1 | "1","Kabul","AFG","Kabol","1780000" |
现在数据是CSV格式,我能使用一个简单的Python脚本导入它,下面是个可用的示例(参考说明设置 Python 环境 以连接到Redis)。
1 | #!/usr/bin/python3 |
让我们检查下是否正确导入:
1 | 127.0.0.1:4321> SCAN 0 MATCH city:* COUNT 5 |
我也可以验证Hash项的内容:
1 | 127.0.0.1:4321> HGETALL city:4059 |
使用mysqldump导出CSV格式
备份工具 mysqldump 可作为客户端,可以从远端导出数据,而不需要修改让任何服务器配置。可以此来代替SELECT INTO OUTFILE
,对有些人来说,它可能代表一个安全问题,因为它是在服务器本身导出行数据到文件系统,并需要启用secure_file_priv 。
1 | mysqldump --host=127.0.0.1 --user=root --password --tab=/tmp --fields-enclosed-by='"' --fields-terminated-by=',' --lines-terminated-by='n' world city |
一旦文件导出(mysqldump导出两个文件,表定义保存在city.sql
文件,数据以CSV格式保存在city.txt
文件),数据可以按照说明导入。
使用RIOT导入CSV备份
假设你有一个MySQL表的CSV备份,事实上,CSV可以来自于任何数据源,比如Excel表格,Postgres等等。如果你不想编码来导入到Redis,你可以使用RIOT(Redis输入输出工具),用于将异构数据源迁移到Redis。
Redis输入输出工具: RIOT
Redis输入/输出工具(RIOT)是一个工具集,其设计目的在于帮助您从Redis导入导出数据。
在本节中,我将演示RIOT的CSV导入工具,称之为 RIOT文件 。首先,安装它(我使用Mac,但是您可以参考文档了解其他安装方法)
1 | brew install redis-developer/tap/riot-file |
安装后,测试帮助方法:
1 | (redisvenv) bash-3.2$ riot-file --help |
是的,您也需要从www.java.com 下载JRE,完成后,继续:
1 | (redisvenv) bash-3.2$ riot-file import hset --help |
现在,我们必须将CSV数据源映射到适当的Hash数据结构。我们原始的CSV文件第一行没有标题。如果我们想加标题,我们甚至可以按照顺序从 MySQL information_schema
中抽取。
注意:MySQL SELECT INTO OUTFILE不会在导出的数据集添加头,这必须使用正确的SQL语法手动添加,或编辑导出的CSV文件。
1 | mysql> SELECT group_concat(COLUMN_NAME ORDER BY ORDINAL_POSITION separator ',') FROM information_schema.COLUMNS WHERE TABLE_NAME='city' AND TABLE_SCHEMA='world'; |
添加ID,Name,CountryCode,District,Population
到CSV文件的第一行。但是我们仍然可以继续手动执行映射。在这里,我们指定字段在CSV文件中出现的顺序,指定表名(keyspace),及补充字段名(key)(例如city:1234
)。
1 | riot-file -h 127.0.0.1 -p 4321 import /tmp/city.csv --fields ID Name CountryCode District Population hmset --keyspace city --keys ID |
或者,如果CSV文件有从MySQL获得的头,我们可以添加--header
参数来使用手动添加的CSV头。
1 | riot-file -h 127.0.0.1 -p 4321 import /tmp/city.csv --header hmset --keyspace city --keys ID |
使用 RIOT DB 从MySQL导入
为了从没有中间转储备份导入MySQL,您可以编码一个方案,来连接源数据库和目标Redis库,或者简单地使用RIOT DB 。下面来安装它:
1 | brew install redis-developer/tap/riot-db |
然后像往常一样导入,指定表名和列名,提供正确的连接信息,显然,需要定义导入数据集的查询语句。
1 | riot-db -h 127.0.0.1 -p 4321 import "SELECT * FROM city" --url jdbc:mysql://root:Oracle1*@127.0.0.1:3306/world hmset --keyspace city --keys ID |
导出并以RESP格式做大量插入
到目前为止,我已经探索了一些逻辑方法,但是对于大量插入,最高速度需要达到百万个键,有一种不同的方法,即使用redis-cli的管道模式,读取数据的同时,立即发送到服务器。特别地,使用这种方法,我们将使用Redis协议(RESP) 。关于大量插入的更多信息请参阅这里 。
它可能导出RESP格式的表,并转瞬流到Redis服务器。让我们看看它是如何工作的。我们能使用SQL来生成数据,并以这种格式发送到Redis服务器:
1 | *<args><cr><lf> |
这里:
- args 是参数的数量
- lenN 是参数跟随的长度
- argN 是参数
假设我们要为MySQL表中的每一行添加一个Hash,每个Hash将插入4个字段,在RESP协议中生成转储的SQL语句将是这样的:
1 | SELECT CONCAT( |
保存SQL到resp.sql
文件,并用Redis的管道模式从MySQL流到Redis:
1 | bash-3.2$ mysql -h 127.0.0.1 -uroot -p -Dworld --skip-column-names --raw </tmp/resp.sql |redis-cli -p 4321 --pipe |
数据已经导入到Redis服务器!
使用 Redis 的 MySQL 连接器:redis-connect-mysql
最后一节,我将介绍如何使用Redis连接套件,特别是 redis-connect-mysql 。您可以阅读这份文档:
redis-connect-mysql第一次连接MySQL时,它会读取所有模式的一致性快照。当快照创建完成,连接器将连续发送MySQL的变更并生成相应的insert,update或delete事件。
因此,它不仅仅是一个迁移工具,还是一个连接异构数据库的复制和传输工具。Redis CDC (变更数据捕捉)曾在RedisConf 2021上演示,所以请查看演示的详细内容。
译者注:这段视频在油管上,此处跳过。
RedisCDC: Seamless database migrations and continuous changed-data replication, Redis Labs
我现在没有运行使用RedisCDC的示例,但是请查看代码库 来了解如何操作它。
清理
为了移除那些导入的Hash值,您可以执行下面的命令:
1 | redis-cli -p <PORT> --scan --pattern city:* -i 0.01 | xargs redis-cli -p <PORT> unlink |
总结
现在,您能从MySQL导出一张表,或者从其他的关系型数据库,任何可以导出CSV的数据库,或者RIOT DB,或者RedisCDC能连接的多种数据库。
接下来,您可能想知道您能用这些创建在Redis实例中的哈希值做些什么。所以我在下篇文章中,将分享一些例子,关于在Redis中存储、检索、更改、删除、索引和检索数据的命令。
那么现在呢? 你可能想知道你可以用这些在Redis实例中创建的哈希值做什么。所以在下一篇文章中,我将分享几个在Redis中存储、检索、更改、删除、索引和搜索数据的命令示例。别走开,我很快就会写的!
- Title: [译] 迁移 MySQL 的表到 Redis
- Author: 严少安
- Created at: 2022-03-16 20:03:49
- Updated at: 2022-03-16 20:03:49
- Link: https://shawnyan.cn/2022/mysql/fanyi-migrate-a-mysql-table-to-redis/
- License: This work is licensed under CC BY-NC-SA 4.0.