做開發的同學都知道,一旦設計到底層存儲優化,數據結構甚至數據庫的變更,通常都會進行數據遷移的工作。如果系統運行時間過長,數據遷移的數量可能非常龐大。這時候,如何進行高效的數據遷移,實際也是上線質量的直接影響因素之一。
下面內容是轉載的一個小技巧,無法適用於各種變化的場景,僅供大家參考。
場景是從MySQL中將數據導入到Redis的Hash結構中。當然,最直接的做法就是遍歷MySQL數據,一條一條寫入到Redis中。這樣可能沒什么錯,但是速度會非常慢。而如果能夠使MySQL的查詢輸出數據直接能夠與Redis命令行的輸入數據協議相吻合,可能就省事多了。
800w的數據遷移,時間從90分鍾縮短到2分鍾。
案例如下:
MySQL數據表結構:
Redis存儲結構:
HSET events_all_time [action] [count]
下面是重點,能過下面SQL語句將MySQL輸出直接變更成redis-cli可接收的格式:
然后用管道符重定向輸出即可:
- "hmset","usr"+i,"userid","usr"+i,"username","usrname"+i
格式: HSET events_all_time [15154668565] [d9ceef502ebc7ff98d3cdff3e3d0f51d]
參數個數,長度,命令,長度,命令......
*4
$4
HSET
$15
events_all_time
$11
15154668565
$32
d9ceef502ebc7ff98d3cdff3e3d0f51d
*4
$4
HSET
$15
events_all_time
$11
15154668565
$32
6b19f6970bf1c48221790374b0c000bd
*4
$4
HSET
$15
events_all_time
$11
15154668565
$32
51d2f0e3db7a901d7a42010a6ae53d4f
使用redis內部的數據格式然后走pipeline,比遍歷mysql一行一行的寫redis快多了!
使用Python操作Redis:
2 . 簡單的redis操作
redis連接實例是線程安全的,可以直接將redis連接實例設置為一個全局變量,直接使用。如果需要另一個Redis實例(or Redis數據庫)時,就需要重新創建redis連接實例來獲取一個新的連接。同理,python的redis沒有實現select命令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
>>> import redis
>>> r = redis.Redis(host='localhost',port=6379,db=0)
>>> r.set('guo','shuai')
True
>>> r.get('guo')
'shuai'
>>> r['guo']
'shuai'
>>> r.keys()
['guo']
>>> r.dbsize() #當前數據庫包含多少條數據
1L
>>> r.delete('guo')
1
>>> r.save() #執行“檢查點”操作,將數據寫回磁盤。保存時阻塞
True
>>> r.get('guo');
>>> r.flushdb() #清空r中的所有數據
True
|
3. pipeline操作
管道(pipeline)是redis在提供單個請求中緩沖多條服務器命令的基類的子類。它通過減少服務器-客戶端之間反復的TCP數據庫包,從而大大提高了執行批量命令的功能。
1
2
3
4
5
6
7
8
|
>>> p = r.pipeline() --創建一個管道
>>> p.set('hello','redis')
>>> p.sadd('faz','baz')
>>> p.incr('num')
>>> p.execute()
[True, 1, 1]
>>> r.get('hello')
'redis'
|
管道的命令可以寫在一起,如:
1
|
>>> p.set('hello','redis').sadd('faz','baz').incr('num').execute()
|
默認的情況下,管道里執行的命令可以保證執行的原子性,執行pipe = r.pipeline(transaction=False)可以禁用這一特性。
總結:redis的pipeline就是這么簡單,實際生產環境,根據需要去編寫相應的代碼。思路同理。線上的redis一般都是集群模式,集群模式下使用pipeline的時候,在創建pipeline的對象時,需要指定
pipe =conn.pipeline(transaction=False)
經過線上實測,利用pipeline取值3500條數據,大約需要900ms,如果配合線程or協程來使用,每秒返回1W數據是沒有問題的,基本能滿足大部分業務。
轉自: http://www.ttlsa.com/database/mysql_data_will_be_migrated_to_redis/
http://blog.51cto.com/leizhu/1825733