2.內(nèi)部原理分析

過期時(shí)間設(shè)置

在Redis中提供了Expire命令設(shè)置一個(gè)鍵的過期時(shí)間,到期以后Redis會(huì)自動(dòng)刪除它。這個(gè)在我們實(shí)際使用過程中用得非常多。

redis 過期刪除的原理

消極方法:在主鍵訪問時(shí)如果發(fā)現(xiàn)它已經(jīng)失效,那么就刪除它

積極方法:周期性地從設(shè)置了失效時(shí)間的主鍵中選擇一部分失效的主鍵刪除。

redis 發(fā)布訂閱

發(fā)布/訂閱模式包含兩種角色,分別是發(fā)布者和訂閱者。
訂閱者可以訂閱一個(gè)或多個(gè)頻道,而發(fā)布者可以向指定的頻道發(fā)送消息,所有訂閱此頻道的訂閱者都會(huì)受到該消息。

redis 的數(shù)據(jù)是如何持久化的?

RDB根據(jù)指定的規(guī)則定時(shí)將內(nèi)存中的數(shù)據(jù)存儲(chǔ)在硬盤上。
AOF在每次執(zhí)行命令后將命令本身記錄下來。
可以單獨(dú)/結(jié)合使用。

RDB

當(dāng)符合一定條件,redis 會(huì)單獨(dú)創(chuàng)建 fork 一個(gè)子進(jìn)程來進(jìn)行持久化,會(huì)先將數(shù)據(jù)寫入一個(gè)臨時(shí)文件 dump.rdb,等到持久化過程都結(jié)束了,
再用這個(gè)臨時(shí)文件替換上次持久化好的文件。整個(gè)過程中,主進(jìn)程是不進(jìn)行任何IO操作的。這就確保了極高的性能。
如果需要進(jìn)行大規(guī)模的數(shù)據(jù)的恢復(fù),且對(duì)于數(shù)據(jù)恢復(fù)的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
RDB唯一的缺點(diǎn)是最后一次持久化后的數(shù)據(jù)可能丟失。

fork的作用是復(fù)制一個(gè)與當(dāng)前線程一樣的進(jìn)程。新進(jìn)程的所有數(shù)據(jù)(變量、環(huán)境變量、程序計(jì)數(shù)器)數(shù)值都和原進(jìn)程一致,
但是是一個(gè)全新的進(jìn)程,并作為原進(jìn)程的子進(jìn)程。

符合條件

  1. 配置規(guī)則
    save seconds changes
    • save :當(dāng)執(zhí)行save命令時(shí),Redis同步做快照操作,在快照?qǐng)?zhí)行過程中會(huì)阻塞所有來自客戶端的請(qǐng)求。
      當(dāng)redis內(nèi)存中的數(shù)據(jù)較多時(shí),通過該命令將導(dǎo)致Redis較長(zhǎng)時(shí)間的不響應(yīng)。所以不建議在生產(chǎn)環(huán)境上使用這個(gè)命令,而是推薦使用bgsave命令
    • bgsave :bgsave 命令可以在后臺(tái)異步地進(jìn)行快照操作。快照的同時(shí)服務(wù)器還可以繼續(xù)響應(yīng)來自客戶端的請(qǐng)求。
      執(zhí)行BGSAVE后,Redis會(huì)立即返回ok表示開始執(zhí)行快照操作。
      當(dāng)redis 內(nèi)存中的數(shù)據(jù)較多時(shí),通過該命令導(dǎo)致喏、較長(zhǎng)時(shí)間的
  2. flushall 清空
  3. 執(zhí)行復(fù)制操作

AOF 方式 append-only-file

當(dāng)使用redis 存儲(chǔ)非臨時(shí)數(shù)據(jù)時(shí),一般需要打開AOF持久化來降低進(jìn)程終止導(dǎo)致的數(shù)據(jù)丟失。
AOF可以將redis執(zhí)行的每一條命令追加到硬盤文件中。這一過程會(huì)降低redis 的性能。
但大部分情況下這個(gè)影響是能夠接受的。另外使用較快的硬盤可以調(diào)AOF性能。

  • auto-aof-rewrite-perecntage 100 當(dāng)前寫入日志文件的大小超過上一次rewrite之后的文件大小的百分之100時(shí)就是2倍時(shí)觸發(fā)rewrite。
  • auto-aof-rewrite-min-size 64mb 最小重寫大小

redis 內(nèi)存回收策略 maxmemory-policy

redis提供了多種內(nèi)存回收策略,當(dāng)內(nèi)存容量不足時(shí),為了保證程序的運(yùn)行,不得不淘汰內(nèi)存中的一些對(duì)象,釋放這些對(duì)象占用空間。
淘汰對(duì)象選擇? 已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)

  • 默認(rèn)的策略是 noeviction。當(dāng)內(nèi)存使用達(dá)到閾值時(shí),所以引起申請(qǐng)內(nèi)存的命令都會(huì)報(bào)錯(cuò)。
  • allkeys-lur:從數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰。 應(yīng)用對(duì)緩存的訪問都是相對(duì)熱點(diǎn)數(shù)據(jù)。
  • volatile-random:從已設(shè)置時(shí)間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰。
  • volatile-lur:從已設(shè)置時(shí)間的數(shù)據(jù)集中選擇最近最少數(shù)據(jù)淘汰。
  • volatile-ttl:從已設(shè)置時(shí)間的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰。

redis 是單進(jìn)程單線程 來處理來自所有客戶端的并發(fā)請(qǐng)求。

cpu 并不是redis的瓶頸所在,redis的瓶頸主要機(jī)器的內(nèi)存和帶寬。
redis能處理高并發(fā)請(qǐng)求,是多路復(fù)用的并發(fā)IO(一個(gè)計(jì)算單元來處理來自多個(gè)客戶端的請(qǐng)求)

多路復(fù)用

redis是跑在單線程的,所有操作都是按照順序線性執(zhí)行的,但是由于讀寫操作等待用戶輸入或者輸出都是阻塞的,所以IO操作在一般情況下往往不能直接返回,
這會(huì)導(dǎo)致某一文件的IO阻塞導(dǎo)致整個(gè)進(jìn)程無法對(duì)其他客戶提供服務(wù),而IO多路復(fù)用就是為了這個(gè)問題出現(xiàn)的。

  • 同步阻塞
  • 同步非阻塞 socket被設(shè)置為NONBLOCK
  • IO多路復(fù)用:reactor設(shè)計(jì)模式,異步阻塞IO。java中的selector和linux中的epol都是這種模型
  • 異步IO:經(jīng)典的proactor設(shè)計(jì)迷失,也稱為異步非阻塞IO

在reids中使用 LUA 腳本

原子性問題:

redis雖然是單一線程的,但是仍然會(huì)存在線程安全問題。不是來自于redis的服務(wù)器內(nèi)部。
而是redis作為數(shù)據(jù)服務(wù)器,是提供給多個(gè)客戶端使用的。多個(gè)客戶端的操作就相當(dāng)于同一個(gè)進(jìn)程下的多個(gè)線程。
如果多個(gè)客戶端之間沒有做好數(shù)據(jù)的同步策略,就會(huì)產(chǎn)生數(shù)據(jù)不一致的情況。

效率

基于內(nèi)存的數(shù)據(jù)庫

LUA 腳本

  1. 減少網(wǎng)絡(luò)開銷,在lua腳本中可以把多個(gè)命令放在同一個(gè)腳本中運(yùn)行
  2. 原子操作:redis回想整個(gè)腳本作為一個(gè)命令執(zhí)行,中間不會(huì)被其他命令插入。腳本執(zhí)行過程中無需擔(dān)心會(huì)出現(xiàn)競(jìng)態(tài)條件。
  3. 復(fù)用性:客戶端發(fā)送的腳本會(huì)永遠(yuǎn)存儲(chǔ)在redis中。復(fù)用。
local key = "ratelimit:"..KEYS[1]

local limit = tonumber(ARGV[1])

local expireTime = ARGV[2]

local times = redis.call('incr',key)

if times == 1 then
        redis.call('expire',key,expireTime)
end

if times > limit then
        return 0
end

return 1

evalsha命令

  1. script load "return redis.call('set','lua','00')" 將腳本加入緩存。并未執(zhí)行命令
  2. 執(zhí)行evalsha命令 evalsha "id"
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 學(xué)習(xí)目標(biāo) 過期時(shí)間設(shè)置及原理分析 發(fā)布訂閱模式 Redis持久化及原理分析 Redis的內(nèi)存回收策略 Redis單...
    味道_3a01閱讀 5,349評(píng)論 2 1
  • 發(fā)布訂閱模式 列表的局限 通過隊(duì)列的rpush 和lpop 可以實(shí)現(xiàn)消息隊(duì)列(隊(duì)尾進(jìn)隊(duì)頭出),但是消費(fèi)者需要不停地...
    WEIJAVA閱讀 654評(píng)論 0 1
  • redis 內(nèi)存回收 過期策略 定時(shí)過期通過redis的expire設(shè)置過期時(shí)間,每個(gè)key都需要?jiǎng)?chuàng)建一個(gè)定時(shí)器,...
    林偉杰_059閱讀 398評(píng)論 0 0
  • Redis原理篇 1.發(fā)布 訂閱模式 1.1列表 的局限 ? 前面我們說通過隊(duì)列的 rpush 和 lpop ...
    Java小窩閱讀 399評(píng)論 0 0
  • 發(fā)布訂閱模式 列表的局限性 通過隊(duì)列的 rpush 和 lpop 可以實(shí)現(xiàn)消息隊(duì)列(隊(duì)尾進(jìn)隊(duì)頭出),但是消費(fèi)者需要...
    vincent浩哥閱讀 311評(píng)論 0 0

友情鏈接更多精彩內(nèi)容