Redis學習筆記(四):過時策略、持久化、事件

 圖片來自《Redis設計與實現》
 
Redis數據庫
    redis.server中redisServer.dbnum用於初始化生成多少個數據庫,默認 16個, Select命令選擇數據庫
    redis.client中redis.db指針指向當前正在使用的數據庫
 
1、過時策略
    設置過時時間命令 expire如  expire <key> <ttl>
 
    redisDb主要由dict和expires兩個字典組成:
            dict 爲鍵空間字典,存放該數據庫中全部的鍵對象;expires參數稱爲過時字典,存放每一個鍵對應的過時時間
            expires的鍵是一個指針,指向鍵空間中的某個鍵對象;值是long long類型的整數,存放過時時間(毫秒UNIX時間戳(chuo))
 
    兩步判斷鍵是否過時
            (1)檢查給定鍵是否存在於過時字典;存在,則得到對應的時間戳
            (2)獲取當前UNIX時間戳,二者進行比較,便可知道是否過時
 
    三個過時鍵刪除策略:
            1. 定時刪除:使用定時器(基於時間事件,無序鏈表,複雜度O(N),沒法高效處理大量時間事件),定時檢查鍵是否過時,對內存友好的策略
            2. 惰性刪除:使用鍵時纔去檢查該鍵是否過時,對CPU友好的策略
            3. 按期刪除:折中的策略,隨機檢查一部分鍵的過時時間並刪除其中過時的鍵,難點是肯定刪除執行的時長和頻率
    Redis中採用 惰性刪除 和 按期刪除 配合使用
 
    因爲兩種過時鍵刪除策略仍然可能會致使大量過時鍵堆積在內存,爲此,Redis引入的內存淘汰機制(淘汰策略共6種。最重要的是 allkeys-lru)
 
    過時鍵對RDB、AOF持久化以及複製的影響
            RDB:RDB持久化時,會檢查鍵是否過時;RDB載入時,主服務器會檢查鍵是否過時,從服務器忽略,等待主服務器同步時處理
            AOF:AOF文件寫入時忽略,直到過時鍵被刪除,才向AOF文件追加一條刪除過時鍵的命令 
                       AOF文件重寫時,會檢查鍵是否過時
            複製:主服務器每刪除一個過時鍵,則顯示地向全部從服務器發送一個DEL命令,通知從服務器刪除過時鍵
                (這個其實就是主從複製的同步流程?)
           
2、持久化
    Redis的持久化分爲兩種:RDB持久化 和 AOF持久化
 
    RDB持久化:
         一個通過壓縮的二進制文件;以鍵值對形式存儲數據庫信息,不一樣的鍵值對使用不一樣的方式保存
 
        兩個命令的區別:SAVE,BGSAVE
            save: 阻塞式RDB持久化。服務器線程執行RDB持久化操做,期間不能處理任何命令請求
            bgsave: 非阻塞式RDB持久化。 會建立一個子進程用於執行RDB持久化操做,服務器線程仍然能處理命令請求
 
         RDB文件載入
            無命令,服務器啓動時自動執行;若服務器開啓了AOF持久化功能, 會優先使用AOF文件來還原數據庫狀態
 
        RDB自動間隔性保存
            可配置服務器save選項,每隔一段時間自動執行一次bgsave命令
            
            默認知足三個條件之一,則自動執行一次bgsave命令。條件存儲在 saveparams 參數中
            除saveparams數組外,還存儲 dirty計數器  lastsave屬性;dirty用於計算累積操做次數,lastsave用於和當前時間戳比較,計算通過的時間
            三個條件: 900 1;300 10;60 10000
 
            Redis的週期性操做函數 serverCron 默認每間隔100ms執行一次,用於對正運行的服務器維護,其中就包括檢查參數條件是否知足
 
    AOF持久化:
        經過保存Redis命令來保存數據庫信息
        以Redis命令請求協議格式保存,Append Only File
 
        三步實現AOF持久化:
            (1)命令追加:每執行一個命令,就將命令追加到 aof_buf緩衝區(常量值大小64)末尾
            (2)命令寫入:服務器每次結束一個事件循環前,都會調用flushAppendOnlyFile函數,考慮是否將緩衝區數據寫入AOF文件
            (3)命令同步:與flushAppendOnlyFile函數的 appendfsync 參數決定
                            always:緩衝區寫入並同步到AOF文件
                            everysec:每秒同步一次
                            no:只寫入,由操做系統決定同步
 
        AOF的載入還原:
            (1)建立一個不帶網絡鏈接的僞客戶端(用於執行AOF文件中的Redis命令,由於命令只能在客戶端中執行)
            (2)從AOF文件中分析並讀取出一條命令
            (3)僞客戶端執行命令
            (4)循環執行2,3;直到AOF文件中的命令執行完畢
 
        AOF的文件重寫:   bgrewriteaof
            爲何須要:爲了解決隨時間和操做的增加,AOF文件的膨脹問題,處理AOF文件中命令冗餘
            實現理念:不是讀取原有AOF文件內容,而是直接讀取當前數據庫狀態,而後用一條(或多條,儘可能少的)命令去記錄鍵值對
            實現過程:
                    1.建立一個 子進程後臺執行重寫 --- 避免使用鎖的狀況下,保證數據安全;且不阻塞服務器進程
                    2.使用了AOF重寫緩衝區,服務器每執行一個命令,都將命令同時追加到AOF緩衝區和AOF重寫緩衝區
                    3.重寫工做完成後,子進程返回一個信號,父進程調用信號處理函數
                        (1)將AOF重寫緩衝區的內容寫入新AOF文件中,使新AOF文件與數據庫狀態一致
                        (2)對新AOF文件更名,原子性地覆蓋現有AOF文件,完成新舊AOF文件交替
                        注意:調用信號處理函數階段,服務器進程阻塞。( 重寫過程當中就這一處阻塞
 
    RDB與AOF兩種持久化方式的比較
    (1)RDB文件小,恢復快;可是沒法保存最近一次快照後的數據,即會丟失這部分數據
    (2)AOF文件可讀性高,數據不易丟失;可是文件體積大,恢復時間長
    Redis 4.0 開始支持 RDB 和 AOF 的混合持久化
 
   
3、事件
         Redis 服務器是一個事件驅動程序
         單線程運行, I/O多路複用來監聽多個套接字;有兩種事件(文件事件和時間事件)
 
        文件事件:對套接字進行操做的抽象;有可讀事件、可寫事件;文件事件擁有基於Reactor模式的文件事件處理器。           
  文件事件處理器: 套接字 + I/O多路複用程序 + 文件事件分派器 + 事件處理器
  常見事件處理器:鏈接應答處理器,命令請求處理器,命令回覆處理器。(依次爲鏈接、接收命令、處理命令回覆)

  時間事件:給定的時間點執行類操做的抽象;有定時事件、週期性事件redis

  時間事件實現: Redis 將全部時間事件都放在一個無序鏈表(不按when屬性大小排序)中,經過遍歷整個鏈表查找出已到達的時間事件,並調用相應的事件處理器。數據庫

  時間事件:三個參數(id,when,timeProc);典型事件:serverCron數組

 
        事件調度與執行
def aeProcessEvents():
# 獲取到達時間離當前時間最接近的時間事件
time_event = aeSearchNearestTimer()
# 計算最接近的時間事件距離到達還有多少毫秒
remaind_ms = time_event.when - unix_ts_now()
# 若是事件已到達,那麼 remaind_ms 的值可能爲負數,將它設爲 0
if remaind_ms < 0:
remaind_ms = 0
# 根據 remaind_ms 的值,建立 timeval
timeval = create_timeval_with_ms(remaind_ms)
# 阻塞並等待文件事件產生,最大阻塞時間由傳入的 timeval 決定
aeApiPoll(timeval)
# 處理全部已產生的文件事件
procesFileEvents()
# 處理全部已到達的時間事件
processTimeEvents()

 

相關文章
相關標籤/搜索