1. 初識redis
redis的8個特性:速度快、基於鍵值對的數據結構服務器、功能豐富、簡單穩定、客戶端語言多、持久化、主從複製、支持高可用和分佈式。
redis不是萬金油,有些場景不符合redis
開發運維結合以及閱讀源碼
生產環境中使用配置文件啓動redis
Redis3.0是重要的里程碑, 發佈了Redis官方的分佈式實現Redis Cluster。
2. API的理解和使用
Redis提供5種數據結構, 每種數據結構都有多種內部編碼實現。
純內存存儲、 IO多路複用技術、 單線程架構是造就Redis高性能的三個因素。
因爲Redis的單線程架構, 因此須要每一個命令能被快速執行完, 不然會存在阻塞Redis的可能, 理解Redis單線程命令處理機制是開發和運維Redis的核心之一。
批量操做(例如mget、 mset、 hmset等) 可以有效提升命令執行的效率, 但要注意每次批量操做的個數和字節數。
瞭解每一個命令的時間複雜度在開發中相當重要, 例如在使用keys、 hgetall、 smembers、 zrange等時間複雜度較高的命令時,須要考慮數據規模對於Redis的影響。
persist命令能夠刪除任意類型鍵的過時時間, 可是set命令也會刪除字符串類型鍵的過時時間, 這在開發時容易被忽視。
move、 dump+restore、 migrate是Redis發展過程當中三種遷移鍵的方式, 其中 move命令基本廢棄, migrate命令用原子性的方式實現了dump+restore, 而且支持批量操做, 是Redis Cluster實現水平擴容的重要工具。
scan命令能夠解決keys命令可能帶來的阻塞問題, 同時Redis還提供了hscan、 sscan、 zscan漸進式地遍歷hash、 set、 zset。
3. 小功能大用處
慢查詢中的兩個重要參數slowlog-log-slower-than和slowlog-max-len。
慢查詢不包含命令網絡傳輸和排隊時間。
有必要將慢查詢按期存放。
redis-cli一些重要的選項, 例如--latency、 –-bigkeys、 -i和-r組合。
redis-benchmark的使用方法和重要參數。
Pipeline能夠有效減小RTT次數, 但每次Pipeline的命令數量不能無節制。
Redis可使用Lua腳本創造出原子、 高效、 自定義命令組合。
Redis執行Lua腳本有兩種方法: eval和evalsha。
Bitmaps能夠用來作獨立用戶統計, 有效節省內存。
Bitmaps中setbit一個大的偏移量, 因爲申請大量內存會致使阻塞。
HyperLogLog雖然在統計獨立總量時存在必定的偏差, 可是節省的內存量十分驚人。
Redis的發佈訂閱機制相比許多專業的消息隊列系統功能較弱, 不具有堆積和回溯消息的能力, 但勝在足夠簡單。
Redis3.2提供了GEO功能, 用來實現基於地理位置信息的應用, 但底層實現是zset。
4. 客戶端
RESP(Redis Serialization Protocol Redis) 保證客戶端與服務端的正常通訊, 是各類編程語言開發客戶端的基礎。
要選擇社區活躍客戶端, 在實際項目中使用穩定版本的客戶端。
區分Jedis直連和鏈接池的區別, 在生產環境中, 應該使用鏈接池。
Jedis.close() 在直連下是關閉鏈接, 在鏈接池則是歸還鏈接。
Jedis客戶端沒有內置序列化, 須要本身選用。
客戶端輸入緩衝區不能配置, 強制限制在1G以內, 可是不會受到maxmemory限制。
客戶端輸出緩衝區支持普通客戶端、 發佈訂閱客戶端、 複製客戶端配置, 一樣會受到maxmemory限制。
Redis的timeout配置能夠自動關閉閒置客戶端, tcp-keepalive參數能夠週期性檢查關閉無效TCP鏈接
monitor命令雖然好用, 可是在大併發下存在輸出緩衝區暴漲的可能性。
info clients幫助開發和運維人員找到客戶端可能存在的問題。
理解Redis通訊原理和創建完善的監控系統對快速定位解決客戶端常見問題很是有幫助。
5. 持久化
Redis提供了兩種持久化方式: RDB和AOF。
RDB使用一次性生成內存快照的方式, 產生的文件緊湊壓縮比更高, 所以讀取RDB恢復速度更快。 因爲每次生成RDB開銷較大, 沒法作到實時持久化, 通常用於數據冷備和複製傳輸。
save命令會阻塞主線程不建議使用, bgsave命令經過fork操做建立子進程生成RDB避免阻塞。
AOF經過追加寫命令到文件實現持久化, 經過appendfsync參數能夠控制實時/秒級持久化。 由於須要不斷追加寫命令, 因此AOF文件體積逐漸變大, 須要按期執行重寫操做來下降文件體積。
AOF重寫能夠經過auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參數控制自動觸發, 也可使用bgrewriteaof命令手動觸發。
子進程執行期間使用copy-on-write機制與父進程共享內存, 避免內存消耗翻倍。 AOF重寫期間還須要維護重寫緩衝區, 保存新的寫入命令避免數據丟失。
持久化阻塞主線程場景有: fork阻塞和AOF追加阻塞。 fork阻塞時間跟內存量和系統有關, AOF追加阻塞說明硬盤資源緊張。
單機下部署多個實例時, 爲了防止出現多個子進程執行重寫操做, 建議作隔離控制, 避免CPU和IO資源競爭。
6. 複製
Redis經過複製功能實現主節點的多個副本。 從節點可靈活地經過slaveof命令創建或斷開復制流程。
複製支持樹狀結構, 從節點能夠複製另外一個從節點, 實現一層層向下的複製流。 Redis2.8以後複製的流程分爲: 全量複製和部分複製。 全量複製須要同步所有主節點的數據集, 大量消耗機器和網絡資源。 而部分複製有效減小因網絡異常等緣由形成的沒必要要全量複製狀況。 經過配置合理的複製積壓緩衝區儘可能避免全量複製。
主從節點之間維護心跳和偏移量檢查機制, 保證主從節點通訊正常和數據一致
Redis爲了保證高性能複製過程是異步的, 寫命令處理完後直接返回給客戶端, 不等待從節點複製完成。 所以從節點數據集會有延遲狀況。
當使用從節點用於讀寫分離時會存在數據延遲、 過時數據、 從節點可用性等問題, 須要根據自身業務提早做出規避。
在運維過程當中, 主節點存在多個從節點或者一臺機器上部署大量主節點的狀況下, 會有複製風暴的風險。
7. redis的噩夢:阻塞
客戶端最早感知阻塞等Redis超時行爲, 加入日誌監控報警工具可快速定位阻塞問題, 同時須要對Redis進程和機器作全面監控。
阻塞的內在緣由: 確認主線程是否存在阻塞, 檢查慢查詢等信息, 發現不合理使用API或數據結構的狀況, 如keys、 sort、 hgetall等。 關注CPU使用率防止單核跑滿。 當硬盤IO資源緊張時, AOF追加也會阻塞主線程。
阻塞的外在緣由: 從CPU競爭、 內存交換、 網絡問題等方面入手排查是否由於系統層面問題引發阻塞。
8. 理解內存
Redis實際內存消耗主要包括: 鍵值對象、 緩衝區內存、 內存碎片。
經過調整maxmemory控制Redis最大可用內存。 當內存使用超出時, 根據maxmemory-policy控制內存回收策略。
內存是相對寶貴的資源, 經過合理的優化能夠有效地下降內存的使用量, 內存優化的思路包括:
精簡鍵值對大小, 鍵值字面量精簡, 使用高效二進制序列化工具。
使用對象共享池優化小整數對象。
數據優先使用整數, 比字符串類型更節省空間。
優化字符串使用, 避免預分配形成的內存浪費
使用ziplist壓縮編碼優化hash、 list等結構, 注重效率和空間的平衡。
使用intset編碼優化整數集合。
使用ziplist編碼的hash結構下降小對象鏈規模。
9. 哨兵
Redis Sentinel是Redis的高可用實現方案: 故障發現、 故障自動轉移、 配置中心、 客戶端通知。
Redis Sentinel從Redis2.8版本開始才正式生產可用, 以前版本生產不可用。
儘量在不一樣物理機上部署Redis Sentinel全部節點。
Redis Sentinel中的Sentinel節點個數應該爲大於等於3且最好爲奇數。
Redis Sentinel中的數據節點與普通數據節點沒有區別。
客戶端初始化時鏈接的是Sentinel節點集合, 再也不是具體的Redis節點, 但Sentinel只是配置中心不是代理。
Redis Sentinel經過三個定時任務實現了Sentinel節點對於主節點、 從節點、 其他Sentinel節點的監控。
Redis Sentinel在對節點作失敗斷定時分爲主觀下線和客觀下線。
看懂Redis Sentinel故障轉移日誌對於Redis Sentnel以及問題排查很是有幫助。
Redis Sentinel實現讀寫分離高可用能夠依賴Sentinel節點的消息通知, 獲取Redis數據節點的狀態變化。
10. 集羣