Redis效能調優

2022-06-26 08:15:08 字數 3735 閱讀 1240

1. 估算redis記憶體使用量

以非數字的字串鍵值對為例,假設key和value的長度均為12個位元組,則內部使用的編碼方式為embstr。共計90000個鍵值對占用的空間

redis中儲存鍵值對使用字典,字典內部使用雜湊表陣列,陣列的每個元素dictentry中共有三個指標(指向鍵的指標,指向值的指標,指向下乙個節點的指標),在64位系統中,每個指標占用8位元組,則共計24個位元組,向上取2的整數冪,則分配32個位元組。

乙個key,使用sds儲存,資料大小12位元組,len+alloc+flags+空字元共4個位元組(3.2版本之後),共計12+4=16個位元組

乙個value,外層使用物件redisobject並指向乙個sds(存放值內容)。物件記憶體占用16個位元組,sds需要16個位元組

綜上,乙個dictentry使用的記憶體總共為 32 + 16 + 16 + 16 = 80位元組。

儲存90000個鍵值對需要的bucket陣列大小為90000向上取2的整數冪,即131072;每個bucket元素占用8位元組(因為內部儲存的指標)。

儲存90000個鍵值對占用的總記憶體:90000*80 + 131072*8 = 82488576。

當儲存的鍵值對長度由12位元組增加到13位元組,對應的sds變成17位元組,jemalloc分配32個位元組,因此每個dictentry占用的位元組數變成112位元組。則儲存90000個的記憶體占用變為 90000*12 + 131072*8  = 11128576。

2. 優化記憶體占用

1. 利用jemalloc特性進行優化

jemalloc是redis的預設記憶體分配器,在64位系統中,將記憶體空間劃分成小、大、巨大三個範圍;每個範圍又劃分為許多小的記憶體塊單位,當redis儲存資料時,選擇適合的記憶體塊進行儲存。譬如儲存130位元組的物件,jemalloc會將其放入到160位元組的記憶體單元中。

2. 使用整型/長整型

redis儲存字串的編碼型別有三種,當字串為數字時,使用int(8位元組)儲存代替字串,可以節省很多空間。

3. 共享物件

共享物件可以減少物件的建立,包括redisobject的建立。redis中的共享物件目前只有0-9999,可以通過redis_shared_integers引數提高,譬如調整到20000,則0-19999都可以共享

4.縮短鍵值對的儲存長度

大鍵值對,延長寫入和讀取耗時、延長持久化需要時間,延長網路傳輸時間,並且占用記憶體多,更容易觸發記憶體淘汰機制。盡量縮短儲存長度,必要時進行壓縮和序列化

redis的servercron函式定期清除過期鍵,節約記憶體占用,避免鍵值對過多堆積,頻繁觸發記憶體淘汰機制

在64位系統中,預設沒有設定最大記憶體,配置項maxmemory被注釋了。當物理記憶體不足時,使用磁碟作為虛擬記憶體,將物理記憶體中的部分資料存放到虛擬記憶體,這個操作會阻塞redis程序。當設定了最大記憶體,當超出限制時,觸發記憶體淘汰。記憶體淘汰策略在redis4.0後有8種,主要用到以下原理

缺點是類似全表掃瞄時,會將鍊錶資料汙染

缺點是短時間內大量訪問的資料很難刪除

1. redis快取淘汰策略

noeviction:不淘汰任何資料,當記憶體不足時,新增操作會報錯,redis 預設記憶體淘汰策略;

allkeys-lru:淘汰整個鍵值中最久未使用的鍵值;

allkeys-random:隨機淘汰任意鍵值;

volatile-lru:淘汰所有設定了過期時間的鍵值中最久未使用的鍵值;

volatile-random:隨機淘汰設定了過期時間的任意鍵值;

volatile-ttl:優先淘汰更早過期的鍵值;

volatile-lfu:淘汰所有設定了過期時間的鍵值中,最少使用的鍵值;

allkeys-lfu:淘汰整個鍵值中最少使用的鍵值;

刪除大鍵值對比較耗時,造成主線程的阻塞,為此將刪除的操作放在子執行緒中。共有四項配置:

redis大部分的讀寫命令的時間複雜度在o(1)到o(n)之間。對於o(n)的命令,需要謹慎使用,如果執行時間過長,將會阻塞redis

使用slowlog命令找出高耗時的redis命令。慢查詢的配置項:

servercron函式每100毫秒執行一次過期掃瞄。隨機抽取過期鍵字典中的20個鍵,刪除其中的已經過期的鍵,判斷過期鍵的比例是否超過25%,重複執行此流程。如果一次掃瞄中刪除了大量過期鍵,將會造成阻塞。

在設定過期時間時,加入隨機數。

redis4.0之後,加入混合持久化功能,結合了rdb和aof。在寫入時,將當前資料以rdb的形式寫入檔案的開頭,後續的操作命令以aof的格式存入檔案;在載入時,先載入rdb檔案,再載入aof命令。

rdb持久化,可能存在一定時間內的資料丟失。aof持久化,檔案較大時執行較慢,影響啟動速度。在非必須持久化操作時,可以關閉持久化,避免間歇性的卡頓(servercron函式週期性執行持久化操作)

使用redis連線池,減少網路傳輸次數和非必要呼叫指令。

import

redis.clients.jedis.jedispool;

import redis.clients.jedis.jedispoolconfig;

redis分布式架構有:

詳細:使用物理機非虛擬機器。虛擬機器和物理機共享物理網口,並且一台物理機可能有多個虛擬機器執行,在記憶體占用和網路延遲上效能較差

linux預設開啟,支援大記憶體頁2mb分配。

開啟thp之後,fork速度變慢,fork之後每個記憶體頁從4kb變成2mb,大幅增加重寫期間父程序記憶體消耗。同時每次寫命令引起的複製記憶體頁單位放大了512倍,會拖慢寫操作的執行時間,導致大量寫操作慢查詢。

產生條件:1. 大量快取同時失效 2.大量併發請求訪問失效快取 導致資料庫宕機

解決方案:過期時間設定加入隨機數

快取中沒有(過期),但資料庫中存在資料。此時大量併發請求訪問這部分資料,資料庫壓力陡增。快取雪崩是大量的快取擊穿。

解決方案:

1.設定熱點資料永不過期

2.介面限流熔斷和降級

3.布隆過濾器。bloomfilter類似乙個雜湊表但是不存key,快速判斷乙個元素是否在集合中。使用多個雜湊函式計算入參key得到座標,在乙個bit陣列中儲存對應位置為1。查詢時只要有乙個位置為0則不存在,但都為1也有可能不存在。使用多個雜湊函式是基於雜湊衝突的考量。

4.加鎖。這種情況,只允許能有乙個執行緒查詢資料庫,獲取結果後將結果放入快取,其餘執行緒則直接訪問快取

public string getdata(string key) throws

exception

else

}else

}return

data;

}

快取和資料庫中都沒有某資料,但有大量的併發請求查詢這些資料。導致資料庫宕機,主要考慮是漏洞攻擊

解決方案:

1. 介面層加校驗,譬如使用者鑑權

2. 將對應的key的value設定為null存入快取

Redis效能調優

向大神學習!儘管redis是乙個非常快速的記憶體資料儲存媒介,也並不代表redis不會產生效能問題。前文中提到過,redis採用單執行緒模型,所有的命令都是由乙個執行緒序列執行的,所以當某個命令執行耗時較長時,會拖慢其後的所有命令,這使得redis對每個任務的執行效率更加敏感。針對redis的效能優...

調優 Nginx效能調優

一.nginx優化配置 1.主配置檔案優化 注 部分配置詳解 worker processes 8 nginx程序數,建議按照cpu數目來指定,一般為它的倍數。worker cpu affinity 00000001 00000010 00000100 00001000 00010000 00100...

Spark效能調優 JVM調優

通過一張圖讓你明白以下四個問題 1.jvm gc機制,堆記憶體的組成 2.spark的調優為什麼會和jvm的調優會有關聯?因為scala也是基於jvm執行的語言 3.spark中oom產生的原因 4.如何在jvm這個層面上來對spark進行調優 補充 spark程式執行時 jvm堆記憶體分配比例 r...