導讀 | 目前在惟品會主要負責redis/hbase的運維和開發支持工做,也參與工具開發工做,本文是在Redis中國用戶組給你們分享redis cluster的生產實踐。 |
分享大綱html
本次分享內容以下:node
一、生產應用場景linux
二、存儲架構演變git
三、應用最佳實踐github
四、運維經驗總結redis
關於這4部分的內容介紹:sql
第一、2部分:介紹redis cluster在惟品會的生產應用場景,以及存儲架構的演變。後端
第3部分:redis cluster的穩定性,應用成熟度,踩到過那些坑,如何解決這些問題?這部分是你們比較關係的內容。緩存
第4部分:簡單介紹大規模運營的一些經驗,包括部署、監控、管理以及redis工具開發。安全
生產應用場景
業務範圍
redis cluster在惟品會主要應用於後端業務,用做內存存儲服務。主要大數據實時推薦/ETL、風控、營銷三大業使用。
cluster用於取代當前twemproxy三層架構,做爲通用的存儲架構。redis cluster能夠大幅度簡化咱們的存儲架構,也解決twemproxy架構沒法在線擴容節點的問題。
目前咱們在線有生產幾十個cluster集羣,約2千個instances,單個集羣最大達到250+instances。
這是咱們的生產應用場景,主要是後端業務的存儲,目前沒有做爲cache使用的場景。
大數據、風控、營銷系統的特徵
cluster 通常數據量大, 單個cluster集羣在幾十個GB到上TB級別內存存儲量。
做爲後端應用的存儲,數據來源主要如下三種方式:
Kafka → Redis Cluster,Storm/Spark實時 Hive → Redis Cluster, MapReduce程序 MySQL → Redis Cluster,Java/C++程序。
數據由離線/實時job生成, 讀寫請求量大, 對讀寫性能也要求高。
業務高峯期請求量急劇上升,幾倍的讀寫量增長,須要多個redis實例承擔業務的讀寫壓力。
業務需求變化快, schema變化頻繁。若是使用MySQL做爲存儲,那麼將會是頻繁的DLL變動,並且須要作online schema change。
大促銷活動時擴容頻繁。
爲何選擇redis cluster
1) cluster適合咱們後端生產應用場景
在線水平擴展能力,可以解決咱們大量的擴容需求。 Failover能力和高可用性。 雖然cluster不保證主從數據強一致性,可是後端業務可以容忍failover後少許的數據丟失。
2) 架構簡單
無中心架構,各個節點度等。slave節點提供數據冗餘,master節點異常時提高爲master。 取代twemproxy三層架構,系統複雜性下降。 能夠節約大量的硬件資源,咱們的Lvs + Twemproxy層 使用了近上千臺物理機器。 少了lvs和twemproxy層,讀寫性能提高明顯。響應時間從100-200us減小到50-100us。 系統瓶頸更少。lvs層網卡和pps吞吐量瓶頸;對於請求長度較大的業務,twemproxy單節點性能低。
總結下,咱們選擇redis cluster主要這兩點緣由:簡單、擴展性。另外,咱們用cluster取代twemproxy集羣,三層架構實在是很使人頭疼,複雜、瓶頸多、管理不方面。
存儲架構演變
架構演變
在2014年7月,爲了準備當時的814撒嬌節大促銷活動,咱們把單個redis的服務遷移到twemproxy上。twemproxy在後端快速完成數據分片和擴容。爲了不再次擴容,咱們靜態分配足夠多的資源。
以後,twemproxy暴露出來的系統瓶頸不少,資源使用不少,也存在必定的浪費。咱們決定用redis cluster取代這種複雜的三層架構。
redis cluster GA以後,咱們就開始上線使用。最初是3.0.2 版本,後面大量使用3.0.3 ,上個月開始使用3.0.7版本。
下面簡單對比下兩種架構,解析下他們的優缺點。
Twemproxy架構
1)優勢 sharding邏輯對開發透明,讀寫方式和單個redis一致。 能夠做爲cache和storage的proxy(by auto-eject)。 2)缺點 架構複雜,層次多。包括lvs、twemproxy、redis、sentinel和其控制層程序。 管理成本和硬件成本很高。 2 * 1Gbps 網卡的lvs機器,最大能支撐140萬pps。 流量高的系統,proxy節點數和redis個數接近。 Redis層仍然擴容能力差,預分配足夠的redis存儲節點。
這是twemproxy的架構,客戶端直接鏈接最上面的lvs(LB),第二層是同構的twemproxy節點,下面的redis master節點以及熱備的slave節點,另外還有獨立的sentinel集羣和切換控制程序,twemproxy先介紹到這裏。
Redis Cluster架構
1)優勢
無中心架構。 數據按照slot存儲分佈在多個redis實例上。 增長slave作standby數據副本,用於failover,使集羣快速恢復。 實現故障auto failover。節點之間經過gossip協議交換狀態信息;投票機制完成slave到master角色的提高。 亦可manual failover,爲升級和遷移提供可操做方案。 下降硬件成本和運維成本,提升系統的擴展性和可用性。
2)缺點
client實現複雜,驅動要求實現smart client,緩存slots mapping信息並及時更新。 目前僅JedisCluster相對成熟,異常處理部分還不完善,好比常見的「max redirect exception」。 客戶端的不成熟,影響應用的穩定性,提升開發難度。 節點會由於某些緣由發生阻塞(阻塞時間大於clutser-node-timeout),被判斷下線。這種failover是沒有必要,sentinel也存在這種切換場景。
架構演變講完了,開始講第三部分,也是你們最感興趣的一部分.
應用最佳實踐
存在哪些坑? develop guideline & best practice
穩定性
不擴容時集羣很是穩定。
擴容resharding時候,早期版本的Jedis端有時會出現「max-redirect」異常。
分析Jedis源碼,請求重試次數達到了上限,仍然沒有請求成功。兩方面分析:redis鏈接不上?仍是集羣節點信息不一致?
存活檢測機制缺陷
redis 存活檢測機制可能由於master 節點上慢查詢、阻塞式命令、或者其它的性能問題致使長時間沒有響應,這個節點會認爲處於failed狀態,並進行切換。這種切換是不必的。
優化策略
a) 默認的cluster-node-timeout爲15s,能夠適當增大; b) 避免使用會引發長時間阻塞的命令,好比save/flushdb等阻塞操做,或者keys pattern 這種慢查詢。
整體來講,redis cluster已經很是穩定了,可是要注意一些應用中的小問題,下面是5個坑,你們注意了.
有哪些坑?
遷移過程當中Jedis「Max Redirect」異常
github上討論的結果是程序retry。 max redirt issues: https://github.com/xetorthio/jedis/issues/1238 retry時間應該大於failover 時間。 Jedis參數優化調整:增大jedis中的‘DEFAULT_MAX_REDIRECTIONS’參數,默認值是5. 避免使用multi-keys操做,好比mset/mget. multi-key操做有些客戶端沒有支持實現。
長時間阻塞引發的沒必要要的failover
阻塞的命令。好比save/flushall/flushdb 慢查詢。keys *、大key的操做、O(N)操做 rename危險操做: rename-command FLUSHDB REDIS_FLUSHDB rename-command FLUSHALL REDIS_FLUSHALL rename-command KEYS REDIS_KEYS
同時支持ipv4和ipv6偵聽服務埋下的坑
具體現象:redis啓動正常,節點的協議端口只有ipv6 socket建立正常。異常節點也沒法加入到集羣中,也沒法獲取epoch。
解決方法:啓動時指定網卡ipv4地址,也能夠是0.0.0.0,配置文件中添加:bind 0.0.0.0
這個是在setup集羣的時候發生過的一個問題,bind 0.0.0.0雖然存在一些安全性問題,可是是比較簡單通用的解決方法。
數據遷移速度較慢
主要使用的redis-trib.rb reshard來完成數據遷移。 redis-3.0.6版本之前migrate操做是單個key逐一操做。從redis-3.0.6開始,支持單次遷移多個key。 redis集羣內部最多隻容許一個slot處於遷移狀態,不能併發的遷移slots。 redis-trib.rb reshard若是執行中斷,用redis-trib.rb fix修復集羣狀態。
版本選擇/升級建議
咱們已經開始使用3.0.7版本,不少3.2.0修復的bug已經backport到這個版本。 另外咱們也開始測試3.2.0版本,內存空間優化很大。 Tips redis-trib.rb支持resharding/rebalance,分配權重。 redis-trib.rb支持從單個redis遷移數據到cluster集羣中。 後面2點不算坑把,算是不足,tips也很實用。開始分享下最佳實踐。
最佳實踐
3.1 應用作好容錯機制 鏈接或者請求異常,進行鏈接retry和reconnect。 重試時間應該大於cluster-node-time時間 仍是強調容錯,這個不是針對cluster,全部的應用設計都適用。 3.2 制定開發規範 慢查詢,進程cpu 100%、客戶端請求變慢,甚至超時。 避免產生hot-key,致使節點成爲系統的短板。 避免產生big-key,致使網卡打爆、慢查詢。 TTL, 設置合理的ttl,釋放內存。避免大量key在同一時間段過時,雖然redis已經作了不少優化,仍然會致使請求變慢。 key命名規則。 避免使用阻塞操做,不建議使用事務。 開發規範,使大家的開發按照最優的方式使用nosql。 3.3 優化鏈接池使用 主要避免server端維持大量的鏈接。 合理的鏈接池大小。 合理的心跳檢測時間。 快速釋放使用完的鏈接。 Jedis一個鏈接建立異常問題(fixed): https://github.com/xetorthio/jedis/issues/1252 鏈接問題是redis開發使用中最多見的問題,connection timeout/read timeout,還有borrow connection的問題。 3.4 區分redis/twemproxy和cluster的使用 redis建議使用pipeline和multi-keys操做,減小RTT次數,提升請求效率。 twemproxy也支持pipeline, 支持部分的multi-key能夠操做。 redis cluster不建議使用pipeline和multi-keys操做,減小max redirect產生的場景。 區分redis 和 cluster的使用,一方面是數據分片引發的;另外一方面,與client的實現支持相關。 3.5 幾個須要調整的參數 1)設置系統參數vm.overcommit_memory=1,能夠避免bgsave/aofrewrite失敗。 2)設置timeout值大於0,可使redis主動釋放空閒鏈接。 3)設置repl-backlog-size 64mb。默認值是1M,當寫入量很大時,backlog溢出會致使增量複製不成功。 4)client buffer參數調整 client-output-buffer-limit normal 256mb 128mb 60 client-output-buffer-limit slave 512mb 256mb 180
運維經驗總結
4.1 自動化管理
CMDB管理全部的資源信息。 Agent方式上報硬軟件信息。 標準化基礎設置。機型、OS內核參數、軟件版本。 Puppet管理和下發標準化的配置文件、公用的任務計劃、軟件包、運維工具。 資源申請自助服務。
4.2 自動化監控
zabbix做爲主要的監控數據收集工具。 開發實時性能dashboard,對開發提供查詢。 單機部署多個redis,藉助於zabbix discovery。 開發DB響應時間監控工具Titan。 基本思想來源於pt-query-degest,經過分析tcp應答報文產生日誌。flume agent + kafka收集,spark實時計算,hbase做爲存儲。最終獲得hotquery/slowquery,request source等性能數據。
4.3 自動化運維
資源申請自助服務化。 若是申請合理,一鍵便可完成cluster集羣部署。 能不動手的,就堅定不動手,另外,監控數據對開發開發很重要,讓他們瞭解本身服務性能,有時候開發會更早發現集羣的一些異常行爲,好比數據不過時這種問題,運維就講這麼多了,後面是乾貨中的乾貨,由deep同窗開發的幾個實用工具。
redis開源工具介紹
1) redis實時數據遷移工具
1)在線實時遷移 2)redis/twemproxy/cluster 異構集羣之間相互遷移。 3)github: https://github.com/vipshop/redis-migrate-tool
2) redis cluster管理工具
1)批量更改集羣參數 2)clusterrebalance 3)不少功能,具體看github : https://github.com/deep011/redis-cluster-tool
3) 多線程版本Twemproxy
1)大幅度提高單個proxy的吞吐量,線程數可配置。 2)壓測狀況下,20線程達到50w+qps,最優6線程達到29w。 3)徹底兼容twemproxy。 4)github: https://github.com/vipshop/twemproxies
4) 在開發的中的多線redis
1)Github: https://github.com/vipshop/vire 2)歡迎一塊兒參與協做開發,這是咱們在開發中的項目,但願你們可以提出好的意見。
互動環節(陳羣和申政解答)
問題1:版本更新,對數據有沒有影響? 答:咱們重啓升級從2.8.17到3.0.3/3.0.7沒有任何的異常。3.0到3.2咱們目前尚未實際升級操做過。 問題2:請問下sentinel模式下有什麼好的讀寫分離的方法嗎 答:咱們沒有讀寫分離的使用,讀寫都在maste;集羣太多,管理複雜;此外,咱們也作了分片,沒有作讀寫分離的必要;且咱們幾乎是一主一從節點配置 問題3:redis的fork主要是爲了rdb吧,去掉是爲了什麼呢 答:fork不友好 問題4:若是不用fork,是怎麼保證rdb快照是精確的,有其餘cow機制麼 答:能夠經過其餘方法,這個還在探究階段,但目標是不用fork 問題5:就是redis cluster模式下批量操做會有不少問題,但是不批量操做又會下降業務系統的性能 答:確實存在這方面的問題,這方面支持須要客戶端的支持,可是jedis的做者也不大願意支持pipeline或者一些multi key操做。若是是大批量的操做,能夠用多線程提升客戶端的吞吐量。
原文來自: https://www.linuxprobe.com/redis-application-confucianism.html