DBAplusコミュニティ 今日
次の記事では男の夢夏の夢のノートの開発から来ています
序文
システムの動作により、データの量がより多く、簡単にMySQLでは、すでに照会のデータストレージ要件を満たすことができないだろう、この時間は、我々はクエリキャッシュ層としてのRedisを紹介なり、熱がRedisのに業務データが保存されます、従来のリレーショナルデータベースサービス機能の拡張、ユーザーが迅速にRedisの共通のデータから直接アプリケーションを介して取得、または対話型アプリケーションでのアクティブなユーザセッションを保存するためのRedisを使用し、大幅にアップグレードし、バックエンドのリレーショナルデータベースの負荷を軽減することができますユーザーエクスペリエンス。
伝統的なコマンドの欠点
シーンに大量のデータの欠陥次従来のRedisのクライアントコマンドを使用します:
Redisのモデルはシングルスレッドであるため、マルチスレッドを迅速にスレッド切り替え時間がかかり、逐次単一の実行コマンドが回避が、データのインポートシーンの大量に、コマンドの結果に応答してサーバによって送信された受信時間がかかるされかかる時間は増幅されます。
インポートデータ1,000,000に必要がある場合は、単にコマンド実行時間という、それは1,000,000 *(T1 + T2)かかります。
コマンドを一つずつ送信することに加えて、当然のことながら、Redisのデザインは確かにパイプラインモードをパイプラインので、そこに、この問題を検討します。
しかし、コマンドラインをパイプライン化することはできませんので、我々は、応答数量を受信するために、新たな処理コードを記述する必要があります。しかし、このようなPHP-Redisの拡張としてだけ非常に少ないサポートクライアント側のコードは、非同期をサポートしていません。
パイプラインモードパイプライン、実際には、コマンドのバッチが終了するTCPコネクションの相互作用時間を短縮し、1回の結果を送信します。
原理は、データの順序ことを保証するために、そのFIFO(先入れ先出し)キューを使用することです。
クライアント支持体の小さい部分のみ、ノンブロッキングI / Oは、すべてのクライアントは、スループット最大化するための答えを解決するための効果的な方法することができません。
これらの理由から、RedisのRedisのプロトコル・データ・フォーマットを含んで形成されているデータの膨大な量を導入する好ましい方法は、バッチは、過去に送信されます。
データのインポートのRedisのウォームアップ
NCを使用してデータをインポートするためのコマンド
NCはnetcatを速記で、NC役割は以下のとおりです。
1)任意のTCP / UDPポートリスナーは、モード指定されたポートをリスニングにTCPやUDPサーバとしてパラメータ-l、NCを増加させた後。
2)ポートスキャン、TCPやUDPの接続を開始することができるクライアントであるNC。
3)マシン間でファイルを転送します。
4)機械速度ネットワークとの間。
モデルのパイプを使用してデータをインポート
すべてのデータを送信する際のnetcatが本当にエラーをチェックすることができない、知らないのでしかし、リスナーNC使用は、大規模データのインポートを実行するための非常に信頼性の高い方法ではありません。Redisの中にバージョン2.6以降では、Redisの-cliスクリプトは、このモデルは、大規模と設計を実行するために挿入され、パイプのパイプラインモードと呼ばれる新しいモデルをサポートしています。次のように使うパイプラインモードのコマンドは動作します。
上記のチャートから、あなたがそこにコマンドtxtファイル内にあり、数は回答の数で返す行数コマンドリターンパイプの結果を見ることができ、エラーは実行中の間違ったコマンドの数を示しています。
Redisのプロトコル学習
次のようにプロトコルの形式は次のとおりです。
*<参数数量> \r\n
$<参数 1 的字节数量> \r\n
<参数 1 的数据> \r\n
...
$<参数 N 的字节数量> \r\n
<参数 N 的数据> \r\n
例:データ型のハッシュを挿入します。
HSET id book1 book_description1
契約、四つの部分の合計なので、残りは次のように説明されている* 4で始まるに従って、Redisの:
注:HSETコマンド自体が送信するためのプロトコルなどのパラメータの一つです。
プロトコルデータ構造を構築します:
*4\r\n$4\r\nHSET\r\n$2\r\nid\r\n$5\r\nbook1\r\n$17\r\nbook_description1\r\n
フォーマット:
*4\r\n
$4\r\n
HSET\r\n
$2\r\n
idvvvv\r\n
$5\r\n
book1\r\n
$17\r\n
book_description1\r\n
RESP契約バルク
クライアントのRedisによって使用される通信プロトコルは、RESP(Redisのシリアライゼーションプロトコル)サーバとのRedisと呼ばれます。
迅速かつコマンドNC問題を解決としてのRedis-CLIコマンドモードNCパイプやニーズは、コマンドを終了したときに知りません。
同時にデータを送信し、それはまた、読んで解決しようとするために応答します。
同じデータを応答結果に一致している場合、より多くのデータが読み出されていない入力ストリームと、それは特別な20ビットのエコーコマンドが送信され、識別は、最後のコマンドは、このバッチに記載され、送信されてきました成功を送信します。
この技術を使用して、我々は、コマンドを送信どのくらい知っているサーバーに送信された解決プロトコルを必要としない、あなただけの応答を解析する必要があります。
応答を解析すると、Redisの答えが挿入多数のコマンドを送信するサーバーにユーザーに伝えることができ、セッションの最後の数にカウントすることが解決されます。私たちは、パイプが結果に応じて、実際の動作モードの上で使用しています。
MySQLへの入力データソース
上記の例では、テキスト入力、データソース、データのインポートモードパイプにtxtを。
これらの契約の学習と理解基づいて、我々は唯一のRedisをインポートすることができ、パイプモードによって確立されたプロトコルに従って、MySQLのデータを必要とします。
百万のRedisへのMySQLからデータをインポートします
まず製データ
環境の制約のため、その導入を達成するためには実際のデータが存在しない、我々は百万事実と数字を作成するために、ストアドプロシージャを使用する必要があります。次の手順を使用して保存されました:
DELIMITER $$
USE `cb_mon`$$
DROP PROCEDURE IF EXISTS `test_insert`$$
CREATE DEFINER=`root`@`%` PROCEDURE `test_insert`()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<= 1000000
DO
INSERT INTO t_book(id,number,NAME,descrition)
VALUES (i, CONCAT("00000",i) , CONCAT('book',i)
, CONCAT('book_description',i));
SET i=i+1;
END WHILE ;
COMMIT;
END$$
DELIMITER ;
ストアドプロシージャを呼び出します。
CALL test_insert();
テーブルのデータを表示します。
クエリステートメントを構築することで合意によります。
上記の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,
id AS redis_key,
NAME AS hkey,
descrition AS hval
FROM
cb_mon.t_book
) AS t limit 1000000
Redis.sqlはファイルに内容を保存します。
パイプモデルのインポートのRedisを使ってスクリプティング
シェルスクリプトを書きます。私は、MySQL、参照用に次のスクリプトをインストールドッキングウィンドウとのRedisを介してホストにしていますので:
#!/bin/bash
starttime=`date +'%Y-%m-%d %H:%M:%S'`
docker exec -i 899fe01d4dbc mysql --default-character-set=utf8
--skip-column-names --raw < ./redis.sql
| docker exec -i 4c90ef506acd redis-cli --pipe
endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s);
end_seconds=$(date --date="$endtime" +%s);
echo "脚本执行耗时:"$((end_seconds-start_seconds))"s"
スクリーンショットの実行:
あなたは百万データは、Redisのをインポートするだけで7秒かかっ見ることができ、効率が非常に高いです。
注意事項
MySQLのテーブルが特に大きい場合には、バッチインポートを検討、またはテーブルを分割するか、インポート処理中に発生する可能性があります。
lost connection to mysql server during query
max_allowed_packedタイムアウト制限するので、データクエリの処理は、断線を引き起こし得る必要がページテーブルを分割または導入することが特にデータテーブル内のデータの量がそれほど。
概要
この記事では、効率的Redisのを、外出先に移行する方法を、次のMySQL上の順序の百万データを焦点を当て、徐々にコースの目標を達成するため、以下の点をまとめました。
スレッド切り替え時間を避けるために図1に示すように、実行コマンドのRedisの単一スレッドは、消費が、遅延の受信に応答して、大規模なデータ送信のために無視することはできません。
2、ネットワークシナリオNCコマンド、および欠点の存在下でのデータをインポート。
3、RedisのRESP契約の理解と応用。
MySQLのデータを素早くインポート例4百万のRedisのため。
著者シュウ夏の夢
開発ノートのソースシュウ夏の夢(ID:xmdevnote)
dbaplusコミュニティが技術者を貢献することを歓迎している、提出Eメール:[email protected]