引言:
如今redis憑借其高性能的優勢, 以及豐富的數據結構作為cache已越來越流行, 逐步取代了memcached等cache產品, 在推ter,新浪微博中廣泛使用,阿里巴巴同樣如此. redis已經占據了其不可動搖的地位, 然而在實際的生產環境中, redis也暴露出一些其他問題.如性能瓶頸, 內存冗余, 運維部署復雜等. 本文目的就是分析redis現有的問題, 以及介紹阿里巴巴技術保障團隊對redis的改造工作, 使其在生產環境中發揮更大的價值.
原生redis的瓶頸:
1. 單進程單線程, 無法充分發揮服務器多核cpu的性能.
2. 大流量下造成IO阻塞. 同樣是由于單進程單線程, cpu在處理業務邏輯的時候,網絡IO被阻塞住, 造成無法處理更多的請求.
3. 維護成本高, 如果想要充分發揮服務器的所有資源包括cpu, 網絡io等, 就必須建立多個instance, 但此時不可避免會增加維護成本. 拿24核服務器舉例來講, 如果部署24個單機版的instance,理論上可以實現10w*24core= 240wQPS的總體性能.但是每個 instance 有各自獨立的數據,占用資源如內存也會同比上升,反過來制約一臺服務器又未必能支持這么多的 instance. 如果部署24個Instance來構成單機集群, 雖然可以共享數據,但是因為節點增加, redis的狀態通訊更加頻繁和費時,性能也下會降很多. 并且兩種方式都意味著要維護24個Instance,運維成本都會成倍增加.
4. 持久化. redis提供了兩種save方式 1)save觸發. 2)bgsave. 當然也可以使用3)aof來實現持久化, 但是這3點都有弊端.
1)save: 由于是單進程單線程, redis會阻塞住所有請求, 來遍歷所有redisDB, 把key-val寫入dump.rdb. 如果內存數據量過大, 會造成短時間幾秒到幾十秒甚至更長的時間停止服務, 這種方案對于推ter, taobao等大流量的網站, 顯然是不可取的.
2)bgsave: 在觸發bgsave時, redis會fork自身, child進程會進入1)的處理方式,這意味著服務器內存要有一半的冗余才可以, 如今內存已變得越來越廉價, 但是對于存儲海量數據的情況,內存以及服務器的成本還是不容忽視的.
3)aof: 說到持久化, redis提供的aof算是最完美的方案了, 但是有得必有失, 嚴重影響性能! 因為redis每接收到一條請求, 就要把命令內容完整的寫到磁盤文件, 且不說頻繁讀寫會影響磁盤壽命,寫磁盤的時間足以拖垮redis整體性能 . 當然熟悉redis的開發者會想到用appendfsync等參數來調整, 但都不是完美.即使使用 SSD,性能也只是略有提升,并且性價比不高。
針對以上幾種情況, 阿里技術保障團隊做了如下優化手段, 其實這不僅僅只是優化, 而更是一種對redis的改造.
1. 多線程master + N*work 工作模式.master線程負責監聽網絡事件, 在接收到一個新的連接后, master會把新的fd注冊到worker的epoll事件中, 交由worker處理這個fd的所有讀寫事件, 這樣master線程就可以完全被釋放出來接收更多的連接, 同時又不妨礙worker處理業務邏輯和IO讀寫.
采用這種master + N*worker的網絡層事件模型,可以實現redis性能的平行擴展. 真正的讓redis在面臨高并發請求時可以叢容面對.
2. 拋棄save, bgsave, aof等三種模式.采用redisDB lock模式. AliRedis在數據存儲層把多DB存儲模式轉換成HashDb存儲, 將key hash到所有RedisDB上, 這樣做有一個弊端就是拋棄了select命令, 但與此同時會帶來一個更大的好處, 可以逐個DB持久化而不會影響整個系統, 在做持久化的時候AliRedis只需lock住1/N個redisDb, 占用1/m個線程. 在不需要內存冗余的情況下進行持久化, 相比之前提到的弊端, 這種方式可以帶來更大的收益, 更豐厚的回報.
3. 重構hiredis客戶端, 支持redis-cluster工作模式, 目前hiredis并不支持redis-cluster模式, 阿里技術保障團隊對hiredis進行重構,使之支持redis-cluster.
4. 優化jemalloc, 采用大內存頁. Redis在使用內存方面可謂苛刻至極, 壓縮, string轉number等, 能省就省, 但是在實際生產環境中, 為了追求性能, 對于內存的使用可以適度(不至于如bgsave般浪費)通融處理, 因此AliRedis對jemalloc做了微調, 通過調整pagesize來讓一次je_malloc分配更多run空間來儲備更多的用戶態可用內存, 同時可以減輕換頁表的負載, 降低user sys的切換頻率, 來提高申請內存的性能, 對jemalloc有興趣的開發者可以參考jemalloc源碼中的bin, run, chunk數據結構進行分析.
通過如上改造 , redis 可以充分發揮服務器多核的優勢 , 以及網絡 IO 復用 , 特別是節省運維成本 , 每臺服務器只需維護一個 AliRedis 實例 .

測試環境
CPU: Intel Xeon E5-2630 2.3GHz, *2
KERNEL: 3.2.0
GCC: 4.4.6
Jemalloc: 3.2.0
NIC: Intel 82599EB
測試數據
AliRedis單機版性能數據
thread: 1 2 4 8 12 16 20 24
set/get=1:1 83182 162214 301552 605817 876656 1173748 1551113 1800878
AliRedis集群
8個節點, 20臺客戶端, 配置相同, cpu全部打滿.
set/get=1:1 qps: 10,344,877
結論
單機版AliRedis可以實現24核跑滿180wQPS性能.
集群版可以實現8臺服務器支撐1000wQPS的數據請求.
阿里巴巴技術保障團隊肩負著支撐阿里技術, 保障系統穩定運行的艱巨使命.不管是雙11, 還是雙12, 或者其他大促活動, 每個阿里人都在努力且拼命的工作, 拿自己的勞動來捍衛著阿里集團的榮譽.
阿里技術-保障奇跡.
阿里技術保障部-系統運營-網絡部-子逍
來自:http://blog.sina.com.cn/s/blog_e59371cc0101br74.html