zoukankan      html  css  js  c++  java
  • 一步完成MySQL向Redis迁移

    在把一个大表从 MySQL 迁移到 Redis 时,你可能会发现,每次提取、转换、导入一条数据是让人难以忍受的慢!这里有一个技巧,你可以通过使用管道把 MySQL 的输出直接输入到 redis-cli输入端,这可以使两个数据库都能以他们的最顶级速度来运行。

    使用了这个技术,我把 800 万条 MySQL 数据导入到 Redis 的时间从 90 分钟缩短到了两分钟。

    Mysql到Redis的数据协议

    redis-cli命令行工具有一个批量插入模式,是专门为批量执行命令设计的。这第一步就是把Mysql查询的内容格式化成redis-cli可用的数据格式。here we go!

    我的统计表:

    1. CREATE TABLE events_all_time (  
    2.   id int(11) unsigned NOT NULL AUTO_INCREMENT,  
    3.   action varchar(255) NOT NULL,  
    4.   count int(11) NOT NULL DEFAULT 0,  
    5.   PRIMARY KEY (id),  
    6.   UNIQUE KEY uniq_action (action)  
    7. ); 

    准备在每行数据中执行的redis命令如下:

    1. HSET events_all_time [action] [count

    按照以上redis命令规则,创建一个events_to_redis.sql文件,内容是用来生成redis数据协议格式的SQL:

    1. -- events_to_redis.sql  
    2.  
    3. SELECT CONCAT(  
    4.   "*4 ",  
    5.   '$', LENGTH(redis_cmd), ' ',  
    6.   redis_cmd, ' ',  
    7.   '$', LENGTH(redis_key), ' ',  
    8.   redis_key, ' ',  
    9.   '$', LENGTH(hkey), ' ',  
    10.   hkey, ' ',  
    11.   '$', LENGTH(hval), ' ',  
    12.   hval, ' ' 
    13. )  
    14. FROM (  
    15.   SELECT 
    16.   'HSET' as redis_cmd,  
    17.   'events_all_time' AS redis_key,  
    18.   action AS hkey,  
    19.   count AS hval  
    20.   FROM events_all_time  
    21. AS t 

    ok, 用下面的命令执行:

    1. mysql stats_db --skip-column-names --raw < events_to_redis.sql | redis-cli --pipe 

    很重要的mysql参数说明:

    --raw: 使mysql不转换字段值中的换行符。

    --skip-column-names: 使mysql输出的每行中不包含列名。

    redis数据批量导入导出

    针对工作中可能用到 将某台服务器中的redis数据 导出然后导入到新的服务器中,一种方法是redis-dump工具,但是 他需要安装ruby环境,安装环境的过程中还可能出现意想不到的错误。所以不得不选用其他方法了。一下 是几点思路 供参考。

    1、数据导出,不用自己写,也不用第三方脚本,
    echo "HGETALL xxx" | redis-cli -h localhost -p 6379
    echo "HGETALL xxx" | redis-cli -h localhost -p 6379 >> wordlist.raw
    2.这样得到的结果,你可以上到服务器上 查看 wordlist.raw文件
    3.整理成输入需要的文件格式 
    $f = 'xx.oo';
    $lines = 0;
    $inkey = 0;
    $rawfile = 'xx.oo';
    $hashkey = 'xx';
    $buff = '';
    $fp = fopen($rawfile,'w');
    $fps = fopen($f,'r');
    while($line= fgets($fps)){
     $inkey = !$inkey;
     if ($inkey){
    $f = 'bayes_wordlist.raw';
    $lines = 0;
    $inkey = 0;
    $rawfile = 'bayes_wordlist.3.raw';
    $hashkey = 'bayes_wordlist';
    $buff = '';
    $fp = fopen($rawfile,'w');
    $fps = fopen($f,'r');
    while($line= fgets($fps)){
     $inkey = !$inkey;
     if ($inkey){
      $line = sprintf('"%s"',trim($line));
      $buff = "HSET $hashkey ".trim($line);
      }
     else
     {
      $buff .= ' "'.trim($line).'"';
      fwrite($fp,$buff." ");
     }
    }
      $buff = "HSET $hashkey ".trim($line);
     }
     else
     {
      $buff .= ' "'.trim($line).'"';
      fwrite($fp,$buff." ");
     }
    }
    如果选择哪个库 要在首行写入 select x
    4.利用redis-cli进行导入
    echo `date` > pipe.log && cat xx.oo | redis-cli >> pipe.log && echo `date` >> pipe.log
    5.加上了时间记录,和对导入结果进行纪录,真正执行导入的语句是
    cat wordlist.raw | redis-cli,当然严谨些的话redis-cli后面还要加-h localhost -p 6379等参数。

  • 相关阅读:
    Java里的阻塞队列
    ReentrantReadWriteLock读写锁实现分析
    策略模式
    Java线程池技术以及实现
    分布式锁的思路以及实现分析
    Protobuf入门实例
    配置maven环境变量并安装jar包到本地仓库
    nio简单客户端服务端实例
    Java内存模型(JMM)中的happens-before
    Java中锁的内存语义
  • 原文地址:https://www.cnblogs.com/hujihon/p/3745351.html
Copyright © 2011-2022 走看看