隨着應用對高性能需求的增長,NoSQL逐漸在各大名企的系統架構中生根發芽。這裏咱們將爲你們分享社交巨頭新浪微博帶來的Redis實踐,首先咱們看新浪微博 @啓盼cobain的Redis實戰經驗分享:html
Tape is Dead,Disk is Tape,Flash is Disk,RAM Locality is King. — Jim Gray面試
Redis不是比較成熟的 memcache 或者 Mysql 的替代品,是對於大型互聯網類應用在架構上很好的補充。如今有愈來愈多的應用也在紛紛基於Redis作架構的改造。首先簡單公佈一下Redis平臺實際狀況:redis
- 2200+億 commands/day 5000億Read/day 500億Write/day
- 18TB+ Memory
- 500+ Servers in 6 IDC 2000+instances
應該是國內外比較大的Redis使用平臺,今天主要從應用角度談談 Redis服務 平臺。sql
Redis使用場景
1.Counting(計數)數據庫
計數的應用在另一篇文章裏較詳細的描述,計數場景的優化後端
http://www.xdata.me/?p=262緩存
這裏就很少加描述了。服務器
能夠預見的是,有不少同窗認爲把計數所有存在內存中成本很是高,我在這裏用個圖表來表達下個人觀點:網絡

不少狀況你們都會設想純使用內存的方案會頗有很高成本,但實際狀況每每會有一些不同:數據結構
- COST,對於有必定吞吐需求的應用來講,確定會單獨申請DB、Cache資源,不少擔憂DB寫入性能的同窗還會主動將DB更新記入異步隊列,而這三塊的資源的利用率通常都不會過高。資源算下來,你驚異的發現:反而純內存的方案會更精簡!
- KISS原則,這對於開發是很是友好的,我只須要創建一套鏈接池,不用擔憂數據一致性的維護,不用維護異步隊列。
- Cache穿透風險,若是後端使用DB,確定不會提供很高的吞吐能力,cache宕機若是沒有妥善處理,那就悲劇了。
- 大多數的起始存儲需求,容量較小。
2.Reverse cache(反向cache)
面對微博經常出現的熱點,如最近出現了較爲火爆的短鏈,短期有數以萬計的人點擊、跳轉,而這裏會經常涌現一些需求,好比咱們向快速在跳轉時斷定用戶等級,是否有一些帳號綁定,性別愛好什麼的,已給其展現不一樣的內容或者信息。
普通採用memcache+Mysql的解決方案,當調用id合法的狀況下,可支撐較大的吞吐。但當調用id不可控,有較多垃圾用戶調用時,因爲memcache未有命中,會大量的穿透至Mysql服務器,瞬間形成鏈接數瘋長,總體吞吐量下降,響應時間變慢。
這裏咱們能夠用redis記錄全量的用戶斷定信息,如string key:uid int:type,作一次反向的cache,當用戶在redis快速獲取本身等級等信息後,再去Mc+Mysql層去獲取全量信息。如圖:

固然這也不是最優化的場景,如用Redis作bloomfilter,可能更加省用內存。
3.Top 10 list
產品運營總會讓你展現最近、最熱、點擊率最高、活躍度最高等等條件的top list。不少更新較頻繁的列表若是使用MC+MySQL維護的話緩存失效的可能性會比較大,鑑於佔用內存較小的狀況,使用Redis作存儲也是至關不錯的。
4.Last Index
用戶最近訪問記錄也是redis list的很好應用場景,lpush lpop自動過時老的登錄記錄,對於開發來講仍是很是友好的。
5.Relation List/Message Queue
這裏把兩個功能放在最後,由於這兩個功能在現實問題當中遇到了一些困難,但在必定階段也確實解決了咱們不少的問題,故在這裏只作說明。
Message Queue就是經過list的lpop及lpush接口進行隊列的寫入和消費,因爲自己性能較好也能解決大部分問題。
6.Fast transaction with Lua
Redis 的Lua的功能擴展實際給Redis帶來了更多的應用場景,你能夠編寫若干command組合做爲一個小型的非阻塞事務或者更新邏輯,如:在收到message推送時,同時1.給本身的增長一個未讀的對話 2.給本身的私信增長一個未讀消息 3.最後給發送人回執一個完成推送消息,這一層邏輯徹底能夠在Redis Server端實現。
可是,須要注意的是Redis會將lua script的所有內容記錄在aof和傳送給slave,這也將是對磁盤,網卡一個不小的開銷。
7.Instead of Memcache
- 不少測試和應用均已證實,
- 在性能方面Redis並無落後memcache多少,而單線程的模型給Redis反而帶來了很強的擴展性。
- 在不少場景下,Redis對同一份數據的內存開銷是小於memcache的slab分配的。
- Redis提供的數據同步功能,實際上是對cache的一個強有力功能擴展。
Redis使用的重要點
1.rdb/aof Backup!
咱們線上的Redis 95%以上是承擔後端存儲功能的,咱們不只用做cache,而更爲一種k-v存儲,他徹底替代了後端的存儲服務(MySQL),故其數據是很是重要的,若是出現數據污染和丟失,誤操做等狀況,將是難以恢復的。因此備份是很是必要的!爲此,咱們有共享的hdfs資源做爲咱們的備份池,但願能隨時能夠還原業務所需數據。
2.Small item & Small instance!
因爲Redis單線程(嚴格意義上不是單線程,但認爲對request的處理是單線程的)的模型,大的數據結構list,sorted set,hash set的批量處理就意味着其餘請求的等待,故使用Redis的複雜數據結構必定要控制其單key-struct的大小。
另外,Redis單實例的內存容量也應該有嚴格的限制。單實例內存容量較大後,直接帶來的問題就是故障恢復或者Rebuild從庫的時候時間較長,而更糟糕的是,Redis rewrite aof和save rdb時,將會帶來很是大且長的系統壓力,並佔用額外內存,極可能致使系統內存不足等嚴重影響性能的線上故障。咱們線上96G/128G內存服務器不建議單實例容量大於20/30G。
3.Been Available!
業界資料和使用比較多的是Redis sentinel(哨兵)
2000行C實現了服務器狀態檢測,自動故障轉移等功能。
但因爲自身實際架構每每會複雜,或者考慮的角度比較多,爲此 @許琦eryk和我一同作了hypnos項目。
hypnos是神話中的睡神,字面意思也是但願咱們工程師無需在休息時間處理任何故障。:-)
其工做原理示意以下:

Talk is cheap, show me your code! 稍後將單獨寫篇博客細緻講下Hypnos的實現。
4.In Memory or not?
發現一種狀況,開發在溝通後端資源設計的時候,經常由於習慣使用和錯誤瞭解產品定位等緣由,而忽視了對真實使用用戶的評估。也許這是一份歷史數據,只有最近一天的數據纔有人進行訪問,而把歷史數據的容量和最近一天請求量都拋給內存類的存儲現實是很是不合理的。
因此當你在究竟使用什麼樣的數據結構存儲的時候,請務必先進行成本衡量,有多少數據是須要存儲在內存中的?有多少數據是對用戶真正有意義的。由於這其實對後端資源的設計是相當重要的,1G的數據容量和1T的數據容量對於設計思路是徹底不同的
Plans in future?
1.slave sync改造
所有改造線上master-slave數據同步機制,這一點咱們借鑑了MySQL Replication的思路,使用rdb+aof+pos做爲數據同步的依據,這裏簡要說明爲何官方提供的psync沒有很好的知足咱們的需求:
假設A有兩個從庫B及C,及 A `— B&C,這時咱們發現master A服務器有宕機隱患須要重啓或者A節點直接宕機,須要切換B爲新的主庫,若是A、B、C不共享rdb及aof信息,C在做爲B的從庫時,仍會清除自身數據,由於C節點只記錄了和A節點的同步情況。
故咱們須要有一種將A`–B&C 結構切換切換爲A`–B`–C結構的同步機制,psync雖然支持斷點續傳,但仍沒法支持master故障的平滑切換。
實際上咱們已經在咱們定製的Redis計數服務上使用瞭如上功能的同步,效果很是好,解決了運維負擔,但仍需向全部Redis服務推廣,若是可能咱們也會向官方Redis提出相關sync slave的改進。
2.更適合redis的name-system Or proxy
細心的同窗發現咱們除了使用DNS做爲命名系統,也在zookeeper中有一份記錄,爲何不讓用戶直接訪問一個系統,zk或者DNS選擇其一呢?
其實仍是很簡單,命名系統是個很是重要的組件,而dns是一套比較完善的命名系統,咱們爲此作了不少改進和試錯,zk的實現仍是相對複雜,咱們尚未較強的把控粒度。咱們也在思考用什麼作命名系統更符合咱們需求。
3.後端數據存儲
大內存的使用確定是一個重要的成本優化方向,flash盤及分佈式的存儲也在咱們將來計劃之中。(原文連接: Largest Redis Clusters Ever)
2.Pinterest:Reids維護上百億的相關性
Pinterest已經成爲硅谷最瘋故事之一,在2012年,他們基於PC的業務增長1047%,移動端採用增長1698%, 該年3月其獨立訪問數量更飆升至533億。在Pinterest,人們關注的事物以百億記——每一個用戶界面都會查詢某個board或者是用戶是否關注的行爲促成了異常複雜的工程問題。這也讓Redis得到了用武之地。通過數年的發展,Pinterest已經成爲媒體、社交等多個領域的佼佼者,其輝煌戰績以下:
- 得到的推薦流量高於Google+、YouTube及LinkedIn三者的總和
- 與Facebook及Twitter一塊兒成爲最流行的三大社交網絡
- 參考Pinterest進行購買的用戶比其它網站更高
如您所想,基於其獨立訪問數,Pinterest的高規模促成了一個很是高的IT基礎設施需求。

經過緩存來優化用戶體驗
近日,Pinterest工程經理Abhi Khune對其公司的用戶體驗需求及Redis的使用經驗 進行了分享。即便是滋生的應用程序打造者,在分析網站的細節以前也不會理解這些特性,所以先大體的理解一下使用場景:首先,爲每一個粉絲進行說起到的預檢查;其次,UI將準確的顯示用戶的粉絲及關注列表分頁。高效的執行這些操做,每次點擊都須要很是高的性能架構。
不能免俗,Pinterest的軟件工程師及架構師已經使用了MySQL及memcache,可是緩存解決方案仍然達到了他們的瓶頸;所以爲了擁有更好的用戶體驗,緩存必須被擴充。而在實際操做過程當中,工程團隊已然發現緩存只有當用戶sub-graph已經在緩存中時纔會起到做用。所以。任何使用這個系統的人都須要被緩存,這就致使了整個圖的緩存。同時,最多見的查詢「用戶A是否關注了用戶B」的da案常常是否認的,然而這卻被做爲了緩存丟失,從而促成一個數據庫查詢,所以他們須要一個新的方法來擴展緩存。最終,他們團隊決定使用Redis來存儲整個圖,用以服務衆多的列表。
使用Redis存儲大量的Pinterest列表
Pinterest使用了Redis做爲解決方案,並將性能推至了內存數據庫等級,爲用戶保存多種類型列表:
- 關注者列表
- 你所關注的board列表
- 粉絲列表
- 關注你board的用戶列表
- 某個用戶中board中你沒有關注的列表
- 每一個board的關注者及非關注者
Redis爲其7000萬用戶存儲了以上的全部列表,本質上講能夠說是儲存了全部粉絲圖,經過用戶ID分片。鑑於你能夠經過類型來查看以上列表的數據,分析概要信息被用看起來更像事務的系統儲存及訪問。Pinterest當下的用戶like被限制爲10萬,初略進行統計:若是每一個用戶關注25個board,將會在用戶及board間產生17.5億的關係。同時更加劇要的是,這些關係隨着系統的使用天天都會增長。
Pinterest的Reids架構及運營
經過Pinterest的一個創始人瞭解到,Pinterest開始使用Python及訂製的Django編寫應用程序,並一直持續到其擁有1800萬用戶級日410TB用戶數據的時候。雖然使用了多個存儲對數據進行儲存,工程師根據用戶id使用了8192個虛擬分片,每一個分片都運行在一個Redis DB之上,同時1個Redis實例將運行多個Redis DB。爲了對CPU核心的充分使用,同一臺主機上同時使用多線程和單線程Redis實例。
鑑於整個數據集運行在內存當中,Redis在Amazon EBS上對每秒傳輸進來的寫入都會進行持久化。擴展主要經過兩個方面進行:第一,保持50%的利用率,經過主從轉換,機器上運行的Redis實例一半會轉譯到一個新機器上;第二,擴展節點和分片。整個Redis集羣都會使用一個主從配置,從部分將被當作一個熱備份。一旦主節點失敗,從部分會馬上完成主的轉換,同時一個新的從部分將會被添加,ZooKeeper將完成整個過程。同時他們每一個小時都會在Amazon S3上運行BGsave作更持久的儲存——這項Reids操做會在後端進行,以後Pinterest會使用這些數據作MapReduce和分析做業。
原文連接: http://www.cnblogs.com/tuyile006/p/14125030.html
若是以爲本文對你有幫助,能夠關注一下我公衆號,回覆關鍵字【面試】便可獲得一份Java核心知識點整理與一份面試大禮包!另有更多技術乾貨文章以及相關資料共享,你們一塊兒學習進步!