pika_to_redis数据迁移工具设计与实现过程

背景

为满足运维人员对于pika可以更好地运维,需要方便地将数据从pika迁移到redis,在pika系统中之前已经为运维人员提供了Redis请求实时copy到pika工具可以实时将redis上的请求同步发送到pika,这个工具则是为了能够将离线的pika数据迁移至redis。

最终目标

  1. 保证数据迁移结果的正确性
  2. 满足目标的条件下,在能够接受的时间下完成任务

实现代码

https://github.com/Qihoo360/nemo/tree/pika_to_redis/tools/migator

实现

版本1:串行可用版

目标

  1. 走通这个数据迁移的流程,确定实现方案的可行性
  2. 为下一版本优化方向做准备

方案

使用串行方式,将整个迁移过程分为三个阶段,如下:

  1. 利用pika数据引擎的接口,将所有数据遍历出来
  2. 利用得到的数据,生成相对应的redis指令(SET,HSET,RPUSH)
  3. 使用pika内部的pink::RedisCli接口,将指令发送给redis服务器并接收响应
    并在每个阶段计时分析以便后面优化。

结果

验证方案可行,但是速度难以接受,迁移10G数据需要20小时以上。从迁移过程的三个步骤中,可以看到无论是数据扫描还是,指令的发送和接收响应都非常慢。分析其原因,主要在于:

  1. 单线程,没有发挥机器多核优势
  2. 在与redis服务器的交互过程为,发送一条数据,并等待一条数据的响应,导致速度很慢

改进措施

在版本1不能满足速度要求之后,发现redis官方客户端提供有一种可以大规模数据插入的方式pipeline mode,使用的基本形式如下:

cat cmd.txt | redis-cli --pipe
# 其中cmd.txt中存的是符合redis协议的指令文本

对现有程序稍加改动,将生成的redis指令直接写入标准输入流,即可使用pipe mode方式,通过千万条数据测试,在本地效果提高30%以上。这种方案速度较之前大幅提升,在于节省了大量浪费在每个指令返回的时间。

但是直接使用这种方案,虽然速度提升不少,完成时间还是不能满足要求。由于这种方式,还是只能使用一个发送端,不方便后期进行多线程的优化。接下来需要自己定制实现pipeline mode

版本2:定制实现pipeline模式

方案

在pika自己实现的客户端中,只能是逐条发送指令,逐条接收。redis官方客户端的实现方式:

  1. socket_fd 设置为非阻塞
  2. 使用poll监听socket_fd的状态,调度指令的发送和响应的接收
  3. 从标准输入流中读入数据(redis指令),放入一个buf中,在将buf中的数据不停写入到socket
  4. 批量接收redis服务器的响应,并将其解析判断如果出现错误,则将错误显示出来
  5. 从标准输入流中读不到数据之后,向redis发送一条ECHO指令,用于标示发送结束

实质上官方客户端是将生成指令和发送指令分别放在两个不同的进程中,在这里模拟标准输入和标准输出,则可以自己开一条管道,一端将指令写入,一端读出指令并发送。

结果

在实现了之后,速度确实有提升,但是发现之前官方客户端从标准输入中读入数据是因为使用场景所限制,大可将管道那一层去掉,让自己管理buf,就少了将数据写入内核,有从内核读出过程,只是自己需要维护buf的读写,这是一个典型的生产者消费者模型。在分析完成之后,对pipeline进行小幅的改进。

改进版本:自己管理buf

  1. 在内存开辟一个数组作为buf,并维护buf的中需要发送的数据长度len和发送数据起始点pos
  2. 为充分发挥非阻塞发送的优势,将发送部分单独放在一个线程中执行,需要改变len和pos对其加锁

版本3:多客户端并行和多库并行

方案

在完成了上面的版本之后,就可以对整个流程进行多线程的优化。由于当前数据的发送并非是整条发送出去,buf的管理都粒度都是在字符级别,所以采用一个指令生成线程(parser)和发送线程(sender)一一对应。

  1. 多客户端并行:建立一个线程池,parser和sender线程组成一个线程组。
  2. 多库并行:由于nemo底层上,不同数据格式的管理都有一个自己rocksdb实例,所以多库并行,做起来也是非常简便的。最终结果能够提升10%左右。

整体架构图如下:


migrator线程
  1. 扫描不同数据类型的分库
  2. 将扫描到key分发给parser线程
parser线程
  1. 接收migrator发送的key
  2. 将key进行解析成响应数据redis指令
  3. 将解析好的redis指令加载到sender的发送buf中
sender线程
  1. 从发送buf中读取数据,以非阻塞方式向redis发送数据
  2. 接收redis返回的结果并解析,如果出现错误则显示错误结果

结果

至此,数据迁移工具在性能上已经从原先需要20小时迁移的数据到现在大概40分钟左右,完全满足最初的时间要求。

测试

测试结果:

  1. 在每个同时使用10个发送端(可配置)情况下,不同机器之间每小时平均能够转移15G
  2. 测试结果,均得到正确性验证

测试分析:

  1. 数据条数对速度影响比数据量更大,见Test2
  2. 并行线程越多,速度越快,见Test3
  3. 本地迁移比不同机器上速度快50%左右,见Test4

测试说明

机器配置说明:

名称 内存 cpu
bada05 160G 24*2.6Hz
bada06 160G 24*2.6Hz

测试数据源说明:

名称 key长度 亿条数据磁盘占用 1G数据数据条数
长数据 30字符 2.1G 0.46亿条
短数据 180字符 6.3G 0.15亿条

性能测试

Test1:远程测试

bada05->bada06 短数

数据库 客户端数量 数据量 数据条数 消耗时间 速度(每小时)
All 10 15.6G 1.5亿*5 3.5小时 4.5G/2.2亿
kv 10 1.2G 1.5亿 32min 2.3G/2.8亿
hash 10 3.2G 1.5亿 45min 4.3G/2亿
set 10 2.8G 1.5亿 40min 4.2G/2.3亿
zset 10 5.6G 1.5亿 41min 8.2G/2.2亿

Test2:数据源的影响

远程测试:bada05->bada06

数据库| 发送端数量| 数据量| 数据条数 |消耗时间| 速度(每小时)
---|---|---|---|---|---|---|---|---|---|---|---
All(短)| 10| 16G| 1.5亿*5 |3.5h| 4.5G/2.1亿
set(短)| 10| 2.8G| 1.5亿 |40min| 4.2G/2.3亿
set(长)| 10| 2.5G |3.8千万 |10min |15G/2.2亿
hash(长)| 10| 3.3G|3.8千万 |10min |20G/2.2亿
kv(长)| 10| 1.6G| 3.8千万| 8min| 12G/2.8亿
list(长)| 10| 2.8|3.8千万| 10min| 16G/2.2亿
注:由于长数据中,不同数据类型key有重复,无法正常导入redis,故采用分库导入

Test3:发送线程数量的影响

bada05->bada06 短数据

线程数量| 数据量|数据条数 |消耗时间| 速度(每小时)
---|---|---|---|---|---|---|---|---
10| 16G| 1.5亿5| 3.5小时| 4.5G/2.1亿
16| 16G| 1.5亿
5| 2.3小时| 7.1G/3.3亿
20| 16G| 1.5亿*5| 2.1小时| 7.5G/3.5亿

Test4:本地和远程对比

|线程数量| 数据量| 数据条数| 速度(每小时)
---|---|---|---|---|---|---
异地|10 |16G |1.5亿5| 3.5h 4.5G/2.1亿
本地|10 |16G |1.5亿
5| 1.9h 8.1G/3.8亿


正确性测试

测试方法:

  1. 压入一批pika数据,每条数据的key,都有唯一的顺序的序列号
  2. 迁移完毕之后。向redis发送不同数据get请求,得到返回之后与预期结果做对比

测试结果:

  1. 本地迁移不同类型数据各1000万条,完全通过
  2. 远程迁移不同数据各1000万条,完全通过
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容

  • 本次分享主题 pika 是360 DBA和基础架构组联合开发的类redis 存储系统, 完全支持Redis协议,用...
    ba0tiao阅读 4,583评论 2 4
  • 1.1 资料 ,最好的入门小册子,可以先于一切文档之前看,免费。 作者Antirez的博客,Antirez维护的R...
    JefferyLcm阅读 17,050评论 1 51
  • 英语单词Indicators 指针 指示信号 轮播图的小圆点filter 过滤 控制台 点h...
    chuhx阅读 205评论 0 0
  • 在我认知的很多大牛里面,写作(或者换个层面说叫思考)已经成了生活必不可少的东西了。“逻辑思维”每天六点半会定时发布...
    币学社区阅读 356评论 0 3
  • 1.障碍 影响决策的两大障碍:自我意识和思维盲点。这两大障碍让你难以客观的看待自己和利用他人帮助。 2.自我意识—...
    持续学习持续成长阅读 277评论 0 1