Mysql

从mysql抽取数据传入redis

2021-12-25  本文已影响0人  随风遣入夜

场景

  1. 需要将大批量数据快速上传至redis,想一想我们有几百万数据待上传到redis,这时候是不是需要一种高效稳定的方式呢?
  2. 我们首先需要具备什么样的水平,才能做这件事情?

回答

  1. 问题回答:
  1. 问题回答:

本文的流程

准备工作

编写仿AOF文件内容的sql脚本

SELECT CONCAT(
  "*3\r\n",
  '$', LENGTH(redis_cmd),'\r\n',redis_cmd,'\r\n',
  '$', LENGTH(redis_key),'\r\n',redis_key,'\r\n',
  '$', LENGTH(hval1),'\r\n',hval1,'\r'
)
FROM (
  SELECT
    'SET' as redis_cmd,
    CONCAT('user:',id) as redis_key,
    CONCAT(
        '{"id":"',a.id,'"',
        ',"name":"',a.name,'"',
        ',"cardId":"',a.cardId,'"',
        ',"code":"',a.code,'"}'
    ) as hval1
  FROM user a

) AS t
# 解释下这里的重点
# 1. [*3]代表中的[*]array,3的是[$]的数量,每个[$]代表一个基础操作位的起始
# 2. [\r\n]代表一个分隔符,一个结束语标识;RESP协议中的分隔符为在Linux下是\r\n,而在Windows下则为\n
# 3. 为什么要将sql脚本写成这样的,那是因为,我想把它拼成json字符串,前端或者后端拿到后,就能序列化出来,关键是key带了数据库的主键,用起来速度快啊
# 4. 我们会达到什么样的效果(不包含括号)
[rediskey](user:111)[redisvalue]({"id":"111","name":"小明","cardId":"GTF001","code":"001"})
[rediskey](user:222)[redisvalue]({"id":"222","name":"小花","cardId":"GTF002","code":"002"})

重点来了,将脚本上传至服务器合适的文件夹下,准备命令进行执行

mysql -uroot -p数据库密码 -h 127.0.0.1 数据库名 --default-character-set=utf8 --skip-column-names --raw < userjson.sql | /usr/local/bin/redis-cli -h 127.0.0.1 -p 6379 -a redis库密码 -n redis库名 --pipe
# 第一部分mysql部分
# mysql -uroot -p数据库密码 -h 127.0.0.1 数据库名 这个就是命令行连接mysql数据库的命令
#  --default-character-set=utf8 默认字符
# --skip-column-names --raw 不输出列名
# < userjson.sql 执行脚本
# 第二部分Linux管道符
# | 把一个程序的结果交给另一个来处理 (不要忽视这个,特别重要)
# 第三部分redis-cli命令
# /usr/local/bin/redis-cli -h 127.0.0.1 -p 6379 -a redis库密码 -n redis库名 常规用redis-cli连接redis-server的命令
# --pipe redis-cli管道操作,也是管道
# 最后合起来, 将mysql的执行结果 交给 redis-cli 进行pipe操作,即从mysql抽取数据传输至redis数据库

一般情况下,不会出现太大问题,请尽量用centos做实验,windows问题太多不适合.

根据我的实操结果,大概68w条的数据,约12秒内即可完成存储,具体因数据宽度和记录条数影响

深化学习

AOF文件说明

pipe操作(Pipeline)

# 参考资料 https://zhuanlan.zhihu.com/p/72867786

RESP协议说明

RESP协议是在Redis 1.2中引入的,但它成为了与Redis 2.0中的Redis服务器通信的标准方式。这是所有Redis客户端都要遵循的协议,我们甚至可以基于此协议,开发实现自己的Redis客户端。
RESP实际上是一个支持以下数据类型的序列化协议:简单字符串,错误类型,整数,批量字符串和数组。

RESP在Redis中用作请求-响应协议的方式如下:

客户端将命令作为Bulk Strings的RESP数组发送到Redis服务器。

服务器根据命令实现回复一种RESP类型。
在RESP中,某些数据的类型取决于第一个字节:
“+”代表简单字符串Simple Strings
“+”代表错误类型
“:”代表整数
$代表Bulk Strings
“*”代表数组
此外,RESP能够使用稍后指定的Bulk Strings或Array的特殊变体来表示Null值。
在RESP中,协议的不同部分始终以“\r\n”(CRLF)结束。
# 参考资料 https://zhuanlan.zhihu.com/p/101564435

我们思考一个问题:为什么redis-cli 能通过pipe传输方式 将仿AOF的形式的数据存储至redis-server呢?

上一篇 下一篇

猜你喜欢

热点阅读