【Redis 开发与运维】开发运维的“陷阱”
生活随笔
收集整理的這篇文章主要介紹了
【Redis 开发与运维】开发运维的“陷阱”
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一、Linux 配置優化
- 內存分配控制
- OOM killer
- 使用 NTP
- 二、flushall / flushdb 誤操作
- 緩存與存儲
- 借助 AOF 機制恢復
- RDB 有什么變化
- 三、安全的 Redis
- Redis 密碼機制
- 偽裝危險命令
- 防火墻
- 定期備份數據
- 不使用默認端口
- 使用非 root 用戶啟動
- 四、處理 bigkey
- bigkey 的危害
- 如何發現
- 如何刪除
- 五、尋找熱點 key
- 統計熱點 key
- 解決熱點 key 問題
一、Linux 配置優化
內存分配控制
- Redis 設置合理的 maxmemory,保證機器有 20% ~ 30% 的閑置內存。
- 集中化管理 AOF 重寫和 RDB 的 bgsave。
- 設置 vm.overcommit_memory=1,防止極端情況下會造成 fork 失敗。
OOM killer
- OOM killer 會在可用內存不足時選擇性地殺掉用戶進程。
- 對于 Redis 所在的服務器來說,可以將所有 Redis 的 oom_adj 設置為最低值或者稍小的值,降低被 OOM killer 殺掉的概率。
使用 NTP
- NTP(Network Time Protocol,網絡時間協議)是一種保證不同機器時鐘一致性的服務。一般公司里都會有 NTP 服務用來提供標準時間服務,從而達到糾正時鐘的效果。
二、flushall / flushdb 誤操作
- Redis 的 flushall / flushdb 命令可以做數據清除,對于 Redis 的開發和運維人員有一定幫助,然而一旦誤操作,它的破壞性也是很明顯的。
緩存與存儲
- 被誤操作 flush 后,根據當前 Redis 是緩存還是存儲使用策略有所不同:
- 緩存:對于業務數據的正確性可能造成損失還小一點,因為緩存中的數據可以從數據源重新進行構建。
- 存儲:對業務方可能會造成巨大的影響,如果沒有提前做業務降級,那么最終反饋到用戶的應用可能就是報錯或者空白頁面等。
借助 AOF 機制恢復
- Redis 執行了 flush 操作后,AOF 持久化文件會受到什么影響呢,如下:
- appendonly no:對 AOF 持久化沒有任何影響,因為根本不存在 AOF 文件。
- appendonly yes:只不過在 AOF 文件中追加了一條 flushall 記錄。
- 也就是說,雖然 Redis 中的數據被清掉了,但是 AOF 文件還保存著 flush 操作之前完整的數據,這對恢復數據是很有幫助的。
RDB 有什么變化
Redis 執行了 flushall 操作后,RDB持久化文件會受到什么影響呢?
- 1)如果沒有開啟 RDB 的自動策略,也就是配置文件中沒有類似如下配置
-
那么除非手動執行過 save、bgsave 或者發生了主從的全量復制,否則 RDB 文件也會保存 flush 操作之前的數據,可以作為恢復數據的數據源。注意問題如下:
- 防止手動執行 save、bgsave,如果此時執行 save、bgsave,新的 RDB 文件就不會包含 flush 操作之前的數據,被老的RDB文件進行覆蓋。
- RDB 文件中的數據可能沒有 AOF 實時性高,也就是說,RDB 文件很可能很久以前主從全量復制生成的,或者之前用 save、bgsave 備份的。
-
2)如果開啟了 RDB 的自動策略,由于 flush 涉及鍵值數量較多,RDB 文件會被清除意味著使用 RDB 恢復基本無望。
三、安全的 Redis
- 數據丟失對于很多 Redis 的開發者來說是致命的,經過相關機構的調查發現,被攻擊的 Redis 有如下特點:
- Redis 所在的機器有外網 IP
- Redis 以默認端口 6379 為啟動端口,并且是對外網開放的
- Redis 以 root 用戶啟動的 Redis 沒有設置密碼
- Redis 的 bind 設置為 0.0.0.0 或者 “”
- 將從下面幾個方面介紹如何保證 Redis 的安全。
Redis 密碼機制
- Redis 提供了 requirepass 配置為 Redis 提供密碼功能,如果添加這個配置,客戶端就不能通過 redis-cli -h {ip} -p {port} 來執行命令。
偽裝危險命令
- Redis 中包含了很多“危險”命令,一旦生產上錯誤使用或者誤操作,后果不堪設想,例如:
- keys:如果鍵值較多,存在阻塞 Redis 的可能性
- flushall/flushdb:數據全部被清除
- save:如果鍵值較多,存在阻塞 Redis 的可能性
- debug:個例如 debug reload 會重啟 Redis
- config:config 應該交給管理員使用
- shutdown:停止 Redis
- Redis 提供了 rename-command 配置解決了這個問題,例如添加如下配置:
- 那么再執行 flushall 的話,會收到 Redis 不認識 flushall 的錯誤提示,說明成功的對 flushall 進行了偽裝。
- 而如果執行 abcabcabc ,那么就可以實現 flushall 功能了。
防火墻
- 可以使用防火墻限制輸入和輸出的 IP 或者 IP 范圍、端口或者端口范圍。
定期備份數據
- 定期備份數據能夠在一定程度挽回一些損失,定期備份持久化數據是一個比較好的習慣。
不使用默認端口
- Redis 的默認端口是 6379,不使用默認端口從一定程度上可降低被入侵者發現的可能性,因為入侵者通常本身也是一些攻擊程序。
使用非 root 用戶啟動
- root 用戶作為管理員,權限非常大。如果被入侵者獲取 root 權限后,就可以在這臺機器以及相關機器所以操作。所以建議在啟動 Redis 服務的時候使用非 root 用戶啟動。
四、處理 bigkey
- bigkey 是指 key 對應的 value 所占的內存空間比較大,例如一個字符串類型的 value 可以最大存到 512MB,一個列表類型的 value 最多可以存儲 2^32 - 1 個元素。如果按照數據結構來細分的話,一般分為兩種:
- 字符串類型:體現在單個 value 值很大,一般認為超過 10 KB 就是 bigkey,但這個值和具體的 OPS 相關。
- 非字符串類型:哈希、列表、集合、有序集合,體現在元素個數過多。
bigkey 的危害
- 內存空間不均勻:例如在 Redis 集群中,bigkey 會造成節點的內存空間使用不均勻。
- 超時阻塞:由于 Redis 單線程的特性,操作 bigkey 比較耗時,也就意味著阻塞 Redis 可能性增大。
- 網絡阻塞:每次獲取 bigkey 產生的網絡流量較大。
如何發現
- redis-cli --bigkeys 可以命令統計 bigkey 的分布。但是生產環境中,開發和運維人員更希望自己可以定義 bigkey 的大小而且更希望找到真正的 bigkey 都有哪些 ,這樣才可以去定位、解決、優化問題。
- 判斷一個 key 是否為 bigkey,只需要執行 debug object key 查看 serializedlength 屬性即可,它表示 key 對應的 value 序列化之后的字節數。
- 在實際的生產環境中發現 bigkey 的兩種方式如下:
- 被動收集:許多開發人員確實可能對 bigkey 不了解或重視程度不夠,但是這種 bigkey 一旦大量訪問,很可能就會帶來命令慢查詢和網卡跑滿問題,開發人員通過對異常的分析通常能找到異常原因可能是 bigkey,這種方式并不推薦,但是在實際生產環境中卻大量存在,建議修改 Redis 客戶端,當拋出異常時打印出所操作的 key,方便排查 bigkey 問題。
- 主動檢測:scan + debug object,如果懷疑存在bigkey,可以使用scan命令漸進的掃描出所有的key,分別計算每個 key 的 serializedlength,找到對應 bigkey 進行相應的處理和報警,這種方式是比較推薦的方式。
如何刪除
- 首先,無論是什么數據結構,del 命令都能將其刪除。但是經過上面的分析你一定不會這么做,刪除 bigkey 通常來說會阻塞 Redis 服務。
- 這個時候就需要 scan 命令的若干類似命令拿出來:sscan、hscan、zscan。
- string
- 對于 string 類型使用 del 命令一般不會產生阻塞
- hash、list、set、sorted set
- 下面以 hash 為例子,使用 hscan 命令,每次獲取部分(例如 100 個)field-value,再利用 hdel 刪除每個 field(為了快速可以使用 Pipeline):
- Redis 4.0 新增了非常實用的惰性刪除 lazy free 特性,從根本上解決了 bigkey(主要指定元素較多集合類型key)刪除的風險
五、尋找熱點 key
熱門新聞事件或商品通常會給系統帶來巨大的流量,對存儲這類信息的 Redis 來說卻是一個巨大的挑戰。以 Redis Cluster 為例,它會造成整體流量的不均衡,個別節點出現 OPS 過大的情況,極端情況下熱點 key 甚至會超過 Redis 本身能夠承受的 OPS,因此尋找熱點 key 對于開發和運維人員非常重要。下面從以下幾個方面分析熱點 key。
統計熱點 key
- 客戶端
- 客戶端其實是距離 key “最近” 的地方,因為 Redis 命令就是從客戶端發出的,例如在客戶端設置全局字典(key 和調用次數),每次調用 Redis 命令時,使用這個字典進行記錄。
- 使用客戶端進行熱點 key 的統計非常容易實現,但同時問題也非常多:
- 無法預知 key 的個數,存在內存泄露的危險。
- 對于客戶端代碼有侵入,各個語言的客戶端都需要維護此邏輯,維護成本較高。
- 只能了解當前客戶端的熱點 key,無法實現規模化運維統計。
- 代理端
- 像 Twemproxy、Codis 這些基于代理的 Redis 分布式架構,所有客戶端的請求都是通過代理端完成的。此架構是最適合做熱點 key 統計的,因為代理是所有 Redis 客戶端和服務端的橋梁。但并不是所有Redis都是采用此種架構。
- Redis 服務端
- 使用 monitor 命令統計熱點 key 是很多開發和運維人員首先想到,monitor 命令可以監控到 Redis 執行的所有命令。
- 利用 monitor 命令就可以統計出一段時間內的熱點 key 排行榜、命令排行榜、客戶端分布等數據。
- 但是此種方法會有兩個問題:
- monitor 命令在高并發條件下,會存在內存暴增和影響 Redis 性能的隱患,所以此種方法適合在短時間內使用。
- 只能統計一個 Redis 節點的熱點 key,對于 Redis 集群需要進行匯總統計。
- 機器
- Redis 客戶端使用 TCP 協議與服務端進行交互,通信協議采用的是 RESP。如果站在機器的角度,可以通過對機器上所有 Redis 端口的 TCP 數據包進行抓取完成熱點 key 的統計。
解決熱點 key 問題
- 拆分復雜數據結構:如果當前 key 的類型是一個二級數據結構,例如哈希類型。如果該哈希元素個數較多,可以考慮將當前 hash 進行拆分,這樣該熱點 key 可以拆分為若干個新的 key 分布到不同 Redis 節點上,從而減輕壓力。
- 遷移熱點key:以 Redis Cluster 為例,可以將熱點 key 所在的 slot 單獨遷移到一個新的 Redis 節點上,但此操作會增加運維成本。
- 本地緩存加通知機制:可以將熱點 key 放在業務端的本地緩存中,因為是在業務端的本地內存中,處理能力要高出 Redis 數十倍,但當數據更新時,此種模式會造成各個業務端和 Redis 數據不一致,通常會使用發布訂閱機制來解決類似問題。
來源:《Redis 開發與運維》第 12 章 開發運維的“陷阱”
總結
以上是生活随笔為你收集整理的【Redis 开发与运维】开发运维的“陷阱”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL2000里的数据类型
- 下一篇: 《Redis开发与运维》- 核心知识整理