天天看點

redis使用詳解

循例介紹一下了,redis是記憶體資料庫,是簡單的key-value結構,也是nosql資料庫,因為結構簡單,而且用的是記憶體,是以速度非常之快.至于問有多快?大家知道以前的機械硬碟,單盤速度其實也還好,而記憶體的讀寫速度是機械硬碟的6萬倍.是以,redis比硬碟有多快,可見一斑了.當然現在都用固态硬碟,情況還是比以前好不少的.這裡不再詳細類比,知道是這回事就好.

安裝

================================

好了,當然先說安裝了,安裝redis很簡單,先說明,我們伺服器都是linux.

首先要說明一下,記憶體資料庫并不代表完全不用硬碟空間,因為一般為了資料安全,配置上會備份一定資料到硬碟的,是以還是得準備一定的硬碟空間.

下載下傳位址:

<code>wget </code><code>"http://download.redis.io/releases/redis-3.2.0.tar.gz"</code>

是編譯版本,現在都出到3.2了,不過版本差異不大,低版本隻是不支援叢集或主進而已,實際上功能沒差.

安裝時有依賴包提示就記得yum下,一般就C語言庫相關的,這些大部分在初始化系統就必須裝上的了.

下面來看安裝方法,很簡單:

<code>#解壓編譯包</code>

<code>tar</code> <code>xzf redis-3.2.0.</code><code>tar</code><code>.gz</code>

<code>#進入解壓後的檔案夾</code>

<code>cd</code> <code>redis-3.2.0</code>

<code>#編譯安裝</code>

<code>make</code>

<code>make</code> <code>install</code>

<code>#順便說說,如果你想安裝在自定義目錄也是可以的</code>

<code>make</code> <code>prefix=(你的目錄) </code><code>install</code>

當make install指令執行完成後,會在/usr/local/bin目錄下生成幾個可執行檔案,它們的作用如下:

redis-server:    Redis伺服器的daemon啟動程式

redis-cli:       Redis指令行操作工具。也可以用telnet根據其純文字協定來操作

redis-benchmark: Redis性能測試工具,測試Redis在目前系統下的讀寫性能

redis-check-aof: 資料修複

redis-check-dump:檢查導出工具 

安裝完了,就要看配置了,配置檔案名可以随便改,位置也不固定要放什麼位置,因為啟動的時候可以指定配置檔案啟動.

還記得編譯目錄嗎?裡面就有配置檔案模闆,複制過來就可以用了,當然了,按照你自己的需求改一下還是有必要的,

<code>ll *.conf</code>

<code>-rw-rw-r-- 1 root root 45390 May  6 15:11 redis.conf</code>

<code>-rw-rw-r-- 1 root root  7109 May  6 15:11 sentinel.conf</code>

一個是redis的配置檔案,一個是哨兵,屬于redis叢集應用的配置檔案

配置太多,我們先看一些重點:

<code>cat</code> <code>redis.conf</code>

<code>#允許背景運作</code>

<code>daemonize  </code><code>yes</code>

<code>#設定端口,最好是非預設端口</code>

<code>port 6666</code>

<code>#綁定登入IP,安全考慮,最好是内網</code>

<code>bind 10.10.2.21</code>

<code>#命名并指定目前redis的PID路徑,用以區分多個redis</code>

<code>pidfile </code><code>/data/redis/data/config/redis_6666</code><code>.pid</code>

<code>#命名并指定目前redis日志檔案路徑</code>

<code>logfile </code><code>"/data/redis/data/logs/redis_6666.log"</code>

<code>#指定RDB檔案名,用以備份資料到硬碟并區分不同redis,當使用記憶體超過可用記憶體的45%時觸發快照功能</code>

<code>dbfilename dump_6666.rdb</code>

<code>#指定目前redis的根目錄,用來存放RDB/AOF檔案</code>

<code>dir</code> <code>/data/redis/data</code>

<code>#目前redis的認證密鑰,redis運作速度非常快,這個密碼要足夠強大</code>

<code>requirepass gggggggGGGGGGGGG999999999</code>

<code>#目前redis的最大容量限制,建議設定為可用記憶體的45%内,最高能設定為系統可用記憶體的95%</code>

<code>#可用config set maxmemory 去線上修改,但重新開機失效,需要使用config rewrite指令去重新整理配置檔案</code>

<code>maxmemory 1024000000</code>

<code>#LRU的政策,有四種,看情況選擇</code>

<code>maxmemory-policy allkeys-lru</code>

<code>#關閉自動持久化操作,預設情況下RDB自動持久化是開啟的,會定時自動壓縮儲存redis的全量資料.</code>

<code>#由于redis是單線程操作的,這個操作無疑比較耗費資源并阻塞操作,有些隻做緩存的環境也不見得資料有多重要.</code>

<code>#save ""</code>

<code>#預設情況下AOF持久化方式是關閉的,有需要可以開啟,但是要注意時間一長很占硬碟空間,相對RDB沒那麼阻塞操作.</code>

<code>#appendonly yes</code>

詳細解析如下:

-----------------------------------------------------------------------------------

1 daemonize  no

預設情況下,redis 不是在背景運作的,如果需要在背景運作,把該項的值更改為yes。

2 pidfile  /var/run/redis.pid

當Redis 在背景運作的時候,Redis 預設會把pid 檔案放在/var/run/redis.pid,你可以配置到其他位址。當運作多個redis 服務時,需要指定不同的pid 檔案和端口

3 port

監聽端口,預設為6379

4 #bind 127.0.0.1

指定Redis 隻接收來自于該IP 位址的請求,如果不進行設定,那麼将處理所有請求,在生産環境中為了安全最好設定該項。預設注釋掉,不開啟

5 timeout 0

設定用戶端連接配接時的逾時時間,機關為秒。當用戶端在這段時間内沒有發出任何指令,那麼關閉該連接配接

6 tcp-keepalive 0

指定TCP連接配接是否為長連接配接,"偵探"信号有server端維護。預設為0.表示禁用

7 loglevel notice

log 等級分為4 級,debug,verbose, notice, 和warning。生産環境下一般開啟notice

8 logfile stdout

配置log 檔案位址,預設使用标準輸出,即列印在指令行終端的視窗上,修改為日志檔案目錄

9 databases 16

設定資料庫的個數,可以使用SELECT 指令來切換資料庫。預設使用的資料庫是0号庫。預設16個庫

10 

save 900 1

save 300 10

save 60 10000

rdb自動持久化參數,儲存資料快照的頻率,即将資料持久化到dump.rdb檔案中的頻度。用來描述"在多少秒期間至少多少個變更操作"觸發snapshot資料儲存動作,

    預設設定,意思是:

    if(在60 秒之内有10000 個keys 發生變化時){

    進行鏡像備份

    }else if(在300 秒之内有10 個keys 發生了變化){

    }else if(在900 秒之内有1 個keys 發生了變化){

    }

    如果設定為空,例如:

    save ""

    即關閉rdb自動持久化.

    預設情況下RDB自動持久化是開啟的,會定時自動壓縮儲存redis的全量資料,但是由于redis是單線程操作的,這個操作無疑比較耗費資源而阻塞操作,有些隻做緩存的環境也不見得資料有多重要,關閉也是可以的.

    注意:手動bgsave指令還是可以使用的,還需要留意dir參數的檔案是否存在,如果存在,重新開機後會把檔案的資料加載進來

11 stop-writes-on-bgsave-error yes

當持久化出現錯誤時,是否依然繼續進行工作,是否終止所有的用戶端write請求。預設設定"yes"表示終止,一旦snapshot資料儲存故障,那麼此server為隻讀服務。如果為"no",那麼此次snapshot将失敗,但下一次snapshot不會受到影響,不過如果出現故障,資料隻能恢複到"最近一個成功點"

12 rdbcompression yes

在進行資料鏡像備份時,是否啟用rdb檔案壓縮手段,預設為yes。壓縮可能需要額外的cpu開支,不過這能夠有效的減小rdb檔案的大,有利于存儲/備份/傳輸/資料恢複

13 rdbchecksum yes

讀取和寫入時候,會損失10%性能

14 rdbchecksum yes

是否進行校驗和,是否對rdb檔案使用CRC64校驗和,預設為"yes",那麼每個rdb檔案内容的末尾都會追加CRC校驗和,利于第三方校驗工具檢測檔案完整性

14 dbfilename dump.rdb

鏡像快照備份檔案的檔案名,預設為 dump.rdb,當使用記憶體超過可用記憶體的45%時觸發快照功能

15 dir ./

資料庫鏡像備份的檔案rdb/AOF檔案放置的路徑。這裡的路徑跟檔案名要分開配置是因為Redis 在進行備份時,先會将目前資料庫的狀态寫入到一個臨時檔案中,等備份完成時,再把該臨時檔案替換為上面所指定的檔案,而這裡的臨時檔案和上面所配置的備份檔案都會放在這個指定的路徑當中

16 # slaveof &lt;masterip&gt; &lt;masterport&gt;

設定該資料庫為其他資料庫的從資料庫,并為其指定master資訊。

17 masterauth

當主資料庫連接配接需要密碼驗證時,在這裡指定

18 slave-serve-stale-data yes

當主master伺服器挂機或主從複制在進行時,是否依然可以允許客戶通路可能過期的資料。在"yes"情況下,slave繼續向用戶端提供隻讀服務,有可能此時的資料已經過期;在"no"情況下,任何向此server發送的資料請求服務(包括用戶端和此server的slave)都将被告知"error"

19 slave-read-only yes

slave是否為"隻讀",強烈建議為"yes"

20 # repl-ping-slave-period 10

slave向指定的master發送ping消息的時間間隔(秒),預設為10

21 # repl-timeout 60

slave與master通訊中,最大空閑時間,預設60秒.逾時将導緻連接配接關閉

22 repl-disable-tcp-nodelay no

slave與master的連接配接,是否禁用TCP nodelay選項。"yes"表示禁用,那麼socket通訊中資料将會以packet方式發送(packet大小受到socket buffer限制)。

可以提高socket通訊的效率(tcp互動次數),但是小資料将會被buffer,不會被立即發送,對于接受者可能存在延遲。"no"表示開啟tcp nodelay選項,任何資料都會被立即發送,及時性較好,但是效率較低,建議設為no

23 slave-priority 100

适用Sentinel子產品(unstable,M-S叢集管理和監控),需要額外的配置檔案支援。slave的權重值,預設100.當master失效後,Sentinel将會從slave清單中找到權重值最低(&gt;0)的slave,并提升為master。如果權重值為0,表示此slave為"觀察者",不參與master選舉

24 # requirepass foobared

設定用戶端連接配接後進行任何其他指定前需要使用的密碼。警告:因為redis 速度相當快,是以在一台比較好的伺服器下,一個外部的使用者可以在一秒鐘進行150K 次的密碼嘗試,這意味着你需要指定非常非常強大的密碼來防止暴力破解。

25 # rename-command CONFIG 3ed984507a5dcd722aeade310065ce5d    (方式:MD5('CONFIG^!'))

重命名指令,對于一些與"server"控制有關的指令,可能不希望遠端用戶端(非管理者使用者)連結随意使用,那麼就可以把這些指令重命名為"難以閱讀"的其他字元串

26 # maxclients 10000

限制同時連接配接的客戶數量。當連接配接數超過這個值時,redis 将不再接收其他連接配接請求,用戶端嘗試連接配接時将收到error 資訊。預設為10000,要考慮系統檔案描述符限制,不宜過大,浪費檔案描述符,具體多少根據具體情況而定

27 # maxmemory &lt;bytes&gt;

redis-cache所能使用的最大記憶體(bytes),預設為0,表示"無限制",最終由OS實體記憶體大小決定(如果實體記憶體不足,有可能會使用swap)。此值盡量不要超過機器的實體記憶體尺寸,從性能和實施的角度考慮,可以為實體記憶體3/4。此配置需要和"maxmemory-policy"配合使用,當redis中記憶體資料達到maxmemory時,觸發"清除政策"。在"記憶體不足"時,任何write操作(比如set,lpush等)都會觸發"清除政策"的執行。在實際環境中,建議redis的所有實體機器的硬體配置保持一緻(記憶體一緻),同時確定master/slave中"maxmemory""policy"配置一緻。可以使用用戶端指令config set maxmemory 去線上修改值,這個指令是立即生效的,但會在重新開機後會失效,需要使用config rewrite指令去重新整理配置檔案

當記憶體滿了的時候,如果還接收到set 指令,redis 将先嘗試剔除設定過expire 資訊的key,而不管該key 的過期時間還沒有到達。在删除時,

将按照過期時間進行删除,最早将要被過期的key 将最先被删除。如果帶有expire 資訊的key 都删光了,記憶體還不夠用,那麼将傳回錯誤。這樣,redis 将不再接收寫請求,隻接收get 請求。maxmemory 的設定比較适合于把redis 當作于類似memcached的緩存來使用。

28 # maxmemory-policy volatile-lru

記憶體不足"時,資料清除政策,預設為"volatile-lru"。

volatile-lru  -&gt;對"過期集合"中的資料采取LRU(近期最少使用)算法.如果對key使用"expire"指令指定了過期時間,那麼此key将會被添加到"過期集合"中。将已經過期/LRU的資料優先移除.如果"過期集合"中全部移除仍不能滿足記憶體需求,将OOM.

allkeys-lru -&gt;對所有的資料,采用LRU算法

volatile-random -&gt;對"過期集合"中的資料采取"随即選取"算法,并移除選中的K-V,直到"記憶體足夠"為止. 如果如果"過期集合"中全部移除全部移除仍不能滿足,将OOM

allkeys-random -&gt;對所有的資料,采取"随機選取"算法,并移除選中的K-V,直到"記憶體足夠"為止

volatile-ttl -&gt;對"過期集合"中的資料采取TTL算法(最小存活時間),移除即将過期的資料.

noeviction -&gt;不做任何幹擾操作,直接傳回OOM異常

另外,如果資料的過期不會對"應用系統"帶來異常,且系統中write操作比較密集,建議采取"allkeys-lru"

29 # maxmemory-samples 3

預設值3,上面LRU和最小TTL政策并非嚴謹的政策,而是大約估算的方式,是以可以選擇取樣值以便檢查

29 appendonly no

aof持久化開關,預設情況下,redis 會在背景異步的把資料庫鏡像備份到磁盤,但是該備份是非常耗時的,而且備份也不能很頻繁。是以redis 提供了另外一種更加高效的資料庫備份及災難恢複方式。開啟append only 模式之後,redis 會把所接收到的每一次寫操作請求都追加到appendonly.aof 檔案中,當redis 重新啟動時,會從該檔案恢複出之前的狀态。但是這樣會造成appendonly.aof 檔案過大,是以redis 還支援了BGREWRITEAOF 指令,對appendonly.aof 進行重新整理。如果不經常進行資料遷移操作,推薦生産環境下的做法為關閉鏡像,開啟appendonly.aof,同時可以選擇在通路較少的時間每天對appendonly.aof 進行重寫一次。

另外,對master機器,主要負責寫,建議使用AOF,對于slave,主要負責讀,挑選出1-2台開啟AOF,其餘的建議關閉

30 # appendfilename appendonly.aof

aof檔案名字,預設為appendonly.aof

31 

# appendfsync always

appendfsync everysec

# appendfsync no

設定對appendonly.aof 檔案進行同步的頻率。always 表示每次有寫操作都進行同步,everysec 表示對寫操作進行累積,每秒同步一次。no不主動fsync,由OS自己來完成。這個需要根據實際業務場景進行配置

32 no-appendfsync-on-rewrite no

在aof rewrite期間,是否對aof新記錄的append暫緩使用檔案同步政策,主要考慮磁盤IO開支和請求阻塞時間。預設為no,表示"不暫緩",新的aof記錄仍然會被立即同步

33 auto-aof-rewrite-percentage 100

當Aof log增長超過指定比例時,重寫log file, 設定為0表示不自動重寫Aof 日志,重寫是為了使aof體積保持最小,而確定儲存最完整的資料。

34 auto-aof-rewrite-min-size 64mb

觸發aof rewrite的最小檔案尺寸

35 lua-time-limit 5000

lua腳本運作的最大時間

36 slowlog-log-slower-than 10000

"慢記錄檔"記錄,機關:微秒(百萬分之一秒,1000 * 1000),如果操作時間超過此值,将會把command資訊"記錄"起來.(記憶體,非檔案)。其中"操作時間"不包括網絡IO開支,隻包括請求達到server後進行"記憶體實施"的時間."0"表示記錄全部操作

37 slowlog-max-len 128

"慢記錄檔"保留的最大條數,"記錄"将會被隊列化,如果超過了此長度,舊記錄将會被移除。可以通過"SLOWLOG &lt;subcommand&gt; args"檢視慢記錄的資訊(SLOWLOG get 10,SLOWLOG reset)

38

 hash-max-ziplist-entries 512

hash類型的資料結構在編碼上可以使用ziplist和hashtable。ziplist的特點就是檔案存儲(以及記憶體存儲)所需的空間較小,在内容較小時,性能和hashtable幾乎一樣.是以redis對hash類型預設采取ziplist。如果hash中條目的條目個數或者value長度達到閥值,将會被重構為hashtable。

這個參數指的是ziplist中允許存儲的最大條目個數,,預設為512,建議為128

hash-max-ziplist-value 64

ziplist中允許條目value值最大位元組數,預設為64,建議為1024

39 

list-max-ziplist-entries 512

list-max-ziplist-value 64

對于list類型,将會采取ziplist,linkedlist兩種編碼類型。解釋同上。

40 set-max-intset-entries 512

intset中允許儲存的最大條目個數,如果達到閥值,intset将會被重構為hashtable

41 

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

zset為有序集合,有2中編碼類型:ziplist,skiplist。因為"排序"将會消耗額外的性能,當zset中資料較多時,将會被重構為skiplist。

42 activerehashing yes

是否開啟頂層資料結構的rehash功能,如果記憶體允許,請開啟。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進行的互動中,每個連接配接都會與一個buffer關聯,此buffer用來隊列化等待被client接受的響應資訊。如果client不能及時的消費響應資訊,那麼buffer将會被不斷積壓而給server帶來記憶體壓力.如果buffer中積壓的資料達到閥值,将會導緻連接配接被關閉,buffer被移除。

buffer控制類型包括:normal -&gt; 普通連接配接;slave -&gt;與slave之間的連接配接;pubsub -&gt;pub/sub類型連接配接,此類型的連接配接,往往會産生此種問題;因為pub端會密集的釋出消息,但是sub端可能消費不足.

指令格式:client-output-buffer-limit &lt;class&gt; &lt;hard&gt; &lt;soft&gt; &lt;seconds&gt;",其中hard表示buffer最大值,一旦達到閥值将立即關閉連接配接;

soft表示"容忍值",它和seconds配合,如果buffer值超過soft且持續時間達到了seconds,也将立即關閉連接配接,如果超過了soft但是在seconds之後,buffer資料小于了soft,連接配接将會被保留.

其中hard和soft都設定為0,則表示禁用buffer控制.通常hard值大于soft.

44 hz 10

Redis server執行背景任務的頻率,預設為10,此值越大表示redis對"間歇性task"的執行次數越頻繁(次數/秒)。"間歇性task"包括"過期集合"檢測、關閉"空閑逾時"的連接配接等,此值必須大于0且小于500。此值過小就意味着更多的cpu周期消耗,背景task被輪詢的次數更頻繁。此值過大意味着"記憶體敏感"性較差。建議采用預設值。

45 

# include /path/to/local.conf

# include /path/to/other.conf

額外載入配置檔案。

------------------------------------------------------------------------------------

然後來看看啟動

<code>#使用配置檔案啟動redis</code>

<code>redis-server /(自定義路徑)</code><code>/redis</code><code>.conf</code>

<code>#然後測試下能不能用</code>

<code>redis-cli -p 6379(指定的端口号,可不填,即預設) -a </code><code>"密碼"</code> <code>[-c </code><code>"指令"</code><code>(可選,非互動式操作)]</code>

<code>set</code> <code>mykey  </code><code>"hi"</code>

<code>ok</code>

<code>get mykey</code>

<code>"hi"</code>

<code>#關閉redis</code>

<code>redis-cli </code><code>shutdown</code>

<code>#或</code>

<code>kill</code> <code>pid</code>

注意:在重新開機伺服器之前,需要在Redis-cli工具上輸入shutdown save指令,意思是強制讓Redis資料庫執行儲存操作并關閉Redis服務,這樣做能保證在執行Redis關閉時不丢失任何資料。 

操作

 首先來看看指令行終端輸出模式操作介紹:

<code>#在Shell指令行下啟動Redis用戶端工具。</code>

<code>redis-cli -h 127.0.0.1 -p 6379 -a </code><code>'********'</code>  

<code>#清空目前選擇的資料庫,以便于對後面示例的了解。</code>

<code>redis 127.0.0.1:6379&gt; flushdb</code>

<code>OK</code>

<code>#添加String類型的模拟資料。</code>

<code>redis 127.0.0.1:6379&gt; </code><code>set</code> <code>mykey 2</code>

<code>redis 127.0.0.1:6379&gt; </code><code>set</code> <code>mykey2 </code><code>"hello"</code>

<code>#添加Set類型的模拟資料。</code>

<code>redis 127.0.0.1:6379&gt; sadd mysetkey 1 2 3</code>

<code>(integer) 3</code>

<code>#添加Hash類型的模拟資料。</code>

<code>redis 127.0.0.1:6379&gt; hset mmtest username </code><code>"stephen"</code>

<code>(integer) 1</code>

<code>#根據參數中的模式,擷取目前資料庫中符合該模式的所有key,從輸出可以看出,該指令在執行時并不區分與Key關聯的Value類型。</code>

<code>redis 127.0.0.1:6379&gt; keys my*</code>

<code>1) </code><code>"mysetkey"</code>

<code>2) </code><code>"mykey"</code>

<code>3) </code><code>"mykey2"</code>

<code>#删除了兩個Keys。</code>

<code>redis 127.0.0.1:6379&gt; del mykey mykey2</code>

<code>(integer) 2</code>

<code>#檢視一下剛剛删除的Key是否還存在,從傳回結果看,mykey确實已經删除了。</code>

<code>redis 127.0.0.1:6379&gt; exists mykey</code>

<code>(integer) 0</code>

<code>#檢視一下沒有删除的Key,以和上面的指令結果進行比較。</code>

<code>redis 127.0.0.1:6379&gt; exists mysetkey</code>

<code>#将目前資料庫中的mysetkey鍵移入到ID為1的資料庫中,從結果可以看出已經移動成功。</code>

<code>redis 127.0.0.1:6379&gt; move mysetkey 1</code>

<code>#打開ID為1的資料庫。</code>

<code>redis 127.0.0.1:6379&gt; </code><code>select</code> <code>1</code>

<code>#檢視一下剛剛移動過來的Key是否存在,從傳回結果看已經存在了。</code>

<code>redis 127.0.0.1:6379[1]&gt; exists mysetkey</code>

<code>#在重新打開ID為0的預設資料庫。</code>

<code>redis 127.0.0.1:6379[1]&gt; </code><code>select</code> <code>0</code>

<code>#檢視一下剛剛移走的Key是否已經不存在,從傳回結果看已經移走。</code>

<code>#準備新的測試資料。    </code>

<code>redis 127.0.0.1:6379&gt; </code><code>set</code> <code>mykey </code><code>"hello"</code>

<code>#将mykey改名為mykey1</code>

<code>redis 127.0.0.1:6379&gt; rename mykey mykey1</code>

<code>#由于mykey已經被重新命名,再次擷取将傳回nil。</code>

<code>redis 127.0.0.1:6379&gt; get mykey</code>

<code>(nil)</code>

<code>#通過新的鍵名擷取。</code>

<code>redis 127.0.0.1:6379&gt; get mykey1</code>

<code>"hello"</code>

<code>#由于mykey已經不存在了,是以傳回錯誤資訊。</code>

<code>(error) ERR no such key</code>

<code>#為renamenx準備測試key</code>

<code>redis 127.0.0.1:6379&gt; </code><code>set</code> <code>oldkey </code><code>"hello"</code>

<code>redis 127.0.0.1:6379&gt; </code><code>set</code> <code>newkey </code><code>"world"</code>

<code>#由于newkey已經存在,是以該指令未能成功執行。</code>

<code>redis 127.0.0.1:6379&gt; renamenx oldkey newkey</code>

<code>#檢視newkey的值,發現它也沒有被renamenx覆寫。</code>

<code>redis 127.0.0.1:6379&gt; get newkey</code>

<code>"world"</code>

<code>        </code> 

<code>2. PERSIST</code><code>/EXPIRE/EXPIREAT/TTL</code><code>:    </code>

<code>#為後面的示例準備的測試資料。</code>

<code>#将該鍵的逾時設定為100秒。</code>

<code>redis 127.0.0.1:6379&gt; expire mykey 100</code>

<code>#通過ttl指令檢視一下還剩下多少秒。</code>

<code>redis 127.0.0.1:6379&gt; ttl mykey</code>

<code>(integer) 97</code>

<code>#立刻執行persist指令,該存在逾時的鍵變成持久化的鍵,即将該Key的逾時去掉。</code>

<code>redis 127.0.0.1:6379&gt; persist mykey</code>

<code>#ttl的傳回值告訴我們,該鍵已經沒有逾時了。</code>

<code>(integer) -1</code>

<code>#為後面的expire指令準備資料。</code>

<code>redis 127.0.0.1:6379&gt; del mykey</code>

<code>#設定該鍵的逾時被100秒。</code>

<code>#用ttl指令看一下目前還剩下多少秒,從結果中可以看出還剩下96秒。</code>

<code>(integer) 96</code>

<code>#重新更新該鍵的逾時時間為20秒,從傳回值可以看出該指令執行成功。</code>

<code>redis 127.0.0.1:6379&gt; expire mykey 20</code>

<code>#再用ttl确認一下,從結果中可以看出果然被更新了。</code>

<code>(integer) 17</code>

<code>#立刻更新該鍵的值,以使其逾時無效。</code>

<code>redis 127.0.0.1:6379&gt; </code><code>set</code> <code>mykey </code><code>"world"</code>

<code>#從ttl的結果可以看出,在上一條修改該鍵的指令執行後,該鍵的逾時也無效了。</code>

<code>3. TYPE</code><code>/RANDOMKEY/SORT</code><code>:</code>

<code>#由于mm鍵在資料庫中不存在,是以該指令傳回none。</code>

<code>redis 127.0.0.1:6379&gt; </code><code>type</code> <code>mm</code>

<code>none</code>

<code>#mykey的值是字元串類型,是以傳回string。</code>

<code>redis 127.0.0.1:6379&gt; </code><code>type</code> <code>mykey</code>

<code>string</code>

<code>#準備一個值是set類型的鍵。</code>

<code>redis 127.0.0.1:6379&gt; sadd mysetkey 1 2</code>

<code>#mysetkey的鍵是set,是以傳回字元串set。</code>

<code>redis 127.0.0.1:6379&gt; </code><code>type</code> <code>mysetkey</code>

<code>set</code>

<code>#傳回資料庫中的任意鍵。</code>

<code>redis 127.0.0.1:6379&gt; randomkey</code>

<code>"oldkey"</code>

<code>#清空目前打開的資料庫。</code>

<code>#由于沒有資料了,是以傳回nil。</code>

上面這些隻是一部分的用法,但是對于一般測試就足夠了?,其他還有list用法和hash用法什麼的,有興趣可以更加深入研究.

--------------------------------------------------------

類似于tail和tailf的概念,終端輸出模式就是一直連線,而下面的指令結果輸出模式就是指令執行就出一個結果,不會繼續連線.

下面來看指令結果輸出模式:

redis-cli參數

-h    設定檢測主機IP位址,預設為127.0.0.1

-p    設定檢測主機的端口号,預設為6379    

-s&lt;socket&gt;    伺服器套接字(壓倒主機和端口)    

-a    連接配接到Master伺服器時使用的密碼    

-r    執行指定的N次指令    

-i    執行指令後等待N秒,如–i 0.1 info(執行後等0.1秒)    

-n    指定連接配接N号ID資料庫,如 –n 3(連接配接3号資料庫)    

-x    從控制台輸入的資訊中讀取最後一個參數    

-d    定義多個定界符為預設輸出格式(預設: \n)    

--raw    使用原資料格式傳回輸出内容    

--latency    進入一個不斷延時采樣的特殊模式    

--slave    模拟一個從伺服器到主伺服器的指令顯示回報    

--pipe    使用管道協定模式    

--bigkeys    監聽顯示資料量大的key值,--bigkeys -i 0.1     

--help    顯示指令行幫助資訊    

--version    顯示版本号    

例子:

<code>$ redis-cli進入指令行模式</code>

<code>$ redis-cli -n 3 </code><code>set</code> <code>mykey </code><code>"hi"</code> <code>把mykey插入到第三個資料庫</code>

<code>$ redis-cli -r 3 info 重複執行info指令三次</code>

<code>下面還有一些比較特别的用法</code>

<code>GETSET: .</code><code>/redis-cli</code> <code>getset nid 987654321 </code>

<code># 表示傳回指定key的原始值,并指定一個新值給他 </code>

<code>MGET: .</code><code>/redis-cli</code> <code>mget nid uid … </code>

<code># 表示擷取多個key的值 </code>

<code>SETNX: .</code><code>/redis-cli</code> <code>setnx nnid 888888 </code>

<code># 表示當一個指定的key不存在時,設定這個key指定的value,如果存在,則設定不成功 </code>

<code>SETEX: .</code><code>/redis-cli</code> <code>setex nid 5 666666 </code>

<code># 表示設定一個key指定的value儲存5秒後失效,設定key/value的有效期 </code>

<code>MSET: .</code><code>/redis-cli</code> <code>mset nid0001 </code><code>"0001"</code> <code>nid0002 </code><code>"0002"</code> <code>nid0003 </code><code>"0003"</code>

<code># 表示多鍵值對的資料儲存 </code>

<code>INCR: .</code><code>/redis-cli</code> <code>incr count </code>

<code># 表示對給定key的value進行遞增(+1)的操作,當然value必須是一個integer </code>

<code>INCRBY: .</code><code>/redis-cli</code> <code>incrby count 5 </code>

<code># 表示對給定key的value進行指定步長的遞增操作 </code>

<code>DECR: .</code><code>/redis-cli</code> <code>decr count </code>

<code># 表示對給定key的value進行遞減(-1)的操作 </code>

<code>DECRBY: .</code><code>/redis-cli</code> <code>decrby count 7 </code>

<code># 表示對給定key的value進行指定步長的遞減操作 </code>

<code>APPEND: .</code><code>/redis-cli</code> <code>append content </code><code>"bad"</code>   <code>或者  .</code><code>/redis-cli</code> <code>append content </code><code>"good"</code>

<code># 表示追加一個value到指定的key中,如果key不存在,則建立key </code>

<code>SUBSTR: .</code><code>/redis-cli</code> <code>substr content 0 4 </code>

<code># 表示傳回指定key的value的部分字元串</code>

<code># 清單操作,精華 </code>

<code>RPUSH key string — 将某個值加入到一個key清單末尾 </code>

<code>LPUSH key string — 将某個值加入到一個key清單頭部 </code>

<code>LLEN key — 清單長度 </code>

<code>LRANGE key start end — 傳回清單中某個範圍的值,相當于mysql裡面的分頁查詢那樣 </code>

<code>LTRIM key start end — 隻保留清單中某個範圍的值 </code>

<code>LINDEX key index — 擷取清單中特定索引号的值,要注意是O(n)複雜度 </code>

<code>LSET key index value — 設定清單中某個位置的值 </code>

<code>RPOP key </code>

<code># 集合操作 </code>

<code>SADD key member — 增加元素 </code>

<code>SREM key member — 删除元素 </code>

<code>SCARD key — 傳回集合大小 </code>

<code>SISMEMBER key member — 判斷某個值是否在集合中 </code>

<code>SINTER key1 key2 ... keyN — 擷取多個集合的交集元素 </code>

<code>SMEMBERS key — 列出集合的所有元素 ?</code>

<code>更新日志檢查 ,加--fix參數為修複log檔案</code>

<code>redis-check-aof appendonly.aof</code>

<code>檢查本地資料庫檔案</code>

<code>redis-check-dump  dump.rdb</code>

========================================================

壓力測試

redis測試分兩種說法,第一種就是并發壓力,另一種就是容量壓力了,

并發壓力可以用redis自帶的軟體redis-benchmark來測試?,具體如下:

redis-benchmark參數

-h    設定檢測主機IP位址,預設為127.0.0.1    

-c    并發連接配接數    

-n    請求數    

-d    測試使用的資料集的大小/位元組的值(預設3位元組)    

-k    1:表示保持連接配接(預設值)0:重新連接配接    

-r    SET/GET/INCR方法使用随機數插入數值,設定10則插入值為rand:000000000000 - rand:000000000009    

-P    預設為1(無管道),當網絡延遲過長時,使用管道方式通信(請求和響應打包發送接收)    

-q    簡約資訊模式,隻顯示查詢和秒值等基本資訊。    

--csv    以CSV格式輸出資訊    

-l    無線循環插入測試資料,ctrl+c停止    

-t&lt;tests&gt;    隻運作&lt;tests&gt;測試逗号分隔的清單指令,如:-t ping,set,get    

-I    空閑模式。立即打開50個空閑連接配接和等待。   

例子: 

<code>redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100  </code>

<code>SET</code><code>/GET</code> <code>100 bytes 檢測host為127.0.0.1 端口為6379的redis伺服器性能</code>

<code>redis-benchmark -h 127.0.0.1 -p 6379 -c 5000 -n 100000 </code>

<code>5000個并發連接配接,100000個請求,檢測host為127.0.0.1 端口為6379的redis伺服器性能 </code>

<code>我們來詳細解析下這條語句的意思:</code>

<code>redis-benchmark -n 100000 -c 60</code>

<code>向redis伺服器發送100000個請求,每個請求附帶60個并發用戶端</code>

結果(部分):

====== SET ======

對集合寫入測試

  100000 requests completed in 2.38 seconds

100000個請求在2.38秒内完成

  60 parallel clients

每次請求有60個并發用戶端

  3 bytes payload

每次寫入3個位元組的資料

  keep alive: 1

保持一個連接配接,一台伺服器來處理這些請求

100.00% &lt;= 62 milliseconds

所有請求在62毫秒内完成

42105.26 requests per second

每秒處理42105.26次請求

還是比較直覺的

-----------------------------------

然後說說容量測試,其實很好了解,記憶體不是無限的,存放資料自然就是有限,雖然說可以去配置檔案去用淘汰機制限制,但是知道容量頂點還是能解決不少問題.

順便也說說,要是你設定的maxmemory 容量不夠,或者整個記憶體都不夠,而又沒有使用有效的LRU配置,那麼你的redis寫滿了之後會提示OOM,就是說記憶體不夠用,寫不進新資料.

說的就是maxmemory-policy這個設定,具體怎麼設定才是合理的,則需要從業務層面去考慮了,例如說丢了一些舊key也沒所謂的,allkeys-lru就是最好了,嚴格來或,你用了這個政策其實也不用測試了,因為他會自動删舊key,沒什麼頂不頂點的概念在..

測試容量的方法很簡單,就是不停的往裡面寫資料,然後看他頂點是多少.? 

參考腳本如下:

<code>#!/bin/sh</code>

<code>keyset=</code><code>"keytest5"</code>

<code>valueset=</code><code>'模拟資料,随便你寫'</code>

<code>dbname=5</code>

<code>a=0</code>

<code>for</code> <code>i </code><code>in</code> <code>`</code><code>seq</code> <code>1 300000`</code>

<code>do</code>

<code>redis-cli -n $dbname </code><code>'set'</code> <code>${keyset}${a} </code><code>"${valueset}${a}"</code> <code>&gt;</code><code>/dev/null</code>

<code>#echo $a</code>

<code>let</code> <code>a++</code>

<code>done</code>

測試結果很簡單,看info的最後一個結果就好了,哪裡會有顯示現在有多少個key在.

性能分析

info資訊:

在redis-cli進入登入界面後,輸入info,或者redis-cli -h ${ip} -p ${post} -a "${pass}" -c info

之後,就會擷取所有與Redis服務相關的實時性能資訊,類似于linux指令top那樣的東西.

info指令輸出的資料可分為10個類别,分别是:

server

clients

memory

persistence

stats

replication

cpu

commandstats

cluster

keyspace

現在主要介紹比較重要的2部分性能名額memory和stats.

maxmemory/maxmemory_human:    配置檔案redis.conf限制的可配置設定的最大記憶體總量

used_memory/used_memory_human:    目前redis實際使用的記憶體總量,如果used_memory &gt; maxmemory ,那麼作業系統開始進行記憶體與swap空間交換,以便騰出新的實體記憶體給新頁或活動頁(page)使用,那是有多糟糕大家可以想得到.

used_memory_rss/used_memory_rss_human:    從作業系統上顯示已經配置設定的記憶體總量,比used_memory多出來的就可能是碎片.

mem_fragmentation_ratio:    記憶體碎片率,記憶體碎片率稍大于1是合理的,說明redis沒有發生記憶體交換,如果記憶體碎片率超過1.5,那就說明Redis消耗了實際需要實體記憶體的150%,其中50%是記憶體碎片率。若是記憶體碎片率低于1的話,說明Redis記憶體配置設定超出了實體記憶體,作業系統正在進行記憶體交換。記憶體交換會引起非常明顯的響應延遲.

    下面是計算公式:

    當碎片率出現問題,有3種方法解決記憶體管理變差的問題,提高redis性能:

        1. 重新開機Redis伺服器:如果記憶體碎片率超過1.5,重新開機Redis伺服器可以讓額外産生的記憶體碎片失效并重新作為新記憶體來使用,使作業系統恢複高效的記憶體管理。

        2.限制記憶體交換: 如果記憶體碎片率低于1,Redis執行個體可能會把部分資料交換到硬碟上。記憶體交換會嚴重影響Redis的性能,是以應該增加可用實體記憶體或減少實Redis記憶體占用

        3.修改記憶體配置設定器:

Redis支援glibc’s malloc、jemalloc11、tcmalloc幾種不同的記憶體配置設定器,每個配置設定器在記憶體配置設定和碎片上都有不同的實作。不建議普通管理者修改Redis預設記憶體配置設定器,因為這需要完全了解這幾種記憶體配置設定器的差異,也要重新編譯Redis。

used_memory_lua:    Lua腳本引擎所使用的記憶體大小。redis預設允許使用lua腳本,不過太多了的話就占用了可用記憶體

mem_allocator:    在編譯時指定的Redis使用的記憶體配置設定器,可以是libc、jemalloc、tcmalloc.

total_commands_processed:    顯示了Redis服務處理指令的總數,且值是遞增的.因為Redis是個單線程模型,用戶端過來的指令是按照順序執行的,如果指令隊列裡等待處理的指令數量比較多,指令的響應時間就變慢,甚至于後面的指令完全被阻塞,導緻Redis性能降低.是以這個時候就需要記錄這個參數的值,是不是增長過快,導緻了性能降低.

evicted_keys:    顯示因為maxmemory限制導緻key被回收删除的數量.根據配置檔案中設定maxmemory-policy值來确定Redis是使用lru政策還是過期時間政策.如果是過期回收的,不會被記錄在這裡,通常這個值不為0,那就要考慮增加記憶體限制,不然就會造成記憶體交換,輕則性能變差,重則丢資料.

---------------------------------------------------------------------------------------------------

其他分析方法:

Redis的延遲資料是無法從info資訊中擷取的。倘若想要檢視延遲時間,可以用 Redis-cli工具加--latency參數運作

redis-cli --latency -h 127.0.0.1 -p 6379

他将會持續掃描延遲時間,直到按ctrl+C退出,以毫秒為機關測量Redis的響應延遲時間,由于伺服器不同的運作情況,延遲時間可能有所誤差,通常1G網卡的延遲時間是0.2毫秒,若延時值遠高于這個參考值,那明顯是有性能問題了。也可以通過下面方法來分析延時慢的原因:

使用slowlog查出引發延遲的慢指令:Redis中的slowlog指令可以讓我們快速定位到那些超出指定執行時間的慢指令,預設情況下指令若是執行時間超過10ms就會被記錄到日志,最多記錄128條,超過就删除,可通過參數slowlog-log-slower-than和slowlog-max-len來修改這個時間和限制條數。通常1gb帶寬的網絡延遲,預期在0.2ms左右,倘若一個指令僅執行時間就超過10ms,那比網絡延遲慢了近50倍。可以通過使用Redis-cli工具,輸入slowlog get指令檢視,傳回結果的第三個字段以微妙位機關顯示指令的執行時間。假如隻需要檢視最後3個慢指令,輸入slowlog get 10即可。

<code>127.0.0.1:6379&gt; slowlog get 10</code>

<code>    </code><code>.</code>

<code>4) 1) (integer) 215</code>

<code>    </code><code>2) (integer) 1489099695</code>

<code>    </code><code>3) (integer) 11983</code>

<code>    </code><code>4) 1) </code><code>"SADD"</code>

<code>       </code><code>2) </code><code>"USER_TOKEN_MAP51193"</code>

<code>       </code><code>3) </code><code>"qIzwZKBmBJozKprQgoTEI3Qo8QO2Fi!4"</code>

<code> </code><code>5) 1) (integer) 214</code>

<code>    </code><code>2) (integer) 1489087112</code>

<code>    </code><code>3) (integer) 18002</code>

<code>       </code><code>2) </code><code>"USER_TOKEN_MAP51192"</code>

<code>       </code><code>3) </code><code>"Z3Hs!iTUNfweqvLLf!ptdchSV2JAOrrH"</code>

<code> </code><code>6) 1) (integer) 213</code>

<code>    </code><code>2) (integer) 1489069123</code>

<code>    </code><code>3) (integer) 15407</code>

<code>       </code><code>2) </code><code>"USER_TOKEN_MAP51191"</code>

<code>       </code><code>3) </code><code>"S3rNzOBwUlaI3QfOK9dIITB6Bk7LIGYe"</code>

1=日志的唯一辨別符

2=被記錄指令的執行時間點,以 UNIX 時間戳格式表示

3=查詢執行時間,以微秒為機關。例子中指令使用11毫秒。

4= 執行的指令,以數組的形式排列。完整指令是拼在一起.

監控用戶端的連接配接:因為Redis是單線程模型(隻能使用單核),來處理所有用戶端的請求, 但由于用戶端連接配接數的增長,處理請求的線程資源開始降低配置設定給單個用戶端連接配接的處理時間,這時每個用戶端需要花費更多的時間去等待Redis共享服務的響應。

<code>#檢視用戶端連接配接狀态</code>

<code>127.0.0.1:6379&gt; info clients</code>

<code># Clients</code>

<code>connected_clients:11</code>

<code>client_longest_output_list:0</code>

<code>client_biggest_input_buf:0</code>

<code>blocked_clients:0</code>

<code>#檢視每一個用戶端的狀态,全部都顯示出來(慎用),注意很長,</code>

<code>127.0.0.1:6379&gt; client list</code>

<code>id</code><code>=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-</code><code>free</code><code>=0 obl=0 oll=0 omem=0 events=r cmd=</code><code>ping</code>

第一個字段(connected_clients)顯示目前執行個體用戶端連接配接的總數,Redis預設允許用戶端連接配接的最大數量是10000。若是看到連接配接數超過5000以上,那可能會影響Redis的性能。倘若一些或大部分用戶端發送大量的指令過來,這個數字會低的多。

還有些簡單舉例下:

<code>#統計生産上比較大的key</code>

<code>redis-cli -h* -a* -p* --bigkeys</code>

<code>#檢視某個key的持續時間</code>

<code>127.0.0.1:6379&gt; OBJECT IDLETIME key名字</code>

資料持久化引發的延遲

Redis的資料持久化工作本身就會帶來延遲,需要根據資料的安全級别和性能要求制定合理的持久化政策:

1.AOF + fsync always的設定雖然能夠絕對確定資料安全,但每個操作都會觸發一次fsync,會對Redis的性能有比較明顯的影響

2.AOF + fsync every second是比較好的折中方案,每秒fsync一次

3.AOF + fsync never會提供AOF持久化方案下的最優性能,使用RDB持久化通常會提供比使用AOF更高的性能,但需要注意RDB的政策配置

4.每一次RDB快照和AOF Rewrite都需要Redis主程序進行fork操作。fork操作本身可能會産生較高的耗時,與CPU和Redis占用的記憶體大小有關。根據具體的情況合理配置RDB快照和AOF Rewrite時機,避免過于頻繁的fork帶來的延遲.

例如:Redis在fork子程序時需要将記憶體分頁表拷貝至子程序,以占用了24GB記憶體的Redis執行個體為例,共需要拷貝24GB / 4kB * 8 = 48MB的資料。在使用單Xeon 2.27Ghz的實體機上,這一fork操作耗時216ms。

可以通過INFO指令傳回的latest_fork_usec字段檢視上一次fork操作的耗時(微秒)。

Swap引發的延遲

當Linux将Redis所用的記憶體分頁移至swap空間時,将會阻塞Redis程序,導緻Redis出現不正常的延遲。Swap通常在實體記憶體不足或一些程序在進行大量I/O操作時發生,應盡可能避免上述兩種情況的出現。

在/proc/redis程序号/smaps檔案中會儲存程序的swap記錄,通過檢視這個檔案,能夠判斷Redis的延遲是否由Swap産生。如果這個檔案中記錄了較大的Swap size,則說明延遲很有可能是Swap造成的。

例子如下,可以看到目前swap的狀态時0KB,也就是沒用到swap,

<code>#/proc/pid/smaps顯示了程序運作時的記憶體影響,系統的運作時庫(so),堆,棧資訊均可在其中看到。</code>

<code>cat</code> <code>/proc/</code><code>`</code><code>ps</code> <code>aux |</code><code>grep</code> <code>redis |</code><code>grep</code> <code>-</code><code>v</code> <code>grep</code> <code>|</code><code>awk</code> <code>'{print $2}'</code><code>`</code><code>/smaps</code>

<code>00400000-00531000 r-xp 00000000 fc:02 805438521 </code><code>/usr/local/bin/redis-server</code>

<code>Size:               1220 kB</code>

<code>Rss:                 924 kB</code>

<code>Pss:                 924 kB</code>

<code>Shared_Clean:          0 kB</code>

<code>Shared_Dirty:          0 kB</code>

<code>Private_Clean:       924 kB</code>

<code>Private_Dirty:         0 kB</code>

<code>Referenced:          924 kB</code>

<code>Anonymous:             0 kB</code>

<code>AnonHugePages:         0 kB</code>

<code>Shared_Hugetlb:        0 kB</code>

<code>Private_Hugetlb:       0 kB</code>

<code>Swap:                  0 kB</code>

<code>SwapPss:               0 kB</code>

<code>KernelPageSize:        4 kB</code>

<code>MMUPageSize:           4 kB</code>

<code>Locked:                0 kB</code>

優化建議

系統優化

1.關閉Transparent huge pages

Transparent HugePages會讓核心khugepaged線程在運作時動态配置設定記憶體。在大部分linux發行版本中預設是啟用的,缺點是可能會造成記憶體在運作時的延遲配置設定,對于大記憶體應用并不友好,例如:oracle,redis等會占用大量記憶體的應用,是以建議關閉。

<code>#關閉Transparent HugePages,預設狀态是[always]</code>

<code>echo</code> <code>never &gt; </code><code>/sys/kernel/mm/transparent_hugepage/enabled</code>

2.在實體機部署redis,這點不用多說了,虛拟機或者是docker都會有一定的延時,沒有必要為了好管理二浪費這些性能。

3.多用連接配接池,而不是頻繁斷開再連接配接,效果我想不言而喻。

4.用戶端進行的批量資料操作,應使用Pipeline特性在一次互動中完成。

行為優化

1.假如緩存資料小于4GB,可以選擇使用32位的Redis執行個體。因為32位執行個體上的指針大小隻有64位的一半,它的記憶體空間占用空間會更少些。Redis的dump檔案在32位和64位之間是互相相容的, 是以倘若有減少占用記憶體空間的需求,可以嘗試先使用32位,後面再切換到64位上。

2.盡可能的使用Hash資料結構。因為Redis在儲存小于100個字段的Hash結構上,其存儲效率是非常高的。是以在不需要集合(set)操作或list的push/pop操作的時候,盡可能的使用Hash結構。Hash結構的操作指令是HSET(key, fields, value)和HGET(key, field),使用它可以存儲或從Hash中取出指定的字段。

3.盡量設定key的過期時間。一個減少記憶體使用率的簡單方法就是,每當存儲對象時確定設定key的過期時間。倘若key在明确的時間周期内使用或者舊key不大可能被使用時,就可以用Redis過期時間指令(expire,expireat, pexpire, pexpireat)去設定過期時間,這樣Redis會在key過期時自動删除key.用ttl指令可以查詢過期時間,機關是秒,顯示-2代表key不存在,顯示-1代表沒有設定逾時時間(也就是永久的). 

4.使用多參數指令:若是用戶端在很短的時間内發送大量的指令過來,會發現響應時間明顯變慢,這由于後面指令一直在等待隊列中前面大量指令執行完畢。舉例來說,循環使用LSET指令去添加1000個元素到list結構中,是性能比較差的一種方式,更好的做法是在用戶端建立一個1000元素的清單,用單個指令LPUSH或RPUSH,通過多參數構造形式一次性把1000個元素發送的Redis服務上。

5.管道指令:另一個減少多指令的方法是使用管道(pipeline),把幾個指令合并一起執行,進而減少因網絡開銷引起的延遲問題。因為10個指令單獨發送到服務端會引起10次網絡延遲開銷,使用管道會一次性把執行結果傳回,僅需要一次網絡延遲開銷。Redis本身支援管道指令,大多數用戶端也支援,倘若目前執行個體延遲很明顯,那麼使用管道去降低延遲是非常有效的。

6.避免操作大集合的慢指令:如果指令處理頻率過低導緻延遲時間增加,這可能是因為使用了高時間複雜度的指令操作導緻,這意味着每個指令從集合中擷取資料的時間增大。 是以減少使用高時間複雜的指令,能顯著的提高的Redis的性能。

7.限制用戶端連接配接數:自Redis2.6以後,允許使用者在配置檔案(Redis.conf)maxclients屬性上修改用戶端連接配接的最大數,也可以通過在Redis-cli工具上輸入config set maxclients 去設定最大連接配接數。根據連接配接數負載的情況,這個數字應該設定為預期連接配接數峰值的110%到150之間,若是連接配接數超出這個數字後,Redis會拒絕并立刻關閉新來的連接配接。通過設定最大連接配接數來限制非預期數量的連接配接數增長,是非常重要的。另外,新連接配接嘗試失敗會傳回一個錯誤消息,這可以讓用戶端知道,Redis此時有非預期數量的連接配接數,以便執行對應的處理措施。 上述二種做法對控制連接配接數的數量和持續保持Redis的性能最優是非常重要的

     本文轉自arthur376 51CTO部落格,原文連結:http://blog.51cto.com/arthur376/1774737,如需轉載請自行聯系原作者