最近遇到一個問題:用python寫500W+的數(shù)據(jù)到redis,時間要花費2小時左右。該如何優(yōu)化呢?
redis介紹
Redis是REmote DIctionary Server的縮寫。對Redis的作用的不同解讀決定了你對Redis的使用方式。如果你認(rèn)為Redis是一個key value store, 那可能會用它來代替MySQL;如果認(rèn)為它是一個可以持久化的cache, 可能只是用它保存一些頻繁訪問的臨時數(shù)據(jù)。有一些看法則認(rèn)為Redis是一個memory database,因為它的高性能都是基于內(nèi)存操作的基礎(chǔ)。另外一些人則認(rèn)為Redis是一個data structure server,因為Redis支持復(fù)雜的數(shù)據(jù)特性,比如List, Set等。
互聯(lián)網(wǎng)數(shù)據(jù)目前基本使用兩種方式來存儲,關(guān)系數(shù)據(jù)庫或者key value( NoSQL)。但是這些互聯(lián)網(wǎng)業(yè)務(wù)本身并不屬于這兩種數(shù)據(jù)類型,比如用戶在社會化平臺中的關(guān)系,它是一個list,如果要用關(guān)系數(shù)據(jù)庫存儲就需要轉(zhuǎn)換成一種多行記錄的形式,這種形式存在很多冗余數(shù)據(jù),每一行需要存儲一些重復(fù)信息。如果用key value存儲則修改和刪除比較麻煩,需要將全部數(shù)據(jù)讀出再寫入。Redis在內(nèi)存中設(shè)計了各種數(shù)據(jù)類型,讓業(yè)務(wù)能夠高速原子的訪問這些數(shù)據(jù)結(jié)構(gòu),并且不需要關(guān)心持久存儲的問題,從架構(gòu)上解決了前面兩種存儲需要走一些彎路的問題。
redis數(shù)據(jù)類型
String
string 類型是二進(jìn)制安全的。意思是 redis 的 string 可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對象。
Hash
Redis hash 是一個 string 類型的 key 和 value 的映射表,hash 特別適合用于存儲對象。
List
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。
Set
Redis的Set是string類型的無序集合。集合是通過哈希表實現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是O(1)。
zset
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復(fù)的成員。 不同的是每個元素都會關(guān)聯(lián)一個double類型的分?jǐn)?shù)。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。zset的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。
redis在推薦系統(tǒng)中的使用
目前我們是把所有模型計算的結(jié)果用zset的數(shù)據(jù)結(jié)構(gòu)寫入redis,其中key的設(shè)計為:
value是商品ID和商品分?jǐn)?shù)的字典表。
利用pipeline和多線程寫大量數(shù)據(jù)到redis
Redis是一種基于客戶端-服務(wù)端模型以及請求/響應(yīng)協(xié)議的TCP服務(wù)。這意味著通常情況下一個請求會遵循以下步驟:
- 客戶端向服務(wù)端發(fā)送一個查詢請求,并監(jiān)聽Socket返回,通常是以阻塞模式,等待服務(wù)端響應(yīng)。
- 服務(wù)端處理命令,并將結(jié)果返回給客戶端。
Redis 管道技術(shù)可以在服務(wù)端未響應(yīng)時,客戶端可以繼續(xù)向服務(wù)端發(fā)送請求,并最終一次性讀取所有服務(wù)端的響應(yīng)。能夠有效地提高redis服務(wù)的性能。
500萬條數(shù)據(jù)用pipeline和不用pipeline時間測試
用pipeline
可見,500萬條數(shù)據(jù)在使用pipeline比不適用pileline速度快了一倍~是不是可以用多線程讓它再快一些呢