您好,登錄后才能下訂單哦!
循例介紹一下了,redis是內(nèi)存數(shù)據(jù)庫,是簡單的key-value結(jié)構(gòu),也是nosql數(shù)據(jù)庫,因?yàn)榻Y(jié)構(gòu)簡單,而且用的是內(nèi)存,所以速度非常之快.至于問有多快?大家知道以前的機(jī)械硬盤,單盤速度其實(shí)也還好,而內(nèi)存的讀寫速度是機(jī)械硬盤的6萬倍.所以,redis比硬盤有多快,可見一斑了.當(dāng)然現(xiàn)在都用固態(tài)硬盤,情況還是比以前好不少的.這里不再詳細(xì)類比,知道是這回事就好.
安裝
================================
好了,當(dāng)然先說安裝了,安裝redis很簡單,先說明,我們服務(wù)器都是linux.
首先要說明一下,內(nèi)存數(shù)據(jù)庫并不代表完全不用硬盤空間,因?yàn)橐话銥榱藬?shù)據(jù)安全,配置上會備份一定數(shù)據(jù)到硬盤的,所以還是得準(zhǔn)備一定的硬盤空間.
下載地址:
wget?"http://download.redis.io/releases/redis-3.2.0.tar.gz"
是編譯版本,現(xiàn)在都出到3.2了,不過版本差異不大,低版本只是不支持集群或主從而已,實(shí)際上功能沒差.
安裝時(shí)有依賴包提示就記得yum下,一般就C語言庫相關(guān)的,這些大部分在初始化系統(tǒng)就必須裝上的了.
下面來看安裝方法,很簡單:
#解壓編譯包 tar?xzf?redis-3.2.0.tar.gz #進(jìn)入解壓后的文件夾 cd?redis-3.2.0 #編譯安裝 make make?install #順便說說,如果你想安裝在自定義目錄也是可以的 make?prefix=(你的目錄)?install
當(dāng)make install命令執(zhí)行完成后,會在/usr/local/bin目錄下生成幾個(gè)可執(zhí)行文件,它們的作用如下:
redis-server: ? ?Redis服務(wù)器的daemon啟動(dòng)程序
redis-cli: ? ? ? Redis命令行操作工具。也可以用telnet根據(jù)其純文本協(xié)議來操作
redis-benchmark: Redis性能測試工具,測試Redis在當(dāng)前系統(tǒng)下的讀寫性能
redis-check-aof: 數(shù)據(jù)修復(fù)
redis-check-dump:檢查導(dǎo)出工具?
安裝完了,就要看配置了,配置文件名可以隨便改,位置也不固定要放什么位置,因?yàn)閱?dòng)的時(shí)候可以指定配置文件啟動(dòng).
還記得編譯目錄嗎?里面就有配置文件模板,復(fù)制過來就可以用了,當(dāng)然了,按照你自己的需求改一下還是有必要的,
cd?redis-3.2.0 ll?*.conf -rw-rw-r--?1?root?root?45390?May??6?15:11?redis.conf -rw-rw-r--?1?root?root??7109?May??6?15:11?sentinel.conf
一個(gè)是redis的配置文件,一個(gè)是哨兵,屬于redis集群應(yīng)用的配置文件
配置太多,我們先看一些重點(diǎn):
cat?redis.conf #允許后臺運(yùn)行 daemonize??yes #設(shè)置端口,最好是非默認(rèn)端口 port?6666 #綁定登錄IP,安全考慮,最好是內(nèi)網(wǎng) bind?10.10.2.21 #命名并指定當(dāng)前redis的PID路徑,用以區(qū)分多個(gè)redis pidfile?/data/redis/data/config/redis_6666.pid #命名并指定當(dāng)前redis日志文件路徑 logfile?"/data/redis/data/logs/redis_6666.log" #指定RDB文件名,用以備份數(shù)據(jù)到硬盤并區(qū)分不同redis,當(dāng)使用內(nèi)存超過可用內(nèi)存的45%時(shí)觸發(fā)快照功能 dbfilename?dump_6666.rdb #指定當(dāng)前redis的根目錄,用來存放RDB/AOF文件 dir?/data/redis/data #當(dāng)前redis的認(rèn)證密鑰,redis運(yùn)行速度非常快,這個(gè)密碼要足夠強(qiáng)大 requirepass?gggggggGGGGGGGGG999999999 #當(dāng)前redis的最大容量限制,建議設(shè)置為可用內(nèi)存的45%內(nèi),最高能設(shè)置為系統(tǒng)可用內(nèi)存的95% #可用config?set?maxmemory?去在線修改,但重啟失效,需要使用config?rewrite命令去刷新配置文件 maxmemory?1024000000 #LRU的策略,有四種,看情況選擇 maxmemory-policy?allkeys-lru #關(guān)閉自動(dòng)持久化操作,默認(rèn)情況下RDB自動(dòng)持久化是開啟的,會定時(shí)自動(dòng)壓縮保存redis的全量數(shù)據(jù). #由于redis是單線程操作的,這個(gè)操作無疑比較耗費(fèi)資源并阻塞操作,有些只做緩存的環(huán)境也不見得數(shù)據(jù)有多重要. #save?"" #默認(rèn)情況下AOF持久化方式是關(guān)閉的,需要手動(dòng)開啟,和RDB各有特點(diǎn),相對RDB沒那么阻塞操作. #appendonly?yes #在開啟AOF之后,需要設(shè)置下面兩個(gè)參數(shù),避免AOF文件不斷增大,影響后續(xù)操作. #auto-aof-rewrite-percentage?100 #auto-aof-rewrite-min-size?64mb
詳細(xì)解析如下:
-----------------------------------------------------------------------------------
1 daemonize ?no
默認(rèn)情況下,redis 不是在后臺運(yùn)行的,如果需要在后臺運(yùn)行,把該項(xiàng)的值更改為yes。
2 pidfile ?/var/run/redis.pid
當(dāng)Redis 在后臺運(yùn)行的時(shí)候,Redis 默認(rèn)會把pid 文件放在/var/run/redis.pid,你可以配置到其他地址。當(dāng)運(yùn)行多個(gè)redis 服務(wù)時(shí),需要指定不同的pid 文件和端口
3 port
監(jiān)聽端口,默認(rèn)為6379
4 #bind 127.0.0.1
指定Redis 只接收來自于該IP 地址的請求,如果不進(jìn)行設(shè)置,那么將處理所有請求,在生產(chǎn)環(huán)境中為了安全最好設(shè)置該項(xiàng)。默認(rèn)注釋掉,不開啟
5 timeout 0
設(shè)置客戶端連接時(shí)的超時(shí)時(shí)間,單位為秒。當(dāng)客戶端在這段時(shí)間內(nèi)沒有發(fā)出任何指令,那么關(guān)閉該連接
6 tcp-keepalive 0
指定TCP連接是否為長連接,"偵探"信號有server端維護(hù)。默認(rèn)為0.表示禁用
7 loglevel notice
log 等級分為4 級,debug,verbose, notice, 和warning。生產(chǎn)環(huán)境下一般開啟notice
8 logfile stdout
配置log 文件地址,默認(rèn)使用標(biāo)準(zhǔn)輸出,即打印在命令行終端的窗口上,修改為日志文件目錄
9 databases 16
設(shè)置數(shù)據(jù)庫的個(gè)數(shù),可以使用SELECT 命令來切換數(shù)據(jù)庫。默認(rèn)使用的數(shù)據(jù)庫是0號庫。默認(rèn)16個(gè)庫
10?
save 900 1
save 300 10
save 60 10000
rdb自動(dòng)持久化參數(shù),保存數(shù)據(jù)快照的頻率,即將數(shù)據(jù)持久化到dump.rdb文件中的頻度。用來描述"在多少秒期間至少多少個(gè)變更操作"觸發(fā)snapshot數(shù)據(jù)保存動(dòng)作,
????默認(rèn)設(shè)置,意思是:
????if(在60 秒之內(nèi)有10000 個(gè)keys 發(fā)生變化時(shí)){
????進(jìn)行鏡像備份
????}else if(在300 秒之內(nèi)有10 個(gè)keys 發(fā)生了變化){
????進(jìn)行鏡像備份
????}else if(在900 秒之內(nèi)有1 個(gè)keys 發(fā)生了變化){
????進(jìn)行鏡像備份
????}
????如果設(shè)置為空,例如:
????save ""
????即關(guān)閉rdb自動(dòng)持久化.
????默認(rèn)情況下RDB自動(dòng)持久化是開啟的,會定時(shí)自動(dòng)壓縮保存redis的全量數(shù)據(jù),但是由于redis是單線程操作的,這個(gè)操作無疑比較耗費(fèi)資源而阻塞操作,有些只做緩存的環(huán)境也不見得數(shù)據(jù)有多重要,關(guān)閉也是可以的.
????注意:手動(dòng)bgsave命令還是可以使用的,還需要留意dir參數(shù)的文件是否存在,如果存在,重啟后會把文件的數(shù)據(jù)加載進(jìn)來
11 stop-writes-on-bgsave-error yes
當(dāng)持久化出現(xiàn)錯(cuò)誤時(shí),是否依然繼續(xù)進(jìn)行工作,是否終止所有的客戶端write請求。默認(rèn)設(shè)置"yes"表示終止,一旦snapshot數(shù)據(jù)保存故障,那么此server為只讀服務(wù)。如果為"no",那么此次snapshot將失敗,但下一次snapshot不會受到影響,不過如果出現(xiàn)故障,數(shù)據(jù)只能恢復(fù)到"最近一個(gè)成功點(diǎn)"
12 rdbcompression yes
在進(jìn)行數(shù)據(jù)鏡像備份時(shí),是否啟用rdb文件壓縮手段,默認(rèn)為yes。壓縮可能需要額外的cpu開支,不過這能夠有效的減小rdb文件的大,有利于存儲/備份/傳輸/數(shù)據(jù)恢復(fù)
13 rdbchecksum yes
讀取和寫入時(shí)候,會損失10%性能
14 rdbchecksum yes
是否進(jìn)行校驗(yàn)和,是否對rdb文件使用CRC64校驗(yàn)和,默認(rèn)為"yes",那么每個(gè)rdb文件內(nèi)容的末尾都會追加CRC校驗(yàn)和,利于第三方校驗(yàn)工具檢測文件完整性
14 dbfilename dump.rdb
鏡像快照備份文件的文件名,默認(rèn)為 dump.rdb,當(dāng)使用內(nèi)存超過可用內(nèi)存的45%時(shí)觸發(fā)快照功能
15 dir ./
數(shù)據(jù)庫鏡像備份的文件rdb/AOF文件放置的路徑。這里的路徑跟文件名要分開配置是因?yàn)镽edis 在進(jìn)行備份時(shí),先會將當(dāng)前數(shù)據(jù)庫的狀態(tài)寫入到一個(gè)臨時(shí)文件中,等備份完成時(shí),再把該臨時(shí)文件替換為上面所指定的文件,而這里的臨時(shí)文件和上面所配置的備份文件都會放在這個(gè)指定的路徑當(dāng)中
16 # slaveof <masterip> <masterport>
設(shè)置該數(shù)據(jù)庫為其他數(shù)據(jù)庫的從數(shù)據(jù)庫,并為其指定master信息。
17 masterauth
當(dāng)主數(shù)據(jù)庫連接需要密碼驗(yàn)證時(shí),在這里指定
18 slave-serve-stale-data yes
當(dāng)主master服務(wù)器掛機(jī)或主從復(fù)制在進(jìn)行時(shí),是否依然可以允許客戶訪問可能過期的數(shù)據(jù)。在"yes"情況下,slave繼續(xù)向客戶端提供只讀服務(wù),有可能此時(shí)的數(shù)據(jù)已經(jīng)過期;在"no"情況下,任何向此server發(fā)送的數(shù)據(jù)請求服務(wù)(包括客戶端和此server的slave)都將被告知"error"
19 slave-read-only yes
slave是否為"只讀",強(qiáng)烈建議為"yes"
20 # repl-ping-slave-period 10
slave向指定的master發(fā)送ping消息的時(shí)間間隔(秒),默認(rèn)為10
21 # repl-timeout 60
slave與master通訊中,最大空閑時(shí)間,默認(rèn)60秒.超時(shí)將導(dǎo)致連接關(guān)閉
22 repl-disable-tcp-nodelay no
slave與master的連接,是否禁用TCP nodelay選項(xiàng)。"yes"表示禁用,那么socket通訊中數(shù)據(jù)將會以packet方式發(fā)送(packet大小受到socket buffer限制)。
可以提高socket通訊的效率(tcp交互次數(shù)),但是小數(shù)據(jù)將會被buffer,不會被立即發(fā)送,對于接受者可能存在延遲。"no"表示開啟tcp nodelay選項(xiàng),任何數(shù)據(jù)都會被立即發(fā)送,及時(shí)性較好,但是效率較低,建議設(shè)為no
23 slave-priority 100
適用Sentinel模塊(unstable,M-S集群管理和監(jiān)控),需要額外的配置文件支持。slave的權(quán)重值,默認(rèn)100.當(dāng)master失效后,Sentinel將會從slave列表中找到權(quán)重值最低(>0)的slave,并提升為master。如果權(quán)重值為0,表示此slave為"觀察者",不參與master選舉
24 # requirepass foobared
設(shè)置客戶端連接后進(jìn)行任何其他指定前需要使用的密碼。警告:因?yàn)閞edis 速度相當(dāng)快,所以在一臺比較好的服務(wù)器下,一個(gè)外部的用戶可以在一秒鐘進(jìn)行150K 次的密碼嘗試,這意味著你需要指定非常非常強(qiáng)大的密碼來防止被破解。
25 # rename-command CONFIG 3ed984507a5dcd722aeade310065ce5d ? ?(方式:MD5('CONFIG^!'))
重命名指令,對于一些與"server"控制有關(guān)的指令,可能不希望遠(yuǎn)程客戶端(非管理員用戶)鏈接隨意使用,那么就可以把這些指令重命名為"難以閱讀"的其他字符串
26 # maxclients 10000
限制同時(shí)連接的客戶數(shù)量。當(dāng)連接數(shù)超過這個(gè)值時(shí),redis 將不再接收其他連接請求,客戶端嘗試連接時(shí)將收到error 信息。默認(rèn)為10000,要考慮系統(tǒng)文件描述符限制,不宜過大,浪費(fèi)文件描述符,具體多少根據(jù)具體情況而定
27 # maxmemory <bytes>
redis-cache所能使用的最大內(nèi)存(bytes),默認(rèn)為0,表示"無限制",最終由OS物理內(nèi)存大小決定(如果物理內(nèi)存不足,有可能會使用swap)。此值盡量不要超過機(jī)器的物理內(nèi)存尺寸,從性能和實(shí)施的角度考慮,可以為物理內(nèi)存3/4。此配置需要和"maxmemory-policy"配合使用,當(dāng)redis中內(nèi)存數(shù)據(jù)達(dá)到maxmemory時(shí),觸發(fā)"清除策略"。在"內(nèi)存不足"時(shí),任何write操作(比如set,lpush等)都會觸發(fā)"清除策略"的執(zhí)行。在實(shí)際環(huán)境中,建議redis的所有物理機(jī)器的硬件配置保持一致(內(nèi)存一致),同時(shí)確保master/slave中"maxmemory""policy"配置一致??梢允褂每蛻舳嗣頲onfig set maxmemory 去在線修改值,這個(gè)命令是立即生效的,但會在重啟后會失效,需要使用config rewrite命令去刷新配置文件
當(dāng)內(nèi)存滿了的時(shí)候,如果還接收到set 命令,redis 將先嘗試剔除設(shè)置過expire 信息的key,而不管該key 的過期時(shí)間還沒有到達(dá)。在刪除時(shí),
將按照過期時(shí)間進(jìn)行刪除,最早將要被過期的key 將最先被刪除。如果帶有expire 信息的key 都刪光了,內(nèi)存還不夠用,那么將返回錯(cuò)誤。這樣,redis 將不再接收寫請求,只接收get 請求。maxmemory 的設(shè)置比較適合于把redis 當(dāng)作于類似memcached的緩存來使用。
28 # maxmemory-policy volatile-lru
內(nèi)存不足"時(shí),數(shù)據(jù)清除策略,默認(rèn)為"volatile-lru"。
volatile-lru ?->對"過期集合"中的數(shù)據(jù)采取LRU(近期最少使用)算法.如果對key使用"expire"指令指定了過期時(shí)間,那么此key將會被添加到"過期集合"中。將已經(jīng)過期/LRU的數(shù)據(jù)優(yōu)先移除.如果"過期集合"中全部移除仍不能滿足內(nèi)存需求,將OOM.
allkeys-lru ->對所有的數(shù)據(jù),采用LRU算法
volatile-random ->對"過期集合"中的數(shù)據(jù)采取"隨即選取"算法,并移除選中的K-V,直到"內(nèi)存足夠"為止. 如果如果"過期集合"中全部移除全部移除仍不能滿足,將OOM
allkeys-random ->對所有的數(shù)據(jù),采取"隨機(jī)選取"算法,并移除選中的K-V,直到"內(nèi)存足夠"為止
volatile-ttl ->對"過期集合"中的數(shù)據(jù)采取TTL算法(最小存活時(shí)間),移除即將過期的數(shù)據(jù).
noeviction ->不做任何干擾操作,直接返回OOM異常
另外,如果數(shù)據(jù)的過期不會對"應(yīng)用系統(tǒng)"帶來異常,且系統(tǒng)中write操作比較密集,建議采取"allkeys-lru"
29 # maxmemory-samples 3
默認(rèn)值3,上面LRU和最小TTL策略并非嚴(yán)謹(jǐn)?shù)牟呗裕谴蠹s估算的方式,因此可以選擇取樣值以便檢查
29 appendonly no
aof持久化開關(guān),默認(rèn)情況下,redis 會在后臺異步的把數(shù)據(jù)庫鏡像備份到磁盤,但是該備份是非常耗時(shí)的,而且備份也不能很頻繁。所以redis 提供了另外一種更加高效的數(shù)據(jù)庫備份及災(zāi)難恢復(fù)方式。開啟append only 模式之后,redis 會把所接收到的每一次寫操作請求都追加到appendonly.aof 文件中,當(dāng)redis 重新啟動(dòng)時(shí),會從該文件恢復(fù)出之前的狀態(tài)。但是這樣會造成appendonly.aof 文件過大,所以redis 還支持了BGREWRITEAOF 指令,對appendonly.aof 進(jìn)行重新整理。如果不經(jīng)常進(jìn)行數(shù)據(jù)遷移操作,推薦生產(chǎn)環(huán)境下的做法為關(guān)閉鏡像,開啟appendonly.aof,同時(shí)可以選擇在訪問較少的時(shí)間每天對appendonly.aof 進(jìn)行重寫一次。
另外,對master機(jī)器,主要負(fù)責(zé)寫,建議使用AOF,對于slave,主要負(fù)責(zé)讀,挑選出1-2臺開啟AOF,其余的建議關(guān)閉
30 # appendfilename appendonly.aof
aof文件名字,默認(rèn)為appendonly.aof
31 appendfsync everysec
設(shè)置對appendonly.aof 文件進(jìn)行同步的頻率。always 表示每次有寫操作都進(jìn)行同步,everysec(默認(rèn)) 表示對寫操作進(jìn)行累積,每秒同步一次。no不主動(dòng)fsync,由OS自己來完成。這個(gè)需要根據(jù)實(shí)際業(yè)務(wù)場景進(jìn)行配置
32 no-appendfsync-on-rewrite no
在aof rewrite期間,是否對aof新記錄的append暫緩使用文件同步策略,主要考慮磁盤IO開支和請求阻塞時(shí)間。默認(rèn)為no,表示"不暫緩",新的aof記錄仍然會被立即同步
33 auto-aof-rewrite-percentage 100
當(dāng)Aof log增長超過指定比例時(shí),重寫log file, 設(shè)置為0表示不自動(dòng)重寫Aof 日志,重寫是為了使aof體積保持最小,而確保保存最完整的數(shù)據(jù)。相對于“上一次”rewrite,本次rewrite觸發(fā)時(shí)aof文件應(yīng)該增長的百分比。每一次rewrite之后,redis都會記錄下此時(shí)“新aof”文件的大小(例如A),那么當(dāng)aof文件增長到A*(1 + p)之后 , 觸發(fā)下一次rewrite,每一次aof記錄的添加,都會檢測當(dāng)前aof文件的尺寸。?
34 auto-aof-rewrite-min-size 64mb
觸發(fā)aof rewrite的最小文件尺寸,aof文件rewrite觸發(fā)的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才會觸發(fā)rewrite,默認(rèn)“64mb”
35 lua-time-limit 5000
lua腳本運(yùn)行的最大時(shí)間
36 slowlog-log-slower-than 10000
"慢操作日志"記錄,單位:微秒(百萬分之一秒,1000 * 1000),如果操作時(shí)間超過此值,將會把command信息"記錄"起來.(內(nèi)存,非文件)。其中"操作時(shí)間"不包括網(wǎng)絡(luò)IO開支,只包括請求達(dá)到server后進(jìn)行"內(nèi)存實(shí)施"的時(shí)間."0"表示記錄全部操作
37 slowlog-max-len 128
"慢操作日志"保留的最大條數(shù),"記錄"將會被隊(duì)列化,如果超過了此長度,舊記錄將會被移除??梢酝ㄟ^"SLOWLOG <subcommand> args"查看慢記錄的信息(SLOWLOG get 10,SLOWLOG reset)
38
?hash-max-ziplist-entries 512
hash類型的數(shù)據(jù)結(jié)構(gòu)在編碼上可以使用ziplist和hashtable。ziplist的特點(diǎn)就是文件存儲(以及內(nèi)存存儲)所需的空間較小,在內(nèi)容較小時(shí),性能和hashtable幾乎一樣.因此redis對hash類型默認(rèn)采取ziplist。如果hash中條目的條目個(gè)數(shù)或者value長度達(dá)到閥值,將會被重構(gòu)為hashtable。
這個(gè)參數(shù)指的是ziplist中允許存儲的最大條目個(gè)數(shù),,默認(rèn)為512,建議為128
hash-max-ziplist-value 64
ziplist中允許條目value值最大字節(jié)數(shù),默認(rèn)為64,建議為1024
39?
list-max-ziplist-entries 512
list-max-ziplist-value 64
對于list類型,將會采取ziplist,linkedlist兩種編碼類型。解釋同上。
40 set-max-intset-entries 512
intset中允許保存的最大條目個(gè)數(shù),如果達(dá)到閥值,intset將會被重構(gòu)為hashtable
41?
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
zset為有序集合,有2中編碼類型:ziplist,skiplist。因?yàn)?排序"將會消耗額外的性能,當(dāng)zset中數(shù)據(jù)較多時(shí),將會被重構(gòu)為skiplist。
42 activerehashing yes
是否開啟頂層數(shù)據(jù)結(jié)構(gòu)的rehash功能,如果內(nèi)存允許,請開啟。rehash能夠很大程度上提高K-V存取的效率
43?
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
客戶端buffer控制。在客戶端與server進(jìn)行的交互中,每個(gè)連接都會與一個(gè)buffer關(guān)聯(lián),此buffer用來隊(duì)列化等待被client接受的響應(yīng)信息。如果client不能及時(shí)的消費(fèi)響應(yīng)信息,那么buffer將會被不斷積壓而給server帶來內(nèi)存壓力.如果buffer中積壓的數(shù)據(jù)達(dá)到閥值,將會導(dǎo)致連接被關(guān)閉,buffer被移除。
buffer控制類型包括:normal -> 普通連接;slave ->與slave之間的連接;pubsub ->pub/sub類型連接,此類型的連接,往往會產(chǎn)生此種問題;因?yàn)閜ub端會密集的發(fā)布消息,但是sub端可能消費(fèi)不足.
指令格式:client-output-buffer-limit <class> <hard> <soft> <seconds>",其中hard表示buffer最大值,一旦達(dá)到閥值將立即關(guān)閉連接;
soft表示"容忍值",它和seconds配合,如果buffer值超過soft且持續(xù)時(shí)間達(dá)到了seconds,也將立即關(guān)閉連接,如果超過了soft但是在seconds之后,buffer數(shù)據(jù)小于了soft,連接將會被保留.
其中hard和soft都設(shè)置為0,則表示禁用buffer控制.通常hard值大于soft.
44 hz 10
Redis server執(zhí)行后臺任務(wù)的頻率,默認(rèn)為10,此值越大表示redis對"間歇性task"的執(zhí)行次數(shù)越頻繁(次數(shù)/秒)。"間歇性task"包括"過期集合"檢測、關(guān)閉"空閑超時(shí)"的連接等,此值必須大于0且小于500。此值過小就意味著更多的cpu周期消耗,后臺task被輪詢的次數(shù)更頻繁。此值過大意味著"內(nèi)存敏感"性較差。建議采用默認(rèn)值。
45?
# include /path/to/local.conf
# include /path/to/other.conf
額外載入配置文件。
#可以通過下面命令去在線修改參數(shù),但重啟失效, config?set?maxmemory?6442450944 #使用下面命令寫進(jìn)配置文件 config?rewrite
------------------------------------------------------------------------------------
然后來看看啟動(dòng)
#使用配置文件啟動(dòng)redis redis-server?/(自定義路徑)/redis.conf #然后測試下能不能用 redis-cli?-p?6379(指定的端口號,可不填,即默認(rèn))?-a?"密碼"?[-c?"命令"(可選,非交互式操作)] set?mykey??"hi" ok get?mykey "hi" #關(guān)閉redis redis-cli?shutdown #或 kill?pid
注意:在重啟服務(wù)器之前,需要在Redis-cli工具上輸入shutdown save命令,意思是強(qiáng)制讓Redis數(shù)據(jù)庫執(zhí)行保存操作并關(guān)閉Redis服務(wù),這樣做能保證在執(zhí)行Redis關(guān)閉時(shí)不丟失任何數(shù)據(jù)。
操作
?首先來看看命令行終端輸出模式操作介紹:
#在Shell命令行下啟動(dòng)Redis客戶端工具。 redis-cli?-h?127.0.0.1?-p?6379?-a?'********'?? #清空當(dāng)前選擇的數(shù)據(jù)庫,以便于對后面示例的理解。 redis?127.0.0.1:6379>?flushdb OK #添加String類型的模擬數(shù)據(jù)。 redis?127.0.0.1:6379>?set?mykey?2 OK redis?127.0.0.1:6379>?set?mykey2?"hello" OK #添加Set類型的模擬數(shù)據(jù)。 redis?127.0.0.1:6379>?sadd?mysetkey?1?2?3 (integer)?3 #添加Hash類型的模擬數(shù)據(jù)。 redis?127.0.0.1:6379>?hset?mmtest?username?"stephen" (integer)?1 #根據(jù)參數(shù)中的模式,獲取當(dāng)前數(shù)據(jù)庫中符合該模式的所有key,從輸出可以看出,該命令在執(zhí)行時(shí)并不區(qū)分與Key關(guān)聯(lián)的Value類型。 redis?127.0.0.1:6379>?keys?my* 1)?"mysetkey" 2)?"mykey" 3)?"mykey2" #刪除了兩個(gè)Keys。 redis?127.0.0.1:6379>?del?mykey?mykey2 (integer)?2 #查看一下剛剛刪除的Key是否還存在,從返回結(jié)果看,mykey確實(shí)已經(jīng)刪除了。 redis?127.0.0.1:6379>?exists?mykey (integer)?0 #查看一下沒有刪除的Key,以和上面的命令結(jié)果進(jìn)行比較。 redis?127.0.0.1:6379>?exists?mysetkey (integer)?1 #將當(dāng)前數(shù)據(jù)庫中的mysetkey鍵移入到ID為1的數(shù)據(jù)庫中,從結(jié)果可以看出已經(jīng)移動(dòng)成功。 redis?127.0.0.1:6379>?move?mysetkey?1 (integer)?1 #打開ID為1的數(shù)據(jù)庫。 redis?127.0.0.1:6379>?select?1 OK #查看一下剛剛移動(dòng)過來的Key是否存在,從返回結(jié)果看已經(jīng)存在了。 redis?127.0.0.1:6379[1]>?exists?mysetkey (integer)?1 #在重新打開ID為0的缺省數(shù)據(jù)庫。 redis?127.0.0.1:6379[1]>?select?0 OK #查看一下剛剛移走的Key是否已經(jīng)不存在,從返回結(jié)果看已經(jīng)移走。 redis?127.0.0.1:6379>?exists?mysetkey (integer)?0 #準(zhǔn)備新的測試數(shù)據(jù)。???? redis?127.0.0.1:6379>?set?mykey?"hello" OK #將mykey改名為mykey1 redis?127.0.0.1:6379>?rename?mykey?mykey1 OK #由于mykey已經(jīng)被重新命名,再次獲取將返回nil。 redis?127.0.0.1:6379>?get?mykey (nil) #通過新的鍵名獲取。 redis?127.0.0.1:6379>?get?mykey1 "hello" #由于mykey已經(jīng)不存在了,所以返回錯(cuò)誤信息。 redis?127.0.0.1:6379>?rename?mykey?mykey1 (error)?ERR?no?such?key #為renamenx準(zhǔn)備測試key redis?127.0.0.1:6379>?set?oldkey?"hello" OK redis?127.0.0.1:6379>?set?newkey?"world" OK #由于newkey已經(jīng)存在,因此該命令未能成功執(zhí)行。 redis?127.0.0.1:6379>?renamenx?oldkey?newkey (integer)?0 #查看newkey的值,發(fā)現(xiàn)它也沒有被renamenx覆蓋。 redis?127.0.0.1:6379>?get?newkey "world" ???????? 2.?PERSIST/EXPIRE/EXPIREAT/TTL:???? #為后面的示例準(zhǔn)備的測試數(shù)據(jù)。 redis?127.0.0.1:6379>?set?mykey?"hello" OK #將該鍵的超時(shí)設(shè)置為100秒。 redis?127.0.0.1:6379>?expire?mykey?100 (integer)?1 #通過ttl命令查看一下還剩下多少秒。 redis?127.0.0.1:6379>?ttl?mykey (integer)?97 #立刻執(zhí)行persist命令,該存在超時(shí)的鍵變成持久化的鍵,即將該Key的超時(shí)去掉。 redis?127.0.0.1:6379>?persist?mykey (integer)?1 #ttl的返回值告訴我們,該鍵已經(jīng)沒有超時(shí)了。 redis?127.0.0.1:6379>?ttl?mykey (integer)?-1 #為后面的expire命令準(zhǔn)備數(shù)據(jù)。 redis?127.0.0.1:6379>?del?mykey (integer)?1 redis?127.0.0.1:6379>?set?mykey?"hello" OK #設(shè)置該鍵的超時(shí)被100秒。 redis?127.0.0.1:6379>?expire?mykey?100 (integer)?1 #用ttl命令看一下當(dāng)前還剩下多少秒,從結(jié)果中可以看出還剩下96秒。 redis?127.0.0.1:6379>?ttl?mykey (integer)?96 #重新更新該鍵的超時(shí)時(shí)間為20秒,從返回值可以看出該命令執(zhí)行成功。 redis?127.0.0.1:6379>?expire?mykey?20 (integer)?1 #再用ttl確認(rèn)一下,從結(jié)果中可以看出果然被更新了。 redis?127.0.0.1:6379>?ttl?mykey (integer)?17 #立刻更新該鍵的值,以使其超時(shí)無效。 redis?127.0.0.1:6379>?set?mykey?"world" OK #從ttl的結(jié)果可以看出,在上一條修改該鍵的命令執(zhí)行后,該鍵的超時(shí)也無效了。 redis?127.0.0.1:6379>?ttl?mykey (integer)?-1 3.?TYPE/RANDOMKEY/SORT: #由于mm鍵在數(shù)據(jù)庫中不存在,因此該命令返回none。 redis?127.0.0.1:6379>?type?mm none #mykey的值是字符串類型,因此返回string。 redis?127.0.0.1:6379>?type?mykey string #準(zhǔn)備一個(gè)值是set類型的鍵。 redis?127.0.0.1:6379>?sadd?mysetkey?1?2 (integer)?2 #mysetkey的鍵是set,因此返回字符串set。 redis?127.0.0.1:6379>?type?mysetkey set #返回?cái)?shù)據(jù)庫中的任意鍵。 redis?127.0.0.1:6379>?randomkey "oldkey" #清空當(dāng)前打開的數(shù)據(jù)庫。 redis?127.0.0.1:6379>?flushdb OK #由于沒有數(shù)據(jù)了,因此返回nil。 redis?127.0.0.1:6379>?randomkey (nil) #在線搭建redis從庫,此時(shí)將會丟棄舊數(shù)據(jù)集,轉(zhuǎn)而開始對新主服務(wù)器進(jìn)行同步 redis?127.0.0.1:6379>?SLAVEOF?10.2.1.21?6379 #不過很多redis是有密碼的,所以要配置一下 CONFIG?SET?MASTERAUTH?123123 #在線關(guān)閉從庫配置,原來同步所得的數(shù)據(jù)集不會被丟棄。 redis?127.0.0.1:6379>?SLAVEOF?NO?ONE #可以通過下面命令去在線修改參數(shù),但重啟失效, config?set?maxmemory?6442450944 #使用下面命令寫進(jìn)配置文件 config?rewrite
上面這些只是一部分的用法,但是對于一般測試就足夠了?,其他還有l(wèi)ist用法和hash用法什么的,有興趣可以更加深入研究.
--------------------------------------------------------
類似于tail和tailf的概念,終端輸出模式就是一直連線,而下面的命令結(jié)果輸出模式就是命令執(zhí)行就出一個(gè)結(jié)果,不會繼續(xù)連線.
下面來看命令結(jié)果輸出模式:
redis-cli參數(shù)
-h ? ?設(shè)置檢測主機(jī)IP地址,默認(rèn)為127.0.0.1
-p ? ?設(shè)置檢測主機(jī)的端口號,默認(rèn)為6379 ? ?
-s<socket> ? ?服務(wù)器套接字(壓倒主機(jī)和端口) ? ?
-a ? ?連接到Master服務(wù)器時(shí)使用的密碼 ? ?
-r ? ?執(zhí)行指定的N次命令 ? ?
-i ? ?執(zhí)行命令后等待N秒,如–i 0.1 info(執(zhí)行后等0.1秒) ? ?
-n ? ?指定連接N號ID數(shù)據(jù)庫,如 –n 3(連接3號數(shù)據(jù)庫) ? ?
-x ? ?從控制臺輸入的信息中讀取最后一個(gè)參數(shù) ? ?
-d ? ?定義多個(gè)定界符為默認(rèn)輸出格式(默認(rèn): \n) ? ?
--raw ? ?使用原數(shù)據(jù)格式返回輸出內(nèi)容 ? ?
--latency ? ?進(jìn)入一個(gè)不斷延時(shí)采樣的特殊模式 ? ?
--slave ? ?模擬一個(gè)從服務(wù)器到主服務(wù)器的命令顯示反饋 ? ?
--pipe ? ?使用管道協(xié)議模式 ? ?
--bigkeys ? ?監(jiān)聽顯示數(shù)據(jù)量大的key值,--bigkeys -i 0.1 ? ??
--help ? ?顯示命令行幫助信息 ? ?
--version ? ?顯示版本號 ? ?
例子:
$?redis-cli進(jìn)入命令行模式 $?redis-cli?-n?3?set?mykey?"hi"?把mykey插入到第三個(gè)數(shù)據(jù)庫 $?redis-cli?-r?3?info?重復(fù)執(zhí)行info命令三次 下面還有一些比較特別的用法 GETSET:?./redis-cli?getset?nid?987654321? #?表示返回指定key的原始值,并指定一個(gè)新值給他? MGET:?./redis-cli?mget?nid?uid?…? #?表示獲取多個(gè)key的值? SETNX:?./redis-cli?setnx?nnid?888888? #?表示當(dāng)一個(gè)指定的key不存在時(shí),設(shè)置這個(gè)key指定的value,如果存在,則設(shè)置不成功? SETEX:?./redis-cli?setex?nid?5?666666? #?表示設(shè)置一個(gè)key指定的value保存5秒后失效,設(shè)置key/value的有效期? MSET:?./redis-cli?mset?nid0001?"0001"?nid0002?"0002"?nid0003?"0003" #?表示多鍵值對的數(shù)據(jù)保存? INCR:?./redis-cli?incr?count? #?表示對給定key的value進(jìn)行遞增(+1)的操作,當(dāng)然value必須是一個(gè)integer? INCRBY:?./redis-cli?incrby?count?5? #?表示對給定key的value進(jìn)行指定步長的遞增操作? DECR:?./redis-cli?decr?count? #?表示對給定key的value進(jìn)行遞減(-1)的操作? DECRBY:?./redis-cli?decrby?count?7? #?表示對給定key的value進(jìn)行指定步長的遞減操作? APPEND:?./redis-cli?append?content?"bad"???或者??./redis-cli?append?content?"good" #?表示追加一個(gè)value到指定的key中,如果key不存在,則新建key? SUBSTR:?./redis-cli?substr?content?0?4? #?表示返回指定key的value的部分字符串 #?列表操作,精華? RPUSH?key?string?—?將某個(gè)值加入到一個(gè)key列表末尾? LPUSH?key?string?—?將某個(gè)值加入到一個(gè)key列表頭部? LLEN?key?—?列表長度? LRANGE?key?start?end?—?返回列表中某個(gè)范圍的值,相當(dāng)于mysql里面的分頁查詢那樣? LTRIM?key?start?end?—?只保留列表中某個(gè)范圍的值? LINDEX?key?index?—?獲取列表中特定索引號的值,要注意是O(n)復(fù)雜度? LSET?key?index?value?—?設(shè)置列表中某個(gè)位置的值? RPOP?key? #?集合操作? SADD?key?member?—?增加元素? SREM?key?member?—?刪除元素? SCARD?key?—?返回集合大小? SISMEMBER?key?member?—?判斷某個(gè)值是否在集合中? SINTER?key1?key2?...?keyN?—?獲取多個(gè)集合的交集元素? SMEMBERS?key?—?列出集合的所有元素?? 更新日志檢查?,加--fix參數(shù)為修復(fù)log文件 redis-check-aof?appendonly.aof 檢查本地?cái)?shù)據(jù)庫文件 redis-check-dump??dump.rdb
========================================================
壓力測試
redis測試分兩種說法,第一種就是并發(fā)壓力,另一種就是容量壓力了,
并發(fā)壓力可以用redis自帶的軟件redis-benchmark來測試?,具體如下:
redis-benchmark參數(shù)
-h ? ?設(shè)置檢測主機(jī)IP地址,默認(rèn)為127.0.0.1 ? ?
-p ? ?設(shè)置檢測主機(jī)的端口號,默認(rèn)為6379 ? ?
-s<socket> ? ?服務(wù)器套接字(壓倒主機(jī)和端口) ? ?
-c ? ?并發(fā)連接數(shù) ? ?
-n ? ?請求數(shù) ? ?
-d ? ?測試使用的數(shù)據(jù)集的大小/字節(jié)的值(默認(rèn)3字節(jié)) ? ?
-k ? ?1:表示保持連接(默認(rèn)值)0:重新連接 ? ?
-r ? ?SET/GET/INCR方法使用隨機(jī)數(shù)插入數(shù)值,設(shè)置10則插入值為rand:000000000000 - rand:000000000009 ? ?
-P ? ?默認(rèn)為1(無管道),當(dāng)網(wǎng)絡(luò)延遲過長時(shí),使用管道方式通信(請求和響應(yīng)打包發(fā)送接收) ? ?
-q ? ?簡約信息模式,只顯示查詢和秒值等基本信息。 ? ?
--csv ? ?以CSV格式輸出信息 ? ?
-l ? ?無線循環(huán)插入測試數(shù)據(jù),ctrl+c停止 ? ?
-t<tests> ? ?只運(yùn)行<tests>測試逗號分隔的列表命令,如:-t ping,set,get ? ?
-I ? ?空閑模式。立即打開50個(gè)空閑連接和等待。 ??
例子:?
#SET/GET?100?bytes?檢測host為127.0.0.1?端口為6379的redis服務(wù)器性能 redis-benchmark?-h?127.0.0.1?-p?6379?-q?-d?100?? #5000個(gè)并發(fā)連接,100000個(gè)請求,檢測host為127.0.0.1?端口為6379的redis服務(wù)器性能? redis-benchmark?-h?127.0.0.1?-p?6379?-c?5000?-n?100000? #向redis服務(wù)器發(fā)送100000個(gè)請求,每個(gè)請求附帶60個(gè)并發(fā)客戶端 redis-benchmark?-n?100000?-c?60
結(jié)果(部分):
====== SET ======
對集合寫入測試
? 100000 requests completed in 2.38 seconds
100000個(gè)請求在2.38秒內(nèi)完成
? 60 parallel clients
每次請求有60個(gè)并發(fā)客戶端
? 3 bytes payload
每次寫入3個(gè)字節(jié)的數(shù)據(jù)
? keep alive: 1
保持一個(gè)連接,一臺服務(wù)器來處理這些請求
100.00% <= 62 milliseconds
所有請求在62毫秒內(nèi)完成
42105.26 requests per second
每秒處理42105.26次請求
還是比較直觀的
-----------------------------------
然后說說容量測試,其實(shí)很好理解,內(nèi)存不是無限的,存放數(shù)據(jù)自然就是有限,雖然說可以去配置文件去用淘汰機(jī)制限制,但是知道容量頂點(diǎn)還是能解決不少問題.
順便也說說,要是你設(shè)置的maxmemory 容量不夠,或者整個(gè)內(nèi)存都不夠,而又沒有使用有效的LRU配置,那么你的redis寫滿了之后會提示OOM,就是說內(nèi)存不夠用,寫不進(jìn)新數(shù)據(jù).
說的就是maxmemory-policy這個(gè)設(shè)置,具體怎么設(shè)置才是合理的,則需要從業(yè)務(wù)層面去考慮了,例如說丟了一些舊key也沒所謂的,allkeys-lru就是最好了,嚴(yán)格來或,你用了這個(gè)策略其實(shí)也不用測試了,因?yàn)樗麜詣?dòng)刪舊key,沒什么頂不頂點(diǎn)的概念在..
測試容量的方法很簡單,就是不停的往里面寫數(shù)據(jù),然后看他頂點(diǎn)是多少.??
參考腳本如下:
#!/bin/sh keyset="keytest5" valueset='模擬數(shù)據(jù),隨便你寫' dbname=5 a=0 for?i?in?`seq?1?300000` do redis-cli?-n?$dbname?'set'?${keyset}${a}?"${valueset}${a}"?>/dev/null #echo?$a let?a++ done
測試結(jié)果很簡單,看info的最后一個(gè)結(jié)果就好了,哪里會有顯示現(xiàn)在有多少個(gè)key在.
性能分析
info信息:
在redis-cli進(jìn)入登錄界面后,輸入info all,或者redis-cli -h ${ip} -p ${post} -a "${pass}" -c info all,通常我們只輸入info就夠了,是簡介模式的意思,info all是詳細(xì)模式
之后,就會獲取所有與Redis服務(wù)相關(guān)的實(shí)時(shí)性能信息,類似于linux命令top那樣的東西.
info命令輸出的數(shù)據(jù)可分為10個(gè)類別,分別是:
server
clients
memory
persistence
stats
replication
cpu
commandstats
cluster
keyspace
下面展開解析一些重點(diǎn)信息.
server?部分:
redis_version?:???? Redis 服務(wù)器版本,不同版本會有些功能和命令不同
arch_bits?: ????架構(gòu)(32 或 64 位),某些情況,容易被忽略的坑
tcp_port?: ????TCP/IP 監(jiān)聽端口,確認(rèn)你操作的對不對
uptime_in_seconds?: ????自 Redis 服務(wù)器啟動(dòng)以來,經(jīng)過的秒數(shù),可以確認(rèn)有沒有被重啟過
uptime_in_days?:???? 自 Redis 服務(wù)器啟動(dòng)以來,經(jīng)過的天數(shù),可以確認(rèn)有沒有被重啟過
clients?部分:
connected_clients?: ????已連接客戶端的數(shù)量(不包括通過從屬服務(wù)器連接的客戶端)
client_longest_output_list?: ????當(dāng)前連接的客戶端當(dāng)中,最長的輸出列表
client_longest_input_buf?: ????當(dāng)前連接的客戶端當(dāng)中,最大輸入緩存
blocked_clients?: ????正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客戶端的數(shù)量
memory部分:
maxmemory/maxmemory_human:??? 配置文件redis.conf限制的可分配的最大內(nèi)存總量,當(dāng)超過之后,就會觸發(fā)LRU刪除舊數(shù)據(jù).
used_memory/used_memory_human:??? 當(dāng)前redis-server實(shí)際使用的內(nèi)存總量,如果used_memory > maxmemory ,那么操作系統(tǒng)開始進(jìn)行內(nèi)存與swap空間交換,以便騰出新的物理內(nèi)存給新頁或活動(dòng)頁(page)使用,那是有多糟糕大家可以想得到.
used_memory_rss/used_memory_rss_human:????從操作系統(tǒng)上顯示已經(jīng)分配的內(nèi)存總量,也就是這個(gè)redis-server占用的系統(tǒng)物理內(nèi)存實(shí)際值,比used_memory多出來的就可能是碎片.
mem_fragmentation_ratio:????內(nèi)存碎片率,內(nèi)存碎片率稍大于1是合理的,說明redis沒有發(fā)生內(nèi)存交換,如果內(nèi)存碎片率超過1.5,那就說明Redis消耗了實(shí)際需要物理內(nèi)存的150%,其中50%是內(nèi)存碎片率。若是內(nèi)存碎片率低于1的話,說明Redis內(nèi)存分配超出了物理內(nèi)存,操作系統(tǒng)正在進(jìn)行內(nèi)存交換。內(nèi)存交換會引起非常明顯的響應(yīng)延遲.
????下面是計(jì)算公式:
????????
????當(dāng)碎片率出現(xiàn)問題,有3種方法解決內(nèi)存管理變差的問題,提高redis性能:
????????1. 重啟Redis服務(wù)器:如果內(nèi)存碎片率超過1.5,重啟Redis服務(wù)器可以讓額外產(chǎn)生的內(nèi)存碎片失效并重新作為新內(nèi)存來使用,使操作系統(tǒng)恢復(fù)高效的內(nèi)存管理。
????????2.限制內(nèi)存交換:?如果內(nèi)存碎片率低于1,Redis實(shí)例可能會把部分?jǐn)?shù)據(jù)交換到硬盤上。內(nèi)存交換會嚴(yán)重影響Redis的性能,所以應(yīng)該增加可用物理內(nèi)存或減少實(shí)Redis內(nèi)存占用
????????3.修改內(nèi)存分配器:
Redis支持glibc’s malloc、jemalloc11、tcmalloc幾種不同的內(nèi)存分配器,每個(gè)分配器在內(nèi)存分配和碎片上都有不同的實(shí)現(xiàn)。不建議普通管理員修改Redis默認(rèn)內(nèi)存分配器,因?yàn)檫@需要完全理解這幾種內(nèi)存分配器的差異,也要重新編譯Redis。
used_memory_lua:????Lua腳本引擎所使用的內(nèi)存大小。redis默認(rèn)允許使用lua腳本,不過太多了的話就占用了可用內(nèi)存
mem_allocator:????在編譯時(shí)指定的Redis使用的內(nèi)存分配器,可以是libc、jemalloc、tcmalloc.
persistence?部分:
RDB信息,RDB的操作要用到bgsave命令,是比較耗費(fèi)資源的持久化操作,而且不是實(shí)時(shí)的,容易造成宕機(jī)數(shù)據(jù)消失,如果內(nèi)存容量滿了,不能做bgsave操作的話,隱患會很大.
rdb_changes_since_last_save?: ????距離最近一次成功創(chuàng)建持久化文件之后,經(jīng)過了多少秒。持久化是需要占用資源的,在高負(fù)載下需要盡量避免持久化的影響,下列參數(shù)均有參考價(jià)值.
rdb_bgsave_in_progress:????當(dāng)前是否在進(jìn)行bgsave操作。是為1
rdb_last_save_time?:???? 最近一次成功創(chuàng)建 RDB 文件的 UNIX 時(shí)間戳。
rdb_last_bgsave_time_sec?: ????記錄了最近一次創(chuàng)建 RDB 文件耗費(fèi)的秒數(shù)。
rdb_last_bgsave_status:????上次保存的狀態(tài)
rdb_current_bgsave_time_sec?: ????如果服務(wù)器正在創(chuàng)建 RDB 文件,那么這個(gè)域記錄的就是當(dāng)前的創(chuàng)建操作已經(jīng)耗費(fèi)的秒數(shù)。
AOF信息,AOF是持續(xù)記錄命令到持久化文件的方法,比較節(jié)省資源,但是AOF存儲文件會沒有限制存儲,時(shí)間一長,或者操作太頻繁,那就會出現(xiàn)AOF文件過大,撐爆硬盤的事.而且,這個(gè)方法還是會定期bgsave操作.
aof_enabled:????AOF文件是否啟用
aof_rewrite_in_progress:????表示當(dāng)前是否在進(jìn)行寫入AOF文件操作
aof_last_rewrite_time_sec?: ????最近一次創(chuàng)建 AOF 文件耗費(fèi)的時(shí)長。
aof_current_rewrite_time_sec?: ????如果服務(wù)器正在創(chuàng)建 AOF 文件,那么這個(gè)域記錄的就是當(dāng)前的創(chuàng)建操作已經(jīng)耗費(fèi)的秒數(shù)。
aof_last_bgrewrite_status:????上次寫入狀態(tài)
aof_last_write_status:????上次寫入狀態(tài)
aof_base_size?: ????服務(wù)器啟動(dòng)時(shí)或者 AOF 重寫最近一次執(zhí)行之后,AOF 文件的大小。
aof_pending_bio_fsync?: ????后臺 I/O 隊(duì)列里面,等待執(zhí)行的?fsync?調(diào)用數(shù)量。
aof_delayed_fsync?: ????被延遲的?fsync?調(diào)用數(shù)量。
stats部分:
total_commands_processed:????顯示了Redis服務(wù)處理命令的總數(shù),且值是遞增的.因?yàn)镽edis是個(gè)單線程模型,客戶端過來的命令是按照順序執(zhí)行的,如果命令隊(duì)列里等待處理的命令數(shù)量比較多,命令的響應(yīng)時(shí)間就變慢,甚至于后面的命令完全被阻塞,導(dǎo)致Redis性能降低.所以這個(gè)時(shí)候就需要記錄這個(gè)參數(shù)的值,是不是增長過快,導(dǎo)致了性能降低.
instantaneous_ops_per_sec?:???? 服務(wù)器每秒鐘執(zhí)行的命令數(shù)量,同上,如果增長過快就有問題。
expired_keys?:???? 因?yàn)檫^期而被自動(dòng)刪除的數(shù)據(jù)庫鍵數(shù)量,具有參考意義。
evicted_keys:????顯示因?yàn)閙axmemory限制導(dǎo)致key被回收刪除的數(shù)量.根據(jù)配置文件中設(shè)置maxmemory-policy值來確定Redis是使用lru策略還是過期時(shí)間策略.如果是過期回收的,不會被記錄在這里,通常這個(gè)值不為0,那就要考慮增加內(nèi)存限制,不然就會造成內(nèi)存交換,輕則性能變差,重則丟數(shù)據(jù).
latest_fork_usec:???? 最近一次?fork()?操作耗費(fèi)的微秒數(shù)。fork()是很耗費(fèi)資源的操作,所以要留意一下.
commandstats部分:
cmdstat_XXX:????記錄了各種不同類型的命令的執(zhí)行統(tǒng)計(jì)信息,命令包含有讀有寫,分得比較細(xì),其中calls代表命令執(zhí)行的次數(shù),usec代表命令耗費(fèi)的 CPU 時(shí)間,usec_per_call代表每個(gè)命令耗費(fèi)的平均 CPU 時(shí)間,單位為微秒.對于排錯(cuò)有一定用途.
---------------------------------------------------------------------------------------------------
其他問題的分析方法:
查看redis的網(wǎng)絡(luò)延時(shí):
Redis的延遲數(shù)據(jù)是無法從info信息中獲取的。倘若想要查看延遲時(shí)間,可以用 Redis-cli工具加--latency參數(shù)運(yùn)行
redis-cli --latency -h 10.1.2.11 -p 6379
他將會持續(xù)掃描延遲時(shí)間,直到按ctrl+C退出,以毫秒為單位測量Redis的響應(yīng)延遲時(shí)間,由于服務(wù)器不同的運(yùn)行情況,延遲時(shí)間可能有所誤差,通常1G網(wǎng)卡的延遲時(shí)間是0.2毫秒,若延時(shí)值遠(yuǎn)高于這個(gè)參考值,那明顯是有性能問題了。這個(gè)時(shí)候我們要考慮檢查一下網(wǎng)絡(luò)狀況.
查看redis的慢查詢:
Slow log 是 Redis 用來記錄查詢執(zhí)行時(shí)間的日志系統(tǒng)。Redis中的slowlog命令可以讓我們快速定位到那些超出指定執(zhí)行時(shí)間的慢命令,默認(rèn)情況下會記錄執(zhí)行時(shí)間超過10ms的記錄到日志,由參數(shù)slowlog-log-slower-than控制.最多記錄128條,由參數(shù)slowlog-max-len控制,超過就自動(dòng)刪除.
通常這個(gè)默認(rèn)參數(shù)夠用,也可以在線CONFIG SET修改參數(shù)slowlog-log-slower-than和slowlog-max-len來修改這個(gè)時(shí)間和限制條數(shù)。
通常1gb帶寬的網(wǎng)絡(luò)延遲,預(yù)期在0.2ms左右,倘若一個(gè)命令僅執(zhí)行時(shí)間就超過10ms,那比網(wǎng)絡(luò)延遲慢了近50倍??梢酝ㄟ^使用Redis-cli工具,輸入slowlog get命令查看,返回結(jié)果的第三個(gè)字段以微妙位單位顯示命令的執(zhí)行時(shí)間。假如只需要查看最后3個(gè)慢命令,輸入slowlog get 10即可。
127.0.0.1:6379>?slowlog?get?10 ????. ????. ????. 4)?1)?(integer)?215 ????2)?(integer)?1489099695 ????3)?(integer)?11983 ????4)?1)?"SADD" ???????2)?"USER_TOKEN_MAP51193" ???????3)?"qIzwZKBmBJozKprQgoTEI3Qo8QO2Fi!4" ?5)?1)?(integer)?214 ????2)?(integer)?1489087112 ????3)?(integer)?18002 ????4)?1)?"SADD" ???????2)?"USER_TOKEN_MAP51192" ???????3)?"Z3Hs!iTUNfweqvLLf!ptdchSV2JAOrrH" ?6)?1)?(integer)?213 ????2)?(integer)?1489069123 ????3)?(integer)?15407 ????4)?1)?"SADD" ???????2)?"USER_TOKEN_MAP51191" ???????3)?"S3rNzOBwUlaI3QfOK9dIITB6Bk7LIGYe"
1=日志的唯一標(biāo)識符
2=被記錄命令的執(zhí)行時(shí)間點(diǎn),以 UNIX 時(shí)間戳格式表示
3=查詢執(zhí)行時(shí)間,以微秒為單位。例子中命令使用11毫秒。
4= 執(zhí)行的命令,以數(shù)組的形式排列。完整命令是拼在一起.
監(jiān)控客戶端的連接:
因?yàn)镽edis是單線程模型(只能使用單核),來處理所有客戶端的請求, 但由于客戶端連接數(shù)的增長,處理請求的線程資源開始降低分配給單個(gè)客戶端連接的處理時(shí)間,這時(shí)每個(gè)客戶端需要花費(fèi)更多的時(shí)間去等待Redis共享服務(wù)的響應(yīng)。
#查看客戶端連接狀態(tài) 127.0.0.1:6379>?info?clients #?Clients connected_clients:11 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0
第一個(gè)字段(connected_clients)顯示當(dāng)前實(shí)例客戶端連接的總數(shù),Redis默認(rèn)允許客戶端連接的最大數(shù)量是10000。若是看到連接數(shù)超過5000以上,那可能會影響Redis的性能。倘若一些或大部分客戶端發(fā)送大量的命令過來,這個(gè)數(shù)字會低的多。
查當(dāng)前客戶端狀態(tài)
#查看所有正在連接的客戶端狀態(tài), 127.0.0.1:6379>?client?list id=821882?addr=10.25.138.2:60990?fd=8?name=?age=53838?idle=24?flags=N?db=0?sub=0?psub=0?multi=-1?qbuf=0?qbuf-free=0?obl=0?oll=0?omem=0?events=r?cmd=ping
這個(gè)看起來有點(diǎn)繞,因?yàn)楹蜌v史數(shù)據(jù)是混在一起的:
addr:客戶端的地址和端口,包含當(dāng)前連接和歷史連接
age:這個(gè)客戶端連進(jìn)來的生命周期,也就是連進(jìn)來之后的持續(xù)時(shí)間,單位是秒
idle:這個(gè)客戶端的空閑時(shí)間,也就是說這個(gè)時(shí)間內(nèi),客戶端沒有操作,單位是秒
db:操作的數(shù)據(jù)庫,redis默認(rèn)有db0~db15可用選擇
cmd:客戶端最后一次使用的命令
也就是說,idle越少,那就代表這個(gè)客戶端剛剛操作,反則是歷史記錄而已.age越少就代表是剛剛建立的連接,越大則是歷史連接.而有些時(shí)候個(gè)別使用者用了scan或keys命令,會對數(shù)據(jù)量大的redis造成很大的負(fù)載壓力,所以需要特別關(guān)注.
特大key的統(tǒng)計(jì):
在redis的單線程處理方式下,一些數(shù)據(jù)量比較大的key的操作明顯是會影響性能,所以必要時(shí),我們要統(tǒng)計(jì)出來,交給開發(fā)來優(yōu)化
#統(tǒng)計(jì)生產(chǎn)上比較大的key redis-cli?-h*?-a*?-p*?--bigkeys #查看某個(gè)key的持續(xù)時(shí)間 127.0.0.1:6379>?OBJECT?IDLETIME?key名字
--bigkeys信息解析:
1.該命令使用scan方式對key進(jìn)行統(tǒng)計(jì),所以使用時(shí)無需擔(dān)心對redis造成阻塞。
2.輸出大概分為兩部分,summary之上的部分,只是顯示了掃描的過程。summary部分給出了每種數(shù)據(jù)結(jié)構(gòu)中最大的Key,所以下面部分更重要些。
3.統(tǒng)計(jì)出的最大key只有string類型是以字節(jié)長度為衡量標(biāo)準(zhǔn)的。list,set,zset等都是以元素個(gè)數(shù)作為衡量標(biāo)準(zhǔn),不能說明其占的內(nèi)存就一定多,需要另外計(jì)算。
得出最大key名字后,就去看看粗略大小,
#查看某個(gè)key序列化后的長度 debug?object?key
輸出的項(xiàng)的說明:
Value at:key的內(nèi)存地址
refcount:引用次數(shù)
encoding:編碼類型
serializedlength:經(jīng)過壓縮后的序列化長度,單位是 B, 也就是 Byte(字節(jié)),因?yàn)閴嚎s效果要看編碼類型,不一定反應(yīng)內(nèi)存中的大小,只是有參考價(jià)值.
lru_seconds_idle:空閑時(shí)間
終上所述,我們要關(guān)注的大key信息正是serializedlength的長度了.
另外還有一個(gè)工具[rdbtools],可以全面分析redis里面的key信息,但是要額外安裝,對于內(nèi)網(wǎng)用戶不可謂不麻煩,因?yàn)椴皇窍到y(tǒng)自帶的功能,這里不詳細(xì)說明,請等待另一篇文章另外介紹.
數(shù)據(jù)持久化引發(fā)的延遲
Redis的數(shù)據(jù)持久化工作本身就會帶來延遲,需要根據(jù)數(shù)據(jù)的安全級別和性能要求制定合理的持久化策略:
1.AOF + fsync always的設(shè)置雖然能夠絕對確保數(shù)據(jù)安全,但每個(gè)操作都會觸發(fā)一次fsync,會對Redis的性能有比較明顯的影響
2.AOF + fsync every second是比較好的折中方案,每秒fsync一次
3.AOF + fsync never會提供AOF持久化方案下的最優(yōu)性能,使用RDB持久化通常會提供比使用AOF更高的性能,但需要注意RDB的策略配置
4.每一次RDB快照和AOF Rewrite都需要Redis主進(jìn)程進(jìn)行fork操作。fork操作本身可能會產(chǎn)生較高的耗時(shí),與CPU和Redis占用的內(nèi)存大小有關(guān)。根據(jù)具體的情況合理配置RDB快照和AOF Rewrite時(shí)機(jī),避免過于頻繁的fork帶來的延遲.
例如:Redis在fork子進(jìn)程時(shí)需要將內(nèi)存分頁表拷貝至子進(jìn)程,以占用了24GB內(nèi)存的Redis實(shí)例為例,共需要拷貝24GB / 4kB * 8 = 48MB的數(shù)據(jù)。在使用單Xeon 2.27Ghz的物理機(jī)上,這一fork操作耗時(shí)216ms。
可以通過INFO命令返回的latest_fork_usec字段查看上一次fork操作的耗時(shí)(微秒)。
Swap引發(fā)的延遲
當(dāng)Linux將Redis所用的內(nèi)存分頁移至swap空間時(shí),將會阻塞Redis進(jìn)程,導(dǎo)致Redis出現(xiàn)不正常的延遲。Swap通常在物理內(nèi)存不足或一些進(jìn)程在進(jìn)行大量I/O操作時(shí)發(fā)生,應(yīng)盡可能避免上述兩種情況的出現(xiàn)。
在/proc/redis進(jìn)程號/smaps文件中會保存進(jìn)程的swap記錄,通過查看這個(gè)文件,能夠判斷Redis的延遲是否由Swap產(chǎn)生。如果這個(gè)文件中記錄了較大的Swap size,則說明延遲很有可能是Swap造成的。
例子如下,可以看到當(dāng)前swap的狀態(tài)時(shí)0KB,也就是沒用到swap,
#/proc/pid/smaps顯示了進(jìn)程運(yùn)行時(shí)的內(nèi)存影響,系統(tǒng)的運(yùn)行時(shí)庫(so),堆,棧信息均可在其中看到。 cat?/proc/`ps?aux?|grep?redis?|grep?-v?grep?|awk?'{print?$2}'`/smaps 00400000-00531000?r-xp?00000000?fc:02?805438521?/usr/local/bin/redis-server Size:???????????????1220?kB Rss:?????????????????924?kB Pss:?????????????????924?kB Shared_Clean:??????????0?kB Shared_Dirty:??????????0?kB Private_Clean:???????924?kB Private_Dirty:?????????0?kB Referenced:??????????924?kB Anonymous:?????????????0?kB AnonHugePages:?????????0?kB Shared_Hugetlb:????????0?kB Private_Hugetlb:???????0?kB Swap:??????????????????0?kB SwapPss:???????????????0?kB KernelPageSize:????????4?kB MMUPageSize:???????????4?kB Locked:????????????????0?kB
內(nèi)存滿了怎么辦:
redis內(nèi)存滿了,那確實(shí)是很麻煩的事,但是再麻煩也得處理啊,這就得從redis架構(gòu)原理說起了.
首先我們要了解,redis的內(nèi)存滿,并不代表是用了系統(tǒng)的100%內(nèi)存,為什么這么說呢?我們都知道redis做持久化是save和bgsave,而常用的bgsave(也是默認(rèn))是fork一個(gè)進(jìn)程,把內(nèi)存copy一份再壓縮后存到硬盤成*.rdb文件.這里就涉及一個(gè)問題,你內(nèi)存必須保證有和數(shù)據(jù)一樣大的空間才能做bgsave,那嚴(yán)格來說,只要你的內(nèi)存超過系統(tǒng)內(nèi)存的50%,那就可以被稱為redis內(nèi)存滿了.
redis的持久化策略,上面只說了持久化會阻塞操作導(dǎo)致延時(shí),而如果內(nèi)存滿了,數(shù)據(jù)量的增加會讓持久化造成的延時(shí)會更嚴(yán)重,而且持久化失敗后是默認(rèn)每分鐘重試一遍.
那么問題就來了,因?yàn)閮?nèi)存滿了,持久化失敗,然后一分鐘后再持久化,就造成了惡性循環(huán),redis的性能直線下降.那怎么辦好呢?
更改持久化策略是個(gè)臨時(shí)解決方案,就是直接把rdb持久化關(guān)閉掉:
config?set?save?""
為什么能解決,答案也很明顯,關(guān)閉了持久化,那就不會阻塞操作,那你redis的性能還是保證到了.但是又會引入新問題,沒了持久化,內(nèi)存數(shù)據(jù)如果redis-server程序重啟或關(guān)閉就沒了,還是比較危險(xiǎn)的.而且內(nèi)存滿的問題還在,如果內(nèi)存用到了系統(tǒng)內(nèi)存100%,甚至觸發(fā)了系統(tǒng)的OOM,那就坑大了,因?yàn)閮?nèi)存被徹底清空,數(shù)據(jù)也都沒有了.也就是所謂的臨時(shí)解決辦法.
所以正確的做法是,在不阻塞操作之后,刪掉可以刪除的數(shù)據(jù),再重新拉起持久化,然后準(zhǔn)備擴(kuò)容的工作.
占用內(nèi)存看哪里,上面已經(jīng)說了,但是內(nèi)存滿了的定義,并不一定只是實(shí)際內(nèi)存占用,碎片也是要包含在內(nèi)的,例如:
#這種情況,肯定就是內(nèi)存滿 used_memory_human:4.2G maxmemory_human:4.00G #但是這種情況,也是內(nèi)存滿 used_memory_human:792.30M used_memory_rss_human:3.97G used_memory_peak_human:4.10G maxmemory_human:4.00G
因?yàn)閮?nèi)存碎片沒有被釋放,那它還是會占用內(nèi)存空間,對于系統(tǒng)來說,碎片也是redis-server占用的內(nèi)存,不是空閑的內(nèi)存,那剩下的內(nèi)存還是不足以用來bgsave.那怎么解決碎片呢?
在redis4.0之前,沒其他更好辦法,只能重啟redis-server,之后的新版本則新加了一個(gè)碎片回收參數(shù),杜絕了這個(gè)問題.
而碎片問題其實(shí)影響頗大,因?yàn)檎G闆r下,這些用不了又確實(shí)占著內(nèi)存的數(shù)據(jù),會讓我們的redis浪費(fèi)空間之余,還會額外造成內(nèi)存滿的風(fēng)險(xiǎn).所以也正如上面說的那樣,如果碎片率超過1.5之后,是該想想回收一下.
那確實(shí)需要保存內(nèi)存數(shù)據(jù)怎么辦?只能忍痛割愛,把不必要的數(shù)據(jù)刪除掉,讓內(nèi)存降到能做bgsave之后再重啟來回收碎片.要不,就是升級到4.0之后避免同類問題.
優(yōu)化建議
系統(tǒng)優(yōu)化
1.關(guān)閉Transparent huge pages
Transparent HugePages會讓內(nèi)核khugepaged線程在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存。在大部分linux發(fā)行版本中默認(rèn)是啟用的,缺點(diǎn)是可能會造成內(nèi)存在運(yùn)行時(shí)的延遲分配,對于大內(nèi)存應(yīng)用并不友好,例如:oracle,redis等會占用大量內(nèi)存的應(yīng)用,所以建議關(guān)閉。
#關(guān)閉Transparent?HugePages,默認(rèn)狀態(tài)是[always] echo?never?>?/sys/kernel/mm/transparent_hugepage/enabled
2.在物理機(jī)部署redis,這點(diǎn)不用多說了,虛擬機(jī)或者是docker都會有一定的延時(shí),沒有必要為了好管理二浪費(fèi)這些性能。
3.多用連接池,而不是頻繁斷開再連接,效果我想不言而喻。
4.客戶端進(jìn)行的批量數(shù)據(jù)操作,應(yīng)使用Pipeline特性在一次交互中完成。
行為優(yōu)化
1.假如緩存數(shù)據(jù)小于4GB,可以選擇使用32位的Redis實(shí)例。因?yàn)?2位實(shí)例上的指針大小只有64位的一半,它的內(nèi)存空間占用空間會更少些。Redis的dump文件在32位和64位之間是互相兼容的, 因此倘若有減少占用內(nèi)存空間的需求,可以嘗試先使用32位,后面再切換到64位上。
2.盡可能的使用Hash數(shù)據(jù)結(jié)構(gòu)。因?yàn)镽edis在儲存小于100個(gè)字段的Hash結(jié)構(gòu)上,其存儲效率是非常高的。所以在不需要集合(set)操作或list的push/pop操作的時(shí)候,盡可能的使用Hash結(jié)構(gòu)。Hash結(jié)構(gòu)的操作命令是HSET(key, fields, value)和HGET(key, field),使用它可以存儲或從Hash中取出指定的字段。
3.盡量設(shè)置key的過期時(shí)間。一個(gè)減少內(nèi)存使用率的簡單方法就是,每當(dāng)存儲對象時(shí)確保設(shè)置key的過期時(shí)間。倘若key在明確的時(shí)間周期內(nèi)使用或者舊key不大可能被使用時(shí),就可以用Redis過期時(shí)間命令(expire,expireat, pexpire, pexpireat)去設(shè)置過期時(shí)間,這樣Redis會在key過期時(shí)自動(dòng)刪除key.用ttl命令可以查詢過期時(shí)間,單位是秒,顯示-2代表key不存在,顯示-1代表沒有設(shè)置超時(shí)時(shí)間(也就是永久的).
4.使用多參數(shù)命令:若是客戶端在很短的時(shí)間內(nèi)發(fā)送大量的命令過來,會發(fā)現(xiàn)響應(yīng)時(shí)間明顯變慢,這由于后面命令一直在等待隊(duì)列中前面大量命令執(zhí)行完畢。舉例來說,循環(huán)使用LSET命令去添加1000個(gè)元素到list結(jié)構(gòu)中,是性能比較差的一種方式,更好的做法是在客戶端創(chuàng)建一個(gè)1000元素的列表,用單個(gè)命令LPUSH或RPUSH,通過多參數(shù)構(gòu)造形式一次性把1000個(gè)元素發(fā)送的Redis服務(wù)上。
5.管道命令:另一個(gè)減少多命令的方法是使用管道(pipeline),把幾個(gè)命令合并一起執(zhí)行,從而減少因網(wǎng)絡(luò)開銷引起的延遲問題。因?yàn)?0個(gè)命令單獨(dú)發(fā)送到服務(wù)端會引起10次網(wǎng)絡(luò)延遲開銷,使用管道會一次性把執(zhí)行結(jié)果返回,僅需要一次網(wǎng)絡(luò)延遲開銷。Redis本身支持管道命令,大多數(shù)客戶端也支持,倘若當(dāng)前實(shí)例延遲很明顯,那么使用管道去降低延遲是非常有效的。
6.避免操作大集合的慢命令:如果命令處理頻率過低導(dǎo)致延遲時(shí)間增加,這可能是因?yàn)槭褂昧烁邥r(shí)間復(fù)雜度的命令操作導(dǎo)致,這意味著每個(gè)命令從集合中獲取數(shù)據(jù)的時(shí)間增大。 所以減少使用高時(shí)間復(fù)雜的命令,能顯著的提高的Redis的性能。
7.限制客戶端連接數(shù):自Redis2.6以后,允許使用者在配置文件(Redis.conf)maxclients屬性上修改客戶端連接的最大數(shù),也可以通過在Redis-cli工具上輸入config set maxclients 去設(shè)置最大連接數(shù)。根據(jù)連接數(shù)負(fù)載的情況,這個(gè)數(shù)字應(yīng)該設(shè)置為預(yù)期連接數(shù)峰值的110%到150之間,若是連接數(shù)超出這個(gè)數(shù)字后,Redis會拒絕并立刻關(guān)閉新來的連接。通過設(shè)置最大連接數(shù)來限制非預(yù)期數(shù)量的連接數(shù)增長,是非常重要的。另外,新連接嘗試失敗會返回一個(gè)錯(cuò)誤消息,這可以讓客戶端知道,Redis此時(shí)有非預(yù)期數(shù)量的連接數(shù),以便執(zhí)行對應(yīng)的處理措施。 上述二種做法對控制連接數(shù)的數(shù)量和持續(xù)保持Redis的性能最優(yōu)是非常重要的
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。