保定專業(yè)網(wǎng)站制作百度推廣賬戶優(yōu)化方案
文章目錄
- 前言
- 一、內(nèi)存管理
- 1、Redis過期策略
- 1.1、惰性過期
- 1.2、定期過期
- 清理頻率配置
- 清理流程
- 2、Redis淘汰策略
- 策略
- 流程
- 算法分析
- 1、LRU
- 2、LFU
- 二、持久化
- 1、RDB
- 2、AOF
前言
redis 內(nèi)存管理與持久化
一、內(nèi)存管理
redis我們的數(shù)據(jù)都是放在內(nèi)存里面的,但是內(nèi)存是有大小的,如果一直將數(shù)據(jù)放入,會導(dǎo)致內(nèi)存溢出,這時候需要進(jìn)行數(shù)據(jù)清理。
內(nèi)存的大小由一個配置決定
maxmemory 100mb
如果配置是0,那么默認(rèn)是電腦的內(nèi)存,如果是32bit 隱式大小為3G。
數(shù)據(jù)清理,通過兩張方式來實(shí)現(xiàn)。1、過期策略,2、淘汰策略
1、Redis過期策略
過期策略又分為惰性過期和定期過期
1.1、惰性過期
在Redis里面,就是每次在訪問操作Key的時候,判斷這個Key是不是過期了,如果過期了就刪除。
該策略就可以最大化地節(jié)省CPU資源,只有訪問的時候才去使用cpu判斷一下, 但是這樣卻對內(nèi)存非常不友好。如果沒有再次訪問,本來該key需要過期刪除,結(jié)果一直堆積在內(nèi)存里面,造成內(nèi)存泄露。
是不是可以定期去掃描,然后判斷是否過期刪除?答案是肯定的,redis也制定了另一種方案,定期過期
1.2、定期過期
清理頻率配置
定期就需要去定義這個循環(huán)周期,比如五分鐘一次,這個參數(shù)由redis.conf中的hz配置來決定,它的取值范圍是 1 到 500。
hz 參數(shù)定義了 Redis 每秒鐘執(zhí)行的事件循環(huán)次數(shù),這包括檢查和刪除過期鍵的任務(wù)。默認(rèn)情況下,hz 設(shè)置為 10,意味著每秒進(jìn)行 10 次過期鍵的檢查。
要修改這個值,你可以編輯 Redis 配置文件 (redis.conf) 或者在運(yùn)行時通過 CONFIG SET 命令動態(tài)修改:
- 在配置文件中設(shè)置
打開你的 redis.conf 文件,并找到 hz 參數(shù),將其值更改為所需的頻率。例如,如果你想將頻率提高到每秒20次,則設(shè)置如下:
hz 20
- 動態(tài)配置
如果你不想重啟 Redis 服務(wù),也可以使用 CONFIG SET 命令在線更改此參數(shù)。例如:
CONFIG SET hz 20
需要注意的是,雖然增加 hz 的值可以讓 Redis 更快地處理同時到期的許多鍵,并且更加精確地處理超時,但這會占用更多的 CPU 資源。
因此,通常不建議將 hz 設(shè)置得過高(超過 100),除非是在對請求延時要求非常低的情況下。
從 Redis 6.2 開始,server.hz 的實(shí)際生效值可能會根據(jù)客戶端連接的數(shù)量動態(tài)調(diào)整,以確保即使在高負(fù)載下也能保持良好的性能。這意味著配置文件中的 hz 只是一個初始值,而實(shí)際運(yùn)行時的刷新頻率是動態(tài)變化的。
清理流程
- serverCron方法定時去執(zhí)行清理,執(zhí)行頻率根據(jù)redis.conf中的hz配置的值
- 執(zhí)行清理的時候,不是去掃描所有的key,而是去掃描所有設(shè)置了過期時間的key(redisDb.expires)
- 如果每次去把所有過期的key都拿過來,那么假如過期的key很多,就會很慢,所以也不是一次性拿取所有的key
- 根據(jù)hash桶的維度去掃描key,掃到20(可配)個key為止。假如第一個桶是15個key ,沒有滿足20,繼續(xù)掃描第二個桶,第二個桶20個key,由于是以hash桶的維度掃描的,所以第二個掃到了就會全掃,總共掃描35個key
- 掃描出來的過期的key,進(jìn)行刪除
- 如果取了400個空桶,或者掃描的刪除比例跟掃描的總數(shù)超過10%,繼續(xù)執(zhí)行4、5步。
- 也不能無限的循環(huán),循環(huán)16次后回去檢測時間,超過指定時間會跳出。
流程圖:
2、Redis淘汰策略
策略
由于Redis內(nèi)存是有大小的,并且里面的數(shù)據(jù)都沒有過期,這樣一直放入數(shù)據(jù),使得內(nèi)存滿了的時候,Redis就不能放入新的數(shù)據(jù),導(dǎo)致不可用,這是我們不愿意看到的。
所以,我們需要使用一些策略來解決這個問題來保證可用性,
官網(wǎng)提供了8種不同的策略
- noeviction(默認(rèn)):
不進(jìn)行任何淘汰。當(dāng)內(nèi)存使用超過限制后,所有寫入操作將返回錯誤信息,而讀取操作仍然可以正常執(zhí)行。 - volatile-lru:
使用 LRU (Least Recently Used) 算法從設(shè)置了過期時間的鍵中淘汰最久未使用的鍵。 - allkeys-lru:
使用 LRU 算法從所有鍵中淘汰最久未使用的鍵,包括那些沒有設(shè)置過期時間的鍵。 - volatile-lfu:
使用 LFU (Least Frequently Used) 算法從設(shè)置了過期時間的鍵中淘汰最少使用的鍵。這個策略是在 Redis 4.0 版本引入的。 - allkeys-lfu:
使用 LFU 算法從所有鍵中淘汰最少使用的鍵。同樣是在 Redis 4.0 中新增的功能。 - volatile-random:
隨機(jī)地從設(shè)置了過期時間的鍵中挑選一個鍵進(jìn)行淘汰。 - allkeys-random:
隨機(jī)地從所有鍵中挑選一個鍵進(jìn)行淘汰。 - volatile-ttl:
淘汰那些設(shè)置了過期時間且剩余生存時間最短的鍵,即優(yōu)先刪除即將過期的鍵。
我們可以在config中配置maxmemory-policy來指定相關(guān)的淘汰策略
maxmemory-policy noeviction //默認(rèn)不淘汰數(shù)據(jù),能讀不能寫
流程
- redis有個淘汰池,默認(rèn)大小是16,并且里面的數(shù)據(jù)是末尾淘汰制。
- 每次指令操作的時候,會判斷當(dāng)前內(nèi)存是否滿足指令所需要的內(nèi)存
- 如果當(dāng)前內(nèi)存不能滿足,會從淘汰池中的尾部拿取一個最適合淘汰的數(shù)據(jù)
- 會取樣(配置 maxmemory-samples)從Redis中獲取隨機(jī)獲取到取樣的數(shù)據(jù),解決一次性讀取所有的數(shù)據(jù)慢的問題
- 在取樣的數(shù)據(jù)中,根據(jù)淘汰算法,找到最適合淘汰的數(shù)據(jù)
- 將最合適的那個數(shù)據(jù)跟淘汰池中的數(shù)據(jù)比較,是否比淘汰池中的更適合淘汰,如果更適合,放入淘汰池
- 按照適合的程度進(jìn)行排序,最適合淘汰的放入尾部
- 將需要淘汰的數(shù)據(jù)從Redis刪除,并且從淘汰池移除。
流程圖:
算法分析
1、LRU
LRU,Least Recently Used 翻譯過來是最久未使用,根據(jù)時間軸來走,仍很久沒用的數(shù)據(jù)。只要最近有用過,我就默認(rèn)是有效的。
根據(jù)使用時間,從近到遠(yuǎn),越遠(yuǎn)的越容易淘汰
1、實(shí)現(xiàn)原理
- 首先,LRU是根據(jù)這個對象的訪問操作時間來進(jìn)行淘汰的,那我們需要知道這個對象最后的操作訪問時間。
- 知道了對象的最后操作訪問時間后,我們只需要跟當(dāng)前的系統(tǒng)時間來進(jìn)行對比,就能計(jì)算出對象已經(jīng)多久沒訪問了
2、時間計(jì)算
- 它使用一個24位的時鐘計(jì)數(shù)器,每秒遞增一次。這個計(jì)數(shù)器提供的分辨率足以滿足大多數(shù)應(yīng)用場景的需求,同時大大減少了存儲時間戳所需的內(nèi)存空間。
- 每當(dāng)一個鍵被訪問時,就會更新它的 LRU 字段為當(dāng)前的lruclock值。當(dāng)時間超過24位(秒,大概是194天),lruclock又會從0開始。redisObject.lru則是記錄當(dāng)前時間。
- 如果redisObject.lru < lruclock,直接通過 lruclock-redisObject.lru 得到這個對象多久沒訪問
- 如果redisObject.lru > lruclock,通過 lruclock+(24bit的最大值-redisObject.lru)得到這個對象多久沒訪問
輪詢
這里有個輪詢的概念,它如果超過24位,又會從0開始。
以時鐘為例
昨天10點(diǎn)訪問的記錄,現(xiàn)在是12點(diǎn)了,請問過了多久?12 - 10 = 2h
昨天10點(diǎn)訪問的記錄,現(xiàn)在是5點(diǎn)了,請問過了多久?24- 10 + 5 = 19h
這里的現(xiàn)在可能是今天,也可能是明天,就是輪詢了多天,那該如何計(jì)算
對于redis而言,偽lru算法本來就不是非常精確的。所以redis只考慮1次輪詢的情況,對于多次輪詢,也只按1次輪詢處理。
也就是說現(xiàn)在只當(dāng)成今天處理,不會當(dāng)成明天或者后天等。
3、知識點(diǎn):
系統(tǒng)時間戳記錄在全局變量中,每100ms更新一次。當(dāng)函數(shù)查詢key調(diào)?lookupKey中更新數(shù)據(jù)的Iru熱度值時,就不?每次調(diào)?系統(tǒng)函數(shù)time,可以提?執(zhí)?效率。
4、流程圖:
2、LFU
LFU,LeastFrequentlyUsed,最不常?,按照使?頻率刪除,4.0版本新增。 它的衡量標(biāo)準(zhǔn)就是次數(shù),次數(shù)越少的越容易被淘汰。每次操作訪問一次,就+1; 淘汰的時候,直接去比較這個次數(shù),次數(shù)越少的越容易淘汰。
1、redisObject.lru的前16bit表示時間,后8bit表示這個對象的訪問頻率。
前16bit代表的是這個對象最后訪問時間的分單位。通過這個值能夠得到這個對象多少分鐘沒訪問。結(jié)合lfu-decay-time,來控制對象的訪問頻率。這樣能有效控制很久沒訪問的數(shù)據(jù)一直保持熱點(diǎn)。
lfu-decay-time 1 // 衰減因子,多少分鐘沒訪問就減少一次
2、8bit最大值是255,用后8bit表示訪問次數(shù)是不夠的。redis在這里做了一些處理,讓數(shù)據(jù)達(dá)到255很難。方案如下:
- 訪問次數(shù)最大只能255,如果到了255,不往上加。實(shí)際到達(dá)255的幾率不是很高??梢灾魏艽蠛艽蟮臄?shù)據(jù)量。
- 訪問次數(shù)屬于隨機(jī)添加,添加的幾率根據(jù)基數(shù)值(LFU_INIT_VAL)、已有的counter值、配置server.lfu_log_factor相關(guān),counter值越大,添加的幾率越小,lfu-log-factor配置的值越大,添加的幾率越小。
假設(shè)基準(zhǔn)值是100 - 訪問次數(shù) < 100,則每次訪問則+1
- 訪問次數(shù) 100 <= counter <= 255,要通過公式計(jì)算,越往上,增長因子越低。會讓255很難達(dá)到,從而8位就能滿足需求了。
3、官方的壓測數(shù)據(jù)如下
二、持久化
Redis 作為一個內(nèi)存數(shù)據(jù)庫,其主要特性之一是高性能的數(shù)據(jù)操作,而這種高性能得益于數(shù)據(jù)存儲在內(nèi)存中。在某些情況下,如服務(wù)器重啟、操作系統(tǒng)崩潰、電源故障等,內(nèi)存中的數(shù)據(jù)會丟失。因此,Redis 需要持久化來保證數(shù)據(jù)的安全性和可恢復(fù)性。
redis持久化方式
- RDB
- AOF
- RDB + AOF
1、RDB
工作原理:
RDB 是通過創(chuàng)建數(shù)據(jù)集的時間點(diǎn)快照(snapshot)來實(shí)現(xiàn)的持久化機(jī)制。Redis 會將內(nèi)存中的數(shù)據(jù)在特定時間點(diǎn)保存到磁盤上的一個二進(jìn)制文件(默認(rèn)名為 dump.rdb)中。
- 文件配置: 磁盤文件的路徑和文件名都是可配置的
// 生成的快照文件名
dbfilename dump.rdb
// 快照文件保存的路徑
dir ./// 開啟數(shù)據(jù)壓縮(默認(rèn)開啟),如果關(guān)閉,會導(dǎo)致.rdb文件變得很大
rdbcompression yes
- 自動觸發(fā):通過配置文件中的 save 選項(xiàng)來指定自動觸發(fā) RDB 快照的條件
save 900 1 # 900秒(15分鐘)內(nèi)有1個鍵被修改就保存快照
save 300 10 # 300秒(5分鐘)內(nèi)有10個鍵被修改就保存快照
save 60 10000 # 60秒(1分鐘)內(nèi)有10000個鍵被修改就保存快照
以上的配置在 redis.conf 完成
- 手動觸發(fā):Redis 提供了一些命令可以手動觸發(fā) RDB 快照
- BGSAVE 命令:這個命令會在后臺進(jìn)行保存操作,Redis 會繼續(xù)處理來自客戶端的請求。
- SAVE 命令:與 BGSAVE 不同,SAVE 命令在執(zhí)行期間會阻塞 Redis 服務(wù)器,直到快照完成。
優(yōu)點(diǎn):
- 生成的rdb文件是一個非常緊湊的文件,所以很適合遠(yuǎn)程傳輸、備份和災(zāi)難恢復(fù)。
- 數(shù)據(jù)恢復(fù)速度快,因?yàn)槲募袷椒浅>o湊。
- 對讀取性能沒有影響,適合用于讀取密集型場景。
缺點(diǎn):
- 安全性很低,可能會有數(shù)據(jù)丟失。假如每5分鐘備份一次,斷電宕機(jī)后會有5分鐘的數(shù)據(jù)丟失。
- 經(jīng)常fork子進(jìn)程,所以比較耗CPU,對CPU不是很友好(對CPU要求高)。
2、AOF
工作原理:
AOF是通過將每一個寫命令記錄到日志文件(默認(rèn)名為appendonly.aof)中實(shí)現(xiàn)的。Redis 在處理寫命令時,會將這些命令追加到日志文件的末尾。在恢復(fù)數(shù)據(jù)時,Redis 會通過重新執(zhí)行這些命令來重建數(shù)據(jù)集。
配置:
通過配置文件中的 appendonly 和 appendfsync 選項(xiàng)來啟用并配置 AOF ,例如:
appendonly yes # 啟用AOF持久化
appendfsync everysec # 每秒持久化一次
# 其他選項(xiàng)可以是:
# appendfsync always # 每次寫操作后持久化(最安全但對性能影響最大)
# appendfsync no # 由操作系統(tǒng)決定何時持久化(性能最好,但最不安全)
AOF有個問題:隨著時間的推移,寫入的命令越來越多,相應(yīng)的AOF的日志文件越來越大,文件中冗余內(nèi)容會越來越多。如果redis再重啟或做數(shù)據(jù)恢復(fù),加載數(shù)據(jù)會很慢。
處理這個問題,則需要重寫AOF
AOF 重寫機(jī)制的工作原理
- Fork 子進(jìn)程:
- Redis 會 fork 一個子進(jìn)程,這個子進(jìn)程會創(chuàng)建一個新的 AOF 文件。
- 子進(jìn)程將根據(jù)當(dāng)前內(nèi)存中的數(shù)據(jù)來生成這個新的 AOF 文件,而不是直接復(fù)制現(xiàn)有的 AOF 文件。
- 命令壓縮:
- 新的 AOF 文件會包含相同的數(shù)據(jù),但是會優(yōu)化和壓縮命令。例如,多個對同一個 key 的寫操作可能會被壓縮為一個 SET 或者其他合并操作。
- 追加命令:
- 在子進(jìn)程創(chuàng)建新 AOF 文件的過程中,主進(jìn)程仍然在接受新寫操作。將這些新的寫操作記錄到一個內(nèi)存緩沖區(qū)中。
- 當(dāng)子進(jìn)程完成新 AOF 文件的創(chuàng)建后,主進(jìn)程將內(nèi)存緩沖區(qū)中的新寫操作追加到新的 AOF 文件。
- 文件替換:
- 最后, Redis 會將舊的 AOF 文件替換成新的 AOF 文件。
觸發(fā)條件和策略
AOF 重寫可以通過自動觸發(fā)和手動觸發(fā)兩種方式進(jìn)行:
- 自動觸發(fā)
Redis 可以根據(jù)配置的條件自動觸發(fā) AOF 重寫。以下是與自動觸發(fā)相關(guān)的配置選項(xiàng):
# 設(shè)置當(dāng)前 AOF 文件大小相對于上一次重寫后的大小增加的百分比,當(dāng)超過這個百分比時觸發(fā)AOF重寫。
# 比如設(shè)置為 100,表示當(dāng)前 AOF 文件大小是上次重寫后的兩倍時觸發(fā)重寫。
auto-aof-rewrite-percentage 100# 設(shè)置觸發(fā) AOF 重寫的最小 AOF 文件大小。
# 比如設(shè)置為 64mb,表示 AOF 文件至少達(dá)到 64MB 時才允許觸發(fā)重寫。
auto-aof-rewrite-min-size 64mb
- 手動觸發(fā)
管理員可以通過 Redis 命令手動觸發(fā) AOF 重寫:
BGREWRITEAOF 命令:
BGREWRITEAOF
該命令在后臺重寫 AOF 文件,不會阻塞 Redis 的正常操作
AOF優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 提供更高的數(shù)據(jù)安全性,因?yàn)閷懨顜缀鯇?shí)時持久化,數(shù)據(jù)丟失風(fēng)險小。
- AOF文件是可讀的,可以通過文本編輯器閱讀和編輯日志文件中的命令。
- 可以配置不同的頻率來記錄命令,使得持久化策略更靈活。
缺點(diǎn):
- AOF日志文件通常比RDB快照文件大。
- 隨著時間推移,日志文件會不斷增長,需要定期重寫(rewrite)日志文件,以縮減其大小。
- 數(shù)據(jù)恢復(fù)速度較慢,因?yàn)樾枰粭l一條重放寫操作。
3、AOF + RDB:
Redis 還支持同時開啟兩種持久化機(jī)制,以結(jié)合兩者的優(yōu)點(diǎn)。通常會選擇 RDB 作為定期的全量備份方案,而 AOF 作為增量日志記錄,確保在最后一次 RDB 快照之后的數(shù)據(jù)變更也能夠持久化。
同時開啟配置
# 啟用 AOF 持久化
appendonly yes
appendfsync everysec# RDB 持久化配置
save 900 1
save 300 10
save 60 10000
這種混合配置可以在確保較好性能的同時,最大限度減少數(shù)據(jù)丟失的風(fēng)險。