日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

【Redis 开发与运维】开发运维的“陷阱”

發布時間:2023/12/10 数据库 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【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 900 1 save 300 10 save 60 10000
  • 那么除非手動執行過 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 配置解決了這個問題,例如添加如下配置:
rename-command flushall abcabcabc
  • 那么再執行 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):
    public void delBigHash(String bigKey) {// 游標Jedis jedis = new Jedis("127.0.0.1", 6379);String cursor = "0";while (true) {ScanResult<Map.Entry<String, String>> scanResult = jedis.hscan(bigKey, cursor, new ScanParams().count(100));// 每次掃描后獲取新的游標cursor = scanResult.getStringCursor();// 獲取掃描結果List<Map.Entry<String, String>> list = scanResult.getResult();if (list == null || list.size() == 0) {continue;}String[] fields = getFieldsFrom(list);// 刪除多個fieldjedis.hdel(bigkey, fields);// 游標為0時停止if (cursor.equals("0")) {break;}}//最終刪除keyjedis.del(bigKey);}/*** 獲取 field 數組* @param list* @return*/private String[] getFieldsFrom(List<Map.Entry<String, String>> list) {List<String> fields = new ArrayList<>();for (Map.Entry<String, String> entry : list) {fields.add(entry.getKey());}return fields.toArray(new String[fields.size()]);}
  • 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 开发与运维】开发运维的“陷阱”的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。