Redis優化經驗總結
關於記憶體管理優化,本文主要和大家分享Redis優化經驗總結,希望能幫助大家。
Redis Hash是value內部為一個HashMap,如果該Map的成員數比較少,則會採用類似一維線性的緊湊格式來存儲該Map, 即省去了大量指針的內存開銷,這個參數控制對應在redis.conf設定檔中下面2項:
hash-max-zipmap-entries 64 hash-max-zipmap-value 512
當value這個Map內部不超過多少個成員時會採用線性緊湊格式存儲,預設是64,即value內部有64個以下的成員就是使用線性緊湊存儲,超過該值自動轉成真正的HashMap。
hash-max-zipmap-value 意義是當 value這個Map內部的每個成員值長度不超過多少位元組就會採用線性緊湊儲存來節省空間。
以上2個條件任一個條件超過設定值都會轉換成真正的HashMap,也就不會再節省記憶體了,那麼這個值是不是設定的越大越好呢,答案當然是否定的, HashMap的優勢就是查找和操作的時間複雜度都是O(1)的,而放棄Hash採用一維存儲則是O(n)的時間複雜度,如果
成員數量很少,則影響不大,否則會嚴重影響效能,所以要權衡好這個值的設置,整體上還是最根本的時間成本和空間成本上的權衡。
list-max-ziplist-value 64 list-max-ziplist-entries 512
list資料類型節點值大小小於多少位元組會採用緊湊儲存格式、list資料型別多少節點會採用去指標的緊湊儲存格式。
記憶體預先分配:
Redis內部實作沒有對記憶體分配方面做過多的最佳化(對比Memcache),在一定程度上會存在記憶體碎片,不過大多數情況下這個不會成為Redis的效能瓶頸,不過如果在Redis內部儲存的大部分資料是數值型的話,Redis內部採用了一個shared integer的方式來省去分配記憶體的開銷,即在系統啟動時先分配一個從1~ n 那麼多個數值對象放在一個池子中,如果存儲的數據恰好是這個數值範圍內的數據,則直接從池子裡取出該對象,並且通過引用計數的方式來共享,這樣在系統存儲了大量數值下,也能一定程度上節省記憶體並且提高效能,這個參數值n的設定需要修改原始碼中的一行巨集定義REDIS_SHARED_INTEGERS,這個值預設是10000,可以依照自己的需求進行修改,修改後重新編譯就可以了。
持久化機制:
定時快照方式(snapshot):
該持久化方式實際上是在Redis內部一個定時器事件,每隔固定時間去檢查當前資料發生的改變次數與時間是否滿足配置的持久化觸發的條件,如果滿足則透過作業系統fork呼叫來建立出一個子進程,這個子進程預設會與父進程共享相同的位址空間,這時就可以透過子進程來遍歷整個內存來進行存儲操作,而主進程則仍然可以提供服務,當有寫入時由操作系統按照內存頁(page)為單位來進行copy-on-write保證父子進程之間不會互相影響。
這個持久的主要缺點是定時快照只是代表一段時間內的記憶體映像,所以系統重新啟動會遺失上次快照與重新啟動之間所有的資料。
基於語句追加方式(aof):
aof方式實際類似mysql的基於語句的binlog方式,即每條會使Redis內存資料改變的命令都會追加到一個log文件中,也就是說這個log檔案就是Redis的持久化資料。
aof的方式的主要缺點是追加log檔案可能導致體積過大,當系統重啟恢復資料時如果是aof的方式則加載資料會非常慢,幾十G的資料可能需要幾小時才能載入完,當然這個耗時並不是因為磁碟檔案讀取速度慢,而是由於讀取的所有指令都要在記憶體中執行一遍。另外由於每個指令都要寫log,所以使用aof的方式,Redis的讀寫效能也會有所下降。
可以考慮將資料保存到不同的Redis實例中,每個實例的記憶體大小在2G左右,避免將雞蛋放到一個籃子裡,既可以減少快取失效對系統帶來的影響,又可以加快資料恢復的速度,不過同時也為系統設計帶來了一定的複雜性。
Redis持久化崩潰問題:
有Redis線上維運經驗的人會發現Redis在物理記憶體使用比較多,但還沒有超過實際物理記憶體總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持久化的fork系統調用造成內存佔用加倍而導致的,這種觀點是不准確的,因為fork 調用的copy-on-write機制是基於操作系統頁這個單位的,也就是只有有寫入的髒頁會被複製,但是一般你的系統不會在短時間內所有的頁都發生了寫入而導致複製,那麼是什麼原因導致Redis崩潰的呢?
答案是Redis的持久化使用了Buffer IO造成的,所謂Buffer IO是指Redis對持久化檔案的寫入和讀取操作都會使用物理記憶體的Page Cache,而大多數資料庫系統會使用Direct IO來繞過這層Page Cache並自行維護一個資料的Cache,而當Redis的持久化檔案過大(尤其是快照檔案),並對其進行讀寫時,磁碟檔案中的資料都會被載入到實體內存中作為作業系統對該檔案的一層Cache,而這層Cache的資料與Redis記憶體中管理的資料實際上是重複儲存的,雖然核心在物理記憶體緊張時會做Page Cache的剔除工作,但核心很可能認為某塊Page Cache更重要,而讓你的進程開始Swap ,這時你的系統就會開始出現不穩定或崩潰了。我們的經驗是當你的Redis實體記憶體使用超過記憶體總容量的3/5時就會開始比較危險了。
總結:
1、根據業務需求選擇合適的資料類型,並為不同的應用場景設定對應的緊湊儲存參數。
2、當業務場景不需要資料持久化時,關閉所有的持久化方式可以獲得最佳的效能以及最大的記憶體使用量。
3、如果需要使用持久化,根據是否可以容忍重啟丟失部分資料在快照方式與語句追加方式之間選擇其一,不要使用虛擬記憶體以及diskstore方式。
4、不要讓你的Redis所在機器物理記憶體使用超過實際記憶體總量的3/5。
redis.conf中的maxmemory選項,該選項是告訴Redis當使用了多少物理內存後就開始拒絕後續的寫入請求,該參數能很好的保護好你的Redis不會因為使用了過多的實體記憶體而導致swap,最終嚴重影響效能甚至崩潰。
redis.conf檔中vm-enabled 為no
相關推薦:
以上是Redis優化經驗總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Redis集群模式通過分片將Redis實例部署到多個服務器,提高可擴展性和可用性。搭建步驟如下:創建奇數個Redis實例,端口不同;創建3個sentinel實例,監控Redis實例並進行故障轉移;配置sentinel配置文件,添加監控Redis實例信息和故障轉移設置;配置Redis實例配置文件,啟用集群模式並指定集群信息文件路徑;創建nodes.conf文件,包含各Redis實例的信息;啟動集群,執行create命令創建集群並指定副本數量;登錄集群執行CLUSTER INFO命令驗證集群狀態;使

使用 Redis 指令需要以下步驟:打開 Redis 客戶端。輸入指令(動詞 鍵 值)。提供所需參數(因指令而異)。按 Enter 執行指令。 Redis 返迴響應,指示操作結果(通常為 OK 或 -ERR)。

啟動 Redis 服務器的步驟包括:根據操作系統安裝 Redis。通過 redis-server(Linux/macOS)或 redis-server.exe(Windows)啟動 Redis 服務。使用 redis-cli ping(Linux/macOS)或 redis-cli.exe ping(Windows)命令檢查服務狀態。使用 Redis 客戶端,如 redis-cli、Python 或 Node.js,訪問服務器。

使用Redis進行鎖操作需要通過SETNX命令獲取鎖,然後使用EXPIRE命令設置過期時間。具體步驟為:(1) 使用SETNX命令嘗試設置一個鍵值對;(2) 使用EXPIRE命令為鎖設置過期時間;(3) 當不再需要鎖時,使用DEL命令刪除該鎖。

要從 Redis 讀取隊列,需要獲取隊列名稱、使用 LPOP 命令讀取元素,並處理空隊列。具體步驟如下:獲取隊列名稱:以 "queue:" 前綴命名,如 "queue:my-queue"。使用 LPOP 命令:從隊列頭部彈出元素並返回其值,如 LPOP queue:my-queue。處理空隊列:如果隊列為空,LPOP 返回 nil,可先檢查隊列是否存在再讀取元素。

要查看 Redis 中的所有鍵,共有三種方法:使用 KEYS 命令返回所有匹配指定模式的鍵;使用 SCAN 命令迭代鍵並返回一組鍵;使用 INFO 命令獲取鍵的總數。

Redis 使用哈希表存儲數據,支持字符串、列表、哈希表、集合和有序集合等數據結構。 Redis 通過快照 (RDB) 和追加只寫 (AOF) 機制持久化數據。 Redis 使用主從復制來提高數據可用性。 Redis 使用單線程事件循環處理連接和命令,保證數據原子性和一致性。 Redis 為鍵設置過期時間,並使用 lazy 刪除機制刪除過期鍵。

Redis計數器是一種使用Redis鍵值對存儲來實現計數操作的機制,包含以下步驟:創建計數器鍵、增加計數、減少計數、重置計數和獲取計數。 Redis計數器的優勢包括速度快、高並發、持久性和簡單易用。它可用於用戶訪問計數、實時指標跟踪、遊戲分數和排名以及訂單處理計數等場景。
