redis大數據
1. 華為大數據平台如何查看redis集群埠
華為大數據平台redis集群埠
註:ip為安裝redis的那台伺服器(集群中的其中一台)的ip,password為redis的密碼
集群相關信息查看
1.集群狀態
redis-cli -h ip -p 9379 -a password cluster info
2.集群節點信息
redis-cli -h ip -p 9379 -a password cluster nodes
3.節點內存、cpu、key數量等信息(每個節點都需查看)
redis-cli -h ip -p 9379 -a password info
2. Spark和Redis結合使用到底有多大的性能提升呢45倍
Spark代表著下一代大數據處理技術,並且,借著開源演算法和計算節點集群分布回式處理,Spark和Hadoop在執行答的方式和速度已經遠遠的超過傳統單節點的技術架構。但Spark利用內存進行數據處理,這讓Spark的處理速度超過基於磁碟的Hadoop 100x 倍。
但Spark和內存資料庫Redis結合後可顯著的提高Spark運行任務的性能,這源於Redis優秀的數據結構和執行過程,從而減小數據處理的復雜性和開銷。Spark通過一個Redis連接器可以訪問Redis的數據和API,加速Spark處理數據。
Spark和Redis結合使用到底有多大的性能提升呢?結合這兩者來處理時序數據時可以提高46倍以上——而不是提高百分之四十五。
3. redis 數據達到多少存磁碟
IO:輸入輸出。
從內存讀取數據叫輸出,將數據寫入內存叫輸入。
大數據IO就是指在磁碟與內存之間傳輸大量數據的意思咯。只不過因為數據太大內存容納不下需要進行多次部分寫入。
數據在磁碟上是無法完成查找的,要麼被調入內存,要麼有磁碟數據的索引(索引調入內存)。計算機所有操作都是在內存中進行的,磁碟是外設。
4. redis大數據並發有哪些測試點
Libevent。和Memcached不同,Redis並沒有選擇libevent。Libevent為了迎合通用性造成代碼龐大(目前內Redis代碼還不到libevent的1/3)及犧容牲了在特定平台的不少性能。Redis用libevent中兩個文件修改實現了自己的epoll event loop(4)。 業界不少開發者
5. 大量數據能緩存到redis裡面嗎
不適合引子:
在大數據時代,總希望存在一個Key-value存儲機制,像HashMap一樣在內存中處理大量(千萬數量級)的key-value對,以便提高數據查找、修改速度。
所以,我們會想到,Memcached和Redis這兩個NoSQL資料庫(嚴格來講二者都不可以算作資料庫)。
1、Memcached是一個cache機制,當內存不足時會採用LRU機制,替換出陳舊數據,因此他不能保證我們的數據像在HashMap中一樣不丟失,且沒有數據持久化機制;
2、Redis克服了這一缺點,採取磁碟存儲機制實現數據持久化。但是,當數據量達到1千萬左右時,由於內存中不能存儲如此大量數目的數據,頻繁同磁碟進行數據交換,導致數據查詢、存儲性能的急劇下降,將導致服務不可用。
結論:當前還沒有好的產品可以實現key-value保證數據完整性,千萬級條數量級的,高效存儲和查詢支持產品。
附錄一:如下是轉自其它網友的測試數據:
附錄二:memcached 和redis的比較,和各自用途
附錄一:
從圖中可以猜測到還會有Redis 2.2.1 的測試,相同的測試環境,1K的數據量,使用ServiceStack.Redis客戶端進行如下測試:
1) Set操作
2) Get操作
3) Del操作
每一套測試分別使用三個配置進行測試:
1) 綠色線條的是開啟Dump方式的持久化,5分鍾持久化一次
2) 藍色線條是開啟AOF方式的持久化,每秒寫入磁碟一次
3) 紅色線條是關閉任何的持久化方式
對於每一個配置都使用相同的其他配置:
1) 開啟VM 最大內存10GB(128位元組一
6. 總結redis在節省內存開銷方面做過哪些設計
因為是拿 Python 測試的,所以可能對其他語言並不完全適用。
使用的測試數據是特定的,可能對更小或更大的數據並不完全適用。
測試結果就不列出了,直接說結論吧。
最差的存儲方式就是用一個 hash 來存儲一個實體(即一條記錄)。時間上比其他方案慢 1 ~ 2 倍,空間佔用較大。
更重要的是拿出來的欄位類型是字元串,還得自己轉換類型。
唯一的好處就是可以單獨操作一個欄位。
使用 string 類型來存儲也是不推薦的,不過稍好於前一種方式。在單個實體較小時,會暴露出 key 佔用內存較多的缺點。
用一個 hash 來存儲一個類型的所有實體(即一張表),在實現上比較簡單,內存佔用尚可。
用多個 hash 來存儲一個類型的所有實體(即分表),在實現上稍微復雜點,但佔用的內存最小。
如果單個欄位值較小(預設值是 64 位元組),單個 hash 存儲的欄位數不多(預設值是 512 個)時,會採用 hash zipmap 來存儲,內存佔用會顯著減小。
單個 hash 存儲的欄位數建議為 2 的次方,例如 1024。略微超過這個值,會導致內存佔用和延遲時間都增加。
Instagram 的工程師認為,使用 hash zipmap 時,最佳的欄位數為 1000 左右。不過據我測試,基本都是隨欄位數增加而變慢,而內存佔用從 128 直到 1024 的變化基本可以忽略。
存儲為 JSON 格式是種不錯的選擇。對包含中文的內容來說,設置 ensure_ascii=False 可以節省大量內存。
ujson 比 json 性能好很多,後者在設置 ensure_ascii=False 後性能急劇下降。
cPickle 比 ujson 的性能要差,不過支持更多類型(如 datetime)。
MessagePack 比 ujson 有一點不太明顯的性能優勢,不過喪失了可讀性,且取回 unicode 需要自己 decode。
號稱比 Protocol Buffer 快 4 倍應該可以無視了,至少其 Python 庫沒有明顯優勢。
使用 zlib 壓縮可以節省更多內存,不過性能變慢 1 ~ 2 倍。
看這個測試結果,感覺還不如用 MongoDB 省事……
7. 如何取出大數據量的 redis hash 結構的數據並遍歷導出
就看你的數據量大小了,如果太大,卻是不好遍歷,如果有規則的key值的話,倒是可以利用分頁的方式來處理,如果沒有規律的話,只有用keys*來取了,或者是通過keysa*;keysz*;keys1*;keys0*等通配符的方式來順序的讀取,讀取時要把內存分配的大一些,不然容易溢出
8. 你所了解的大數據,是真正的大數據嗎
什麼是大數據
大數據是指無法在一定時間內用常規軟體工具對其內容進行抓取、管理和處理的數據集合。大數據技術,是指從各種各樣類型的數據中,快速獲得有價值信息的能力。適用於大數據的技術,包括大規模並行處理(MPP)資料庫,數據挖掘電網,分布式文件系統,分布式資料庫,雲計算平台,互聯網,和可擴展的存儲系統。
大數據時代存儲所面對的問題
隨著大數據應用的爆發性增長,它已經衍生出了自己獨特的架構,而且也直接推動了存儲、網路以及計算技術的發展。畢竟處理大數據這種特殊的需求是一個新的挑戰。硬體的發展最終還是由軟體需求推動的,就這個例子來說,我們很明顯的看到大數據分析應用需求正在影響著數據存儲基礎設施的發展。
從另一方面看,這一變化對存儲廠商和其他IT基礎設施廠商未嘗不是一個機會。隨著結構化數據和非結構化數據量的持續增長,以及分析數據來源的多樣化,此前存儲系統的設計已經無法滿足大數據應用的需要。存儲廠商已經意識到這一點,他們開始修改基於塊和文件的存儲系統的架構設計以適應這些新的要求。在這里,我們會討論哪些與大數據存儲基礎設施相關的屬性,看看它們如何迎接大數據的挑戰。
容量問題
這里所說的「大容量」通常可達到PB級的數據規模,因此,海量數據存儲系統也一定要有相應等級的擴展能力。與此同時,存儲系統的擴展一定要簡便,可以通過增加模塊或磁碟櫃來增加容量,甚至不需要停機。基於這樣的需求,客戶現在越來越青睞Scale-out架構的存儲。Scale-out集群結構的特點是每個節點除了具有一定的存儲容量之外,內部還具備數據處理能力以及互聯設備,與傳統存儲系統的煙囪式架構完全不同,Scale-out架構可以實現無縫平滑的擴展,避免存儲孤島。
「大數據」應用除了數據規模巨大之外,還意味著擁有龐大的文件數量。因此如何管理文件系統層累積的元數據是一個難題,處理不當的話會影響到系統的擴展能力和性能,而傳統的NAS系統就存在這一瓶頸。所幸的是,基於對象的存儲架構就不存在這個問題,它可以在一個系統中管理十億級別的文件數量,而且還不會像傳統存儲一樣遭遇元數據管理的困擾。基於對象的存儲系統還具有廣域擴展能力,可以在多個不同的地點部署並組成一個跨區域的大型存儲基礎架構。
延遲問題
「大數據」應用還存在實時性的問題。特別是涉及到與網上交易或者金融類相關的應用。舉個例子來說,網路成衣銷售行業的在線廣告推廣服務需要實時的對客戶的瀏覽記錄進行分析,並准確的進行廣告投放。這就要求存儲系統在必須能夠支持上述特性同時保持較高的響應速度,因為響應延遲的結果是系統會推送「過期」的廣告內容給客戶。這種場景下,Scale-out架構的存儲系統就可以發揮出優勢,因為它的每一個節點都具有處理和互聯組件,在增加容量的同時處理能力也可以同步增長。而基於對象的存儲系統則能夠支持並發的數據流,從而進一步提高數據吞吐量。
有很多「大數據」應用環境需要較高的IOPS性能(IOPS (Input/Output Operations Per Second),即每秒進行讀寫(I/O)操作的次數,多用於資料庫等場合,衡量隨機訪問的性能),比如HPC高性能計算。此外,伺服器虛擬化的普及也導致了對高IOPS的需求,正如它改變了傳統IT環境一樣。為了迎接這些挑戰,各種模式的固態存儲設備應運而生,小到簡單的在伺服器內部做高速緩存,大到全固態介質的可擴展存儲系統等等都在蓬勃發展。
並發訪問一旦企業認識到大數據分析應用的潛在價值,他們就會將更多的數據集納入系統進行比較,同時讓更多的人分享並使用這些數據。為了創造更多的商業價值,企業往往會綜合分析那些來自不同平台下的多種數據對象。包括全局文件系統在內的存儲基礎設施就能夠幫助用戶解決數據訪問的問題,全局文件系統允許多個主機上的多個用戶並發訪問文件數據,而這些數據則可能存儲在多個地點的多種不同類型的存儲設備上。
安全問題
某些特殊行業的應用,比如金融數據、醫療信息以及政府情報等都有自己的安全標准和保密性需求。雖然對於IT管理者來說這些並沒有什麼不同,而且都是必須遵從的,但是,大數據分析往往需要多類數據相互參考,而在過去並不會有這種數據混合訪問的情況,因此大數據應用也催生出一些新的、需要考慮的安全性問題。
成本問題
「大」,也可能意味著代價不菲。而對於那些正在使用大數據環境的企業來說,成本控制是關鍵的問題。想控製成本,就意味著我們要讓每一台設備都實現更高的「效率」,同時還要減少那些昂貴的部件。目前,像重復數據刪除等技術已經進入到主存儲市場,而且現在還可以處理更多的數據類型,這都可以為大數據存儲應用帶來更多的價值,提升存儲效率。在數據量不斷增長的環境中,通過減少後端存儲的消耗,哪怕只是降低幾個百分點,都能夠獲得明顯的投資回報。此外,自動精簡配置、快照和克隆技術的使用也可以提升存儲的效率。
很多大數據存儲系統都包括歸檔組件,尤其對那些需要分析歷史數據或需要長期保存數據的機構來說,歸檔設備必不可少。從單位容量存儲成本的角度看,磁帶仍然是最經濟的存儲介質,事實上,在許多企業中,使用支持TB級大容量磁帶的歸檔系統仍然是事實上的標准和慣例。
對成本控制影響最大的因素是那些商業化的硬體設備。因此,很多初次進入這一領域的用戶以及那些應用規模最大的用戶都會定製他們自己的「硬體平台」而不是用現成的商業產品,這一舉措可以用來平衡他們在業務擴展過程中的成本控制戰略。為了適應這一需求,現在越來越多的存儲產品都提供純軟體的形式,可以直接安裝在用戶已有的、通用的或者現成的硬體設備上。此外,很多存儲軟體公司還在銷售以軟體產品為核心的軟硬一體化裝置,或者與硬體廠商結盟,推出合作型產品。
數據的積累
許多大數據應用都會涉及到法規遵從問題,這些法規通常要求數據要保存幾年或者幾十年。比如醫療信息通常是為了保證患者的生命安全,而財務信息通常要保存7年。而有些使用大數據存儲的用戶卻希望數據能夠保存更長的時間,因為任何數據都是歷史記錄的一部分,而且數據的分析大都是基於時間段進行的。要實現長期的數據保存,就要求存儲廠商開發出能夠持續進行數據一致性檢測的功能以及其他保證長期高可用的特性。同時還要實現數據直接在原位更新的功能需求。
靈活性
大數據存儲系統的基礎設施規模通常都很大,因此必須經過仔細設計,才能保證存儲系統的靈活性,使其能夠隨著應用分析軟體一起擴容及擴展。在大數據存儲環境中,已經沒有必要再做數據遷移了,因為數據會同時保存在多個部署站點。一個大型的數據存儲基礎設施一旦開始投入使用,就很難再調整了,因此它必須能夠適應各種不同的應用類型和數據場景。
應用感知
最早一批使用大數據的用戶已經開發出了一些針對應用的定製的基礎設施,比如針對政府項目開發的系統,還有大型互聯網服務商創造的專用伺服器等。在主流存儲系統領域,應用感知技術的使用越來越普遍,它也是改善系統效率和性能的重要手段,所以,應用感知技術也應該用在大數據存儲環境里。
小用戶怎麼辦?
依賴大數據的不僅僅是那些特殊的大型用戶群體,作為一種商業需求,小型企業未來也一定會應用到大數據。我們看到,有些存儲廠商已經在開發一些小型的「大數據」存儲系統,主要吸引那些對成本比較敏感的用戶。
9. 有哪些大數據服務架構 hadoop redis hbase spark hive storm
大數據分很多塊,包括內存資料庫,mpp,hadoop,實時流處理,數據抽取轉換,可視化等。每一塊查一下就知道了,內容太多
10. redis這些內存消耗數據怎麼看呢,主要看哪個說明內存比較大了
Redis常用數據類型
Redis最為常用的數據類型主要有以下五種:
String
Hash
List
Set
Sorted set
在具體描述這幾種數據類型之前,我們先通過一張圖了解下Redis內部內存管理中是如何描述這些不同數據類型的:
首先Redis內部使用一個redisObject對象來表示所有的key和value,redisObject最主要的信息如上圖所示:type代表一個value對象具體是何種數據類型,encoding是不同數據類型在redis內部的存儲方式,比如:type=string代表value存儲的是一個普通字元串,那麼對應的encoding可以是raw或者是int,如果是int則代表實際redis內部是按數值型類存儲和表示這個字元串的,當然前提是這個字元串本身可以用數值表示,比如:「123」 「456」這樣的字元串。
這里需要特殊說明一下vm欄位,只有打開了Redis的虛擬內存功能,此欄位才會真正的分配內存,該功能默認是關閉狀態的,該功能會在後面具體描述。通過上圖我們可以發現Redis使用redisObject來表示所有的key/value數據是比較浪費內存的,當然這些內存管理成本的付出主要也是為了給Redis不同數據類型提供一個統一的管理介面,實際作者也提供了多種方法幫助我們盡量節省內存使用,我們隨後會具體討論。
下面我們先來逐一的分析下這五種數據類型的使用和內部實現方式:
String
常用命令:
set,get,decr,incr,mget 等。
應用場景:
String是最常用的一種數據類型,普通的key/value存儲都可以歸為此類,這里就不所做解釋了。
實現方式:
String在redis內部存儲默認就是一個字元串,被redisObject所引用,當遇到incr,decr等操作時會轉成數值型進行計算,此時redisObject的encoding欄位為int。
Hash
常用命令:
hget,hset,hgetall 等。
應用場景:
我們簡單舉個實例來描述下Hash的應用場景,比如我們要存儲一個用戶信息對象數據,包含以下信息:
用戶ID為查找的key,存儲的value用戶對象包含姓名,年齡,生日等信息,如果用普通的key/value結構來存儲,主要有以下2種存儲方式:
常用內存優化手段與參數
通過我們上面的一些實現上的分析可以看出redis實際上的內存管理成本非常高,即佔用了過多的內存,作者對這點也非常清楚,所以提供了一系列的參數和手段來控制和節省內存,我們分別來討論下。
首先最重要的一點是不要開啟Redis的VM選項,即虛擬內存功能,這個本來是作為Redis存儲超出物理內存數據的一種數據在內存與磁碟換入換出的一個持久化策略,但是其內存管理成本也非常的高,並且我們後續會分析此種持久化策略並不成熟,所以要關閉VM功能,請檢查你的redis.conf文件中 vm-enabled 為 no。
其次最好設置下redis.conf中的maxmemory選項,該選項是告訴Redis當使用了多少物理內存後就開始拒絕後續的寫入請求,該參數能很好的保護好你的Redis不會因為使用了過多的物理內存而導致swap,最終嚴重影響性能甚至崩潰。
另外Redis為不同數據類型分別提供了一組參數來控制內存使用,我們在前面詳細分析過Redis Hash是value內部為一個HashMap,如果該Map的成員數比較少,則會採用類似一維線性的緊湊格式來存儲該Map, 即省去了大量指針的內存開銷,這個參數控制對應在redis.conf配置文件中下面2項:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
hash-max-zipmap-entries
含義是當value這個Map內部不超過多少個成員時會採用線性緊湊格式存儲,默認是64,即value內部有64個以下的成員就是使用線性緊湊存儲,超過該值自動轉成真正的HashMap。
hash-max-zipmap-value 含義是當 value這個Map內部的每個成員值長度不超過多少位元組就會採用線性緊湊存儲來節省空間。
以上2個條件任意一個條件超過設置值都會轉換成真正的HashMap,也就不會再節省內存了,那麼這個值是不是設置的越大越好呢,答案當然是否定的,HashMap的優勢就是查找和操作的時間復雜度都是O(1)的,而放棄Hash採用一維存儲則是O(n)的時間復雜度,如果
成員數量很少,則影響不大,否則會嚴重影響性能,所以要權衡好這個值的設置,總體上還是最根本的時間成本和空間成本上的權衡。
同樣類似的參數還有:
list-max-ziplist-entries 512
說明:list數據類型多少節點以下會採用去指針的緊湊存儲格式。
list-max-ziplist-value 64
說明:list數據類型節點值大小小於多少位元組會採用緊湊存儲格式。
set-max-intset-entries 512
說明:set數據類型內部數據如果全部是數值型,且包含多少節點以下會採用緊湊格式存儲。
最後想說的是Redis內部實現沒有對內存分配方面做過多的優化,在一定程度上會存在內存碎片,不過大多數情況下這個不會成為Redis的性能瓶頸,不過如果在Redis內部存儲的大部分數據是數值型的話,Redis內部採用了一個shared integer的方式來省去分配內存的開銷,即在系統啟動時先分配一個從1~n 那麼多個數值對象放在一個池子中,如果存儲的數據恰好是這個數值范圍內的數據,則直接從池子里取出該對象,並且通過引用計數的方式來共享,這樣在系統存儲了大量數值下,也能一定程度上節省內存並且提高性能,這個參數值n的設置需要修改源代碼中的一行宏定義REDIS_SHARED_INTEGERS,該值默認是10000,可以根據自己的需要進行修改,修改後重新編譯就可以了。
Redis的持久化機制
Redis由於支持非常豐富的內存數據結構類型,如何把這些復雜的內存組織方式持久化到磁碟上是一個難題,所以Redis的持久化方式與傳統資料庫的方式有比較多的差別,Redis一共支持四種持久化方式,分別是:
在設計思路上,前兩種是基於全部數據都在內存中,即小數據量下提供磁碟落地功能,而後兩種方式則是作者在嘗試存儲數據超過物理內存時,即大數據量的數據存儲,截止到本文,後兩種持久化方式仍然是在實驗階段,並且vm方式基本已經被作者放棄,所以實際能在生產環境用的只有前兩種,換句話說Redis目前還只能作為小數據量存儲(全部數據能夠載入在內存中),海量數據存儲方面並不是Redis所擅長的領域。下面分別介紹下這幾種持久化方式:
定時快照方式(snapshot):
該持久化方式實際是在Redis內部一個定時器事件,每隔固定時間去檢查當前數據發生的改變次數與時間是否滿足配置的持久化觸發的條件,如果滿足則通過操作系統fork調用來創建出一個子進程,這個子進程默認會與父進程共享相同的地址空間,這時就可以通過子進程來遍歷整個內存來進行存儲操作,而主進程則仍然可以提供服務,當有寫入時由操作系統按照內存頁(page)為單位來進行-on-write保證父子進程之間不會互相影響。
該持久化的主要缺點是定時快照只是代表一段時間內的內存映像,所以系統重啟會丟失上次快照與重啟之間所有的數據。
基於語句追加方式(aof):
aof方式實際類似mysql的基於語句的binlog方式,即每條會使Redis內存數據發生改變的命令都會追加到一個log文件中,也就是說這個log文件就是Redis的持久化數據。
aof的方式的主要缺點是追加log文件可能導致體積過大,當系統重啟恢復數據時如果是aof的方式則載入數據會非常慢,幾十G的數據可能需要幾小時才能載入完,當然這個耗時並不是因為磁碟文件讀取速度慢,而是由於讀取的所有命令都要在內存中執行一遍。另外由於每條命令都要寫log,所以使用aof的方式,Redis的讀寫性能也會有所下降。
虛擬內存方式:
虛擬內存方式是Redis來進行用戶空間的數據換入換出的一個策略,此種方式在實現的效果上比較差,主要問題是代碼復雜,重啟慢,復制慢等等,目前已經被作者放棄。
diskstore方式:
diskstore方式是作者放棄了虛擬內存方式後選擇的一種新的實現方式,也就是傳統的B-tree的方式,目前仍在實驗階段,後續是否可用我們可以拭目以待。
Redis持久化磁碟IO方式及其帶來的問題
有Redis線上運維經驗的人會發現Redis在物理內存使用比較多,但還沒有超過實際物理內存總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持久化的fork系統調用造成內存佔用加倍而導致的,這種觀點是不準確的,因為fork 調用的-on-write機制是基於操作系統頁這個單位的,也就是只有有寫入的臟頁會被復制,但是一般你的系統不會在短時間內所有的頁都發生了寫入而導致復制,那麼是什麼原因導致Redis崩潰的呢?
答案是Redis的持久化使用了Buffer IO造成的,所謂Buffer IO是指Redis對持久化文件的寫入和讀取操作都會使用物理內存的Page Cache,而大多數資料庫系統會使用Direct IO來繞過這層Page Cache並自行維護一個數據的Cache,而當Redis的持久化文件過大(尤其是快照文件),並對其進行讀寫時,磁碟文件中的數據都會被載入到物理內存中作為操作系統對該文件的一層Cache,而這層Cache的數據與Redis內存中管理的數據實際是重復存儲的,雖然內核在物理內存緊張時會做Page Cache的剔除工作,但內核很可能認為某塊Page Cache更重要,而讓你的進程開始Swap ,這時你的系統就會開始出現不穩定或者崩潰了。我們的經驗是當你的Redis物理內存使用超過內存總容量的3/5時就會開始比較危險了。
定時快照方式(snapshot)
基於語句追加文件的方式(aof)
虛擬內存(vm)
Diskstore方式
第一種方式將用戶ID作為查找key,把其他信息封裝成一個對象以序列化的方式存儲,這種方式的缺點是,增加了序列化/反序列化的開銷,並且在需要修改其中一項信息時,需要把整個對象取回,並且修改操作需要對並發進行保護,引入CAS等復雜問題。
第二種方法是這個用戶信息對象有多少成員就存成多少個key-value對兒,用用戶ID+對應屬性的名稱作為唯一標識來取得對應屬性的值,雖然省去了序列化開銷和並發問題,但是用戶ID為重復存儲,如果存在大量這樣的數據,內存浪費還是非常可觀的。
那麼Redis提供的Hash很好的解決了這個問題,Redis的Hash實際是內部存儲的Value為一個HashMap,並提供了直接存取這個Map成員的介面,如下圖:
也就是說,Key仍然是用戶ID, value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標簽) 就可以操作對應屬性數據了,既不需要重復存儲數據,也不會帶來序列化和並發修改控制的問題。很好的解決了問題。
這里同時需要注意,Redis提供了介面(hgetall)可以直接取到全部的屬性數據,但是如果內部Map的成員很多,那麼涉及到遍歷整個內部Map的操作,由於Redis單線程模型的緣故,這個遍歷操作可能會比較耗時,而另其它客戶端的請求完全不響應,這點需要格外注意。
實現方式:
上面已經說到Redis Hash對應Value內部實際就是一個HashMap,實際這里會有2種不同實現,這個Hash的成員比較少時Redis為了節省內存會採用類似一維數組的方式來緊湊存儲,而不會採用真正的HashMap結構,對應的value redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht。
List
常用命令:
lpush,rpush,lpop,rpop,lrange等。
應用場景:
Redis list的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現,比較好理解,這里不再重復。
實現方式:
Redis list的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。
Set
常用命令:
sadd,spop,smembers,sunion 等。
應用場景:
Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的。
實現方式:
set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。
Sorted set
常用命令:
zadd,zrange,zrem,zcard等
使用場景:
Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過用戶額外提供一個優先順序(score)的參數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重復的集合列表,那麼可以選擇sorted set數據結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。
實現方式:
Redis sorted set的內部使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,HashMap里放的是成員到score的映射,而跳躍表裡存放的是所有的成員,排序依據是HashMap里存的score,使用跳躍表的結構可以獲得比較高的查找效率,並且在實現上比較簡單。