做开发的同学都知道,一旦设计到底层存储优化,数据结构甚至数据库的变更,通常都会进行数据迁移的工作。如果系统运行时间过长,数据迁移的数量可能非常庞大。这时候,如何进行高效的数据迁移,实际也是上线质量的直接影响因素之一。
下面内容是转载的一个小技巧,无法适用于各种变化的场景,仅供大家参考。
场景是从MySQL中将数据导入到Redis的Hash结构中。当然,最直接的做法就是遍历MySQL数据,一条一条写入到Redis中。这样可能没什么错,但是速度会非常慢。而如果能够使MySQL的查询输出数据直接能够与Redis命令行的输入数据协议相吻合,可能就省事多了。
800w的数据迁移,时间从90分钟缩短到2分钟。
案例如下:
MySQL数据表结构:
|
CREATE
TABLE
events_all_time
(
id
int
(
11
)
unsigned
NOT
NULL
AUTO_INCREMENT
,
action
varchar
(
255
)
NOT
NULL
,
count
int
(
11
)
NOT
NULL
DEFAULT
0
,
PRIMARY
KEY
(
id
)
,
UNIQUE
KEY
uniq_action
(
action
)
)
;
|
Redis存储结构:
HSET events_all_time [action] [count]
下面是重点,能过下面SQL语句将MySQL输出直接变更成redis-cli可接收的格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# vim events_to_redis.sql
SELECT
CONCAT
(
"*4\r\n"
,
'$'
,
LENGTH
(
redis_cmd
)
,
'\r\n'
,
redis_cmd
,
'\r\n'
,
'$'
,
LENGTH
(
redis_key
)
,
'\r\n'
,
redis_key
,
'\r\n'
,
'$'
,
LENGTH
(
hkey
)
,
'\r\n'
,
hkey
,
'\r\n'
,
'$'
,
LENGTH
(
hval
)
,
'\r\n'
,
hval
,
'\r'
)
FROM
(
SELECT
'HSET'
as
redis_cmd
,
'events_all_time'
AS
redis_key
,
action
AS
hkey
,
count
AS
hval
FROM
events_all
_time
)
AS
t
|
然后用管道符重定向输出即可:
|
# mysql stats_db --skip-column-names --raw < events_to_redis.sql | redis-cli --pipe
|
使用redis内部的数据格式然后走pipeline,比遍历mysql一行一行的写redis快多了!
转自:http://dcw.ca/blog/2013/01/02/mysql-to-redis-in-one-step/