Redis 架構和運維必懂的10個知識
- 2019 年 11 月 5 日
- 筆記
Redis 是一個開源的使用 ANSI C 語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value 資料庫,並提供多種語言的 API。
如今,互聯網業務的數據正以更快的速度在增長,數據類型越來越豐富,這對數據處理的速度和能力提出了更高要求。Redis 是一種開源的記憶體非關係型資料庫,給開發人員帶來的體驗是顛覆性的。在自始至終的設計過程中,都充分考慮高性能,這使得 Redis 成為當今速度最快的 NoSQL 資料庫。
考慮高性能的同時,高可用也是很重要的考慮因素。互聯網 7×24 無間斷服務,在故障期間以最快的速度 Failover,能給企業帶來最小的損失。
那麼,在實際應用中,都有哪些高可用架構呢?架構之間有何優劣?我們應該怎麼取捨?有哪些最佳實踐?以下四個方面十個具有典型性和普遍性問題的解答,可以作為了解 Redis 高可用及 Redis 運維的參考。
一、高可用相關
1:Redis 常用高可用架構有哪些?
Redis 高可用架構如下:
- Redis Sentinel 集群 + 內網 DNS + 自定義腳本
- Redis Sentinel 集群 + VIP + 自定義腳本
- 封裝客戶端直連 Redis Sentinel 埠
- JedisSentinelPool,適合 Java
- PHP 基於 phpredis 自行封裝
- Redis Sentinel 集群 + Keepalived/Haproxy
- Redis M/S + Keepalived
- Redis Cluster
- Twemproxy
- Codis
2:Redis 高可用架構優劣對比?
—Redis Sentinel 集群 + 內網 DNS + 自定義腳本
優點:
- 秒級切換
- 腳本自定義,架構可控
- 對應用透明
缺點:
- 維護成本略高
- 依賴 DNS,存在解析延時
- Sentinel 模式存在短時間的服務不可用
—Redis Sentinel 集群 + VIP + 自定義腳本
優點:
- 秒級切換
- 腳本自定義,架構可控
- 對應用透明
缺點:
- 維護成本略高
- Sentinel 模式存在短時間的服務不可用
—封裝客戶端直連 Redis Sentinel 埠
優點:
- 服務探測故障及時
- DBA 維護成本低
缺點:
- 依賴客戶端支援 Sentinel
- Sentinel 伺服器需要開放訪問許可權
- 對應用有侵入性
—Redis Sentinel 集群 + Keepalived/Haproxy
優點:
- 秒級切換
- 對應用透明
缺點:
- 維護成本高
- 存在腦裂
- Sentinel 模式存在短時間的服務不可用
—Redis M/S +Keepalived
優點:
- 秒級切換
- 對應用透明
- 部署簡單,維護成本低
缺點:
- 需要腳本實現切換功能
- 存在腦裂
(Redis Cluster、Twemproxy、Codis 優劣對比見下個問題)
3:常見的 Redis 集群方案有哪些優缺點?
Twemproxy:

多個同構 Twemproxy(配置相同)同時工作,接受客戶端的請求,根據 hash 演算法,轉發給對應的 Redis。
優點:
- 開發簡單,對應用幾乎透明
- 歷史悠久,方案成熟
缺點:
- 代理影響性能
- LVS 和 Twemproxy 會有節點性能瓶頸
- Redis 擴容非常麻煩
- Twitter 內部已放棄使用該方案,新使用的架構未開源
Codis:

- ZooKeeper
- 存放路由表和代理節點元數據
- 分發Codis-Config的命令
- Codis-Config 集成管理工具,有web介面
- Codis-Proxy
- 無狀態代理,兼容Redis協議
- 對業務透明
- Codis-Redis
- 基於2.8版本,二次開發
- 加入slot支援和遷移命令
優點:
- 開發簡單,對應用幾乎透明
- 性能比 Twemproxy 好
- 有圖形化介面,擴容容易,運維方便
缺點:
- 代理依舊影響性能
- 組件過多,需要很多機器資源
- 修改了 Redis 程式碼,導致和官方無法同步,新特性跟進緩慢
- 開發團隊準備主推基於 Redis 改造的 reborndb
Redis Cluster:

P2P模式,無中心化。把 key 分成 16384 個 slot,每個實例負責一部分 slot。客戶端請求若不在連接的實例,該實例會轉發給對應的實例。通過Gossip協議同步節點資訊。
優點:
- 組件 all-in-box,部署簡單,節約機器資源
- 性能比 proxy 模式好
- 自動故障轉移、Slot 遷移中數據可用
- 官方原生集群方案,更新與支援有保障
缺點:
- 架構比較新,最佳實踐較少
- 多鍵操作支援有限(驅動可以曲線救國)
- 為了性能提升,客戶端需要快取路由表資訊
- 節點發現、reshard 操作不夠自動化
二、Redis 通用
1:Redis 相對 MySQL、PostgreSQL 這些關係型資料庫,有什麼優缺點?
觀點一:
Redis 主要是用來做快取,它有持久化,但也只是為了快取的可靠而已。優點是數據全放記憶體,速度快。缺點就是,數據大小不能超過記憶體大小。兩個用在不同業務場景,Redis 無法取代傳統關係型資料庫。
觀點二:
Redis 首先它是一種記憶體資料庫,最大的優勢在於效率高。尤其在某些特定場合下,例如熱點數據量非常大,而數據從記憶體和磁碟之間的換入換出代價比較高的情況下,Redis 就會體現它的價值。
傳統關係型資料庫在於它對數據的一致性保障,它的數據模型範式是遵循嚴格事務規則的結構化數據,由於其數據的高度抽象化,它調度到記憶體的數據一般場合下不會佔用很大的記憶體空間。
總的來說,兩種資料庫各有各的優點和缺點。不同的業務場合有特定的追求目標,redis 首要的是效率,適用的是一些單純二維結構化數據無法表達的數據模型,而關係型資料庫處理的是可以用範式模型表達的二維數據,追求的是數據的高度一致性。隨著 IT 的發展,每一類型的資料庫都會在其特定的場合內發揮出無可比擬的優勢,最終的趨勢是大家趨於平衡,沒有最好,只有最適合。
觀點三:
記住一句話:任何資料庫都有自己的應用場景,應該關注數據流、數據屬性。
個人的經驗來說,Redis 不可能取代 MySQL 或者 PG。
2:Redis 有哪些應用場景,是否可以舉例說明下哪個公司用了?
Redis 是一個高性能的快取,一般應用在 Session 快取、隊列、排行榜、計數器、最近最熱文章、最近最熱評論、發布訂閱等。
更多應用場景,可以參考此處。
可以這樣講,Redis 適用於 數據實時性要求高、數據存儲有過期和淘汰特徵的、不需要持久化或者只需要保證弱一致性、邏輯簡單的場景。
中國的互聯網公司,據我了解,基本是都在用,其中新浪對 Redis 在中國普及起了重要的作用。
另外,Redis 官網有「Who's using Redis?」的鏈接。
3:新接手一個複雜的 Redis 集群(Sentinel 模式),如何了解它
剛剛接手一套 Redis 集群,想要了解這套集群的相關配置。應該如何入手。難道只能通過 info 命令去查看各個配置嗎?
這是筆者的建議:
- 通讀 Sentinel 官方文檔:https://redis.io/topics/sentinel
- Google 搜索 Redis Sentinel,找幾篇中英文的文章看看
- 進入 Sentinel 集群後,使用 info 查看集群資訊
- 查看 Sentinel 配置文件,配合文檔搞清楚每個參數的含義
- 使用幾台虛擬機模擬線上環境,然後做測試,在實踐中深入理解
- 思考當前 Sentinel 集群是否有不合理的地方,如有,提出並改進
三、Redis 故障排查
1:Redis 實例中,存在大量的 FIN_WAIT2 連接
客戶端 TCP 狀態遷移:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
伺服器 TCP 狀態遷移:
CLOSED->LISTEN->SYN 收到 ->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
這個狀態存在於主動發起斷開請求的一端,如果伺服器存在大量的這個狀態,那麼這個伺服器就充當客戶端的角色,如網路爬蟲,出現的原因是由於客戶端發起 FIN 請求結束連接之後,收到了服務端的應答之後進入 FIN_WAIT2,之後就沒收到服務端發送的 FIN 訊號導致。
PS:線上 Web 客戶端用的什麼語言?
此問題的評論值得一看:http://www.aixchina.net/Question/231035-1406575
2:如何知道,當前 Redis 實例是處於阻塞狀態?
請問大神們, 通過什麼方式,能夠知道,當前某個 Redis 實例是處於阻塞狀態啊? 能不能通過某個命令查詢出來 ? 求解, 謝謝!
解答一:
隨便 get 一個 key,然後卡著不動就行,簡單粗暴。優雅一點是看 latency 的延遲,blocked_clients 的數量,rejected_connections 的數量等。
解答二:
- 方法一:登錄 Redis,執行 info,查看 blocked_clients
- 方法二:執行 redis-cli –latency -h -p 查看延時情況
3:Redis 運維的故障有哪些?
回答一:
常見的運維故障
- 使用 keys * 把庫堵死,——建議使用別名把這個命令改名
- 超過記憶體使用後,部分數據被刪除——這個有刪除策略的,選擇適合自己的即可
- 沒開持久化,卻重啟了實例,數據全掉——記得非快取的資訊需要打開持久化
- RDB 的持久化需要 vm.overcommit_memory=1,否則會持久化失敗
- 沒有持久化情況下,主從,主重啟太快,從還沒認為主掛的情況下,從會清空自己的數據——人為重啟主節點前,先關閉從節點的同步
回答二:
我簡單說下 Redis 故障的排查方法吧。
- 了解清楚業務數據流是怎麼樣的
- 結合 Redis 監控查看 QPS、快取命中率、記憶體使用率等資訊
- 確認機器層面的資源是否有異常
- 故障時及時上機,使用 redis-cli monitor 列印出操作日誌,然後分析(事後分析此條失效)
- 和研發溝通,確認是否有大 Key 在堵塞(大 Key 也可以在日常的巡檢中獲得)
- 和組內同事溝通,確實是否有誤操作
- 和運維同事、研發一起排查流量是否正常,是否存在被刷的情況
更多的排查需要對線上系統的分析。
四、Redis 性能優化
1:提高 Redis 記憶體資料庫的性能,有哪些措施?
這個問題有點偏題了,還是回答下吧。整理下工作中積累的經驗:
- 根據不同業務選擇數據類型,有必要時對數據結構進行審核,減少數據冗餘
- 精簡鍵名和鍵值,控制鍵值的大小
- 使用前綴管理好 key
- 使用 scan 代替 keys,將遍歷 Redis DB 中所有 key 的操作放到客戶端來做
- 避免使用 O(N) 複雜度的命令
- 配置使用 ziplist 來優化 list
- 合理配置 maxmemory
- 數據量大的情況,做好 key 和 value 的壓縮
- 利用管道,批量處理命令
- 根據不同業務選擇短鏈接或者長鏈接
- 定期使用 redis-cli –big-keys 檢測大 Key
本文內容來自社區交流,由溫國兵、liucj2004、趙海等社區專家和會員分享,溫國兵整理彙編 轉自公眾號:talkwithtrend 網站社區:http://www.talkwithtrend.com/Topic/91