這篇文章主要介紹了超強、超詳細redis入門教程,本文詳細介紹了Redis數據庫各個方面的知識,需要的朋友可以參考下
【本教程目錄】1.redis是什么2.redis的作者何許人也3.誰在使用redis4.學會安裝redis5.學會啟動redis6.使用redis客戶端7.redis數據結構 – 簡介8.redis數據結構 – strings9.redis數據結構 – lists10.redis數據結構 – 集合11.redis數據結構 – 有序集合12.redis數據結構 – 哈希13.聊聊redis持久化 – 兩種方式14.聊聊redis持久化 – RDB15.聊聊redis持久化 – AOF16.聊聊redis持久化 – AOF重寫17.聊聊redis持久化 – 如何選擇RDB和AOF18.聊聊主從 – 用法19.聊聊主從 – 同步原理20.聊聊redis的事務處理21.教你看懂redis配置 – 簡介22.教你看懂redis配置 -通用23.教你看懂redis配置 – 快照24.教你看懂redis配置 – 復制25.教你看懂redis配置 – 安全26.教你看懂redis配置 -限制27.教你看懂redis配置 – 追加模式28.教你看懂redis配置 – LUA腳本29.教你看懂redis配置 – 慢日志30.教你看懂redis配置 – 事件通知31.教你看懂redis配置 – 高級配置
【redis是什么】
redis是一個開源的、使用C語言編寫的、支持網絡交互的、可基于內存也可持久化的Key-Value數據庫。
redis的官網地址,非常好記,是redis.io。(特意查了一下,域名后綴io屬于國家域名,是british Indian Ocean territory,即英屬印度洋領地)
目前,Vmware在資助著redis項目的開發和維護。
【redis的作者何許人也】
開門見山,先看照片:
是不是出乎了你的意料,嗯,高手總會有些地方與眾不同的。
這位便是redis的作者,他叫Salvatore Sanfilippo,來自意大利的西西里島,現在居住在卡塔尼亞。目前供職于Pivotal公司。
他使用的網名是antirez,如果你有興趣,可以去他的博客逛逛,地址是antirez.com,當然也可以去follow他的github,地址是http://github.com/antirez。
【誰在使用redis】
Blizzard、digg、stackoverflow、github、flickr …
【學會安裝redis】
從redis.io下載最新版redis-X.Y.Z.tar.gz后解壓,然后進入redis-X.Y.Z文件夾后直接make即可,安裝非常簡單。
make成功后會在src文件夾下產生一些二進制可執行文件,包括redis-server、redis-cli等等:
復制代碼代碼如下:
$?find?.?-type?f?-executable ./redis-benchmark?//用于進行redis性能測試的工具 ./redis-check-dump?//用于修復出問題的dump.rdb文件 ./redis-cli?//redis的客戶端 ./redis-server?//redis的服務端 ./redis-check-aof?//用于修復出問題的AOF文件 ./redis-sentinel?//用于集群管理
?
【學會啟動redis】
啟動redis非常簡單,直接./redis-server就可以啟動服務端了,還可以用下面的方法指定要加載的配置文件:
復制代碼代碼如下:
./redis-server?../redis.conf
默認情況下,redis-server會以非daemon的方式來運行,且默認服務端口為6379。
有關作者為什么選擇6379作為默認端口,還有一段有趣的典故,英語好的同學可以看看作者這篇博文中的解釋。
【使用redis客戶端】
我們直接看一個例子:
復制代碼代碼如下:
//這樣來啟動redis客戶端了 $?./redis-cli //用set指令來設置key、value 127.0.0.1:6379>?set?name?"roc"? OK //來獲取name的值 127.0.0.1:6379>?get?name? "roc" //通過客戶端來關閉redis服務端 127.0.0.1:6379>?shutdown? 127.0.0.1:6379>
?
【redis數據結構 – 簡介】
redis是一種高級的key:value存儲系統,其中value支持五種數據類型:
1.字符串(strings)
2.字符串列表(lists)
3.字符串集合(sets)
4.有序字符串集合(sorted sets)
5.哈希(hashes)
而關于key,有幾個點要提醒大家:
1.key不要太長,盡量不要超過1024字節,這不僅消耗內存,而且會降低查找的效率;
2.key也不要太短,太短的話,key的可讀性會降低;
3.在一個項目中,key最好使用統一的命名模式,例如user:10000:passwd。
【redis數據結構 – strings】
有人說,如果只使用redis中的字符串類型,且不使用redis的持久化功能,那么,redis就和memcache非常非常的像了。這說明strings類型是一個很基礎的數據類型,也是任何存儲系統都必備的數據類型。
我們來看一個最簡單的例子:
復制代碼代碼如下:
set?mystr?"hello?world!"?//設置字符串類型 get?mystr?//讀取字符串類型
字符串類型的用法就是這么簡單,因為是二進制安全的,所以你完全可以把一個圖片文件的內容作為字符串來存儲。
另外,我們還可以通過字符串類型進行數值操作:
復制代碼代碼如下:
127.0.0.1:6379>?set?mynum?"2" OK 127.0.0.1:6379>?get?mynum "2" 127.0.0.1:6379>?incr?mynum (integer)?3 127.0.0.1:6379>?get?mynum "3"
看,在遇到數值操作時,redis會將字符串類型轉換成數值。
由于INCR等指令本身就具有原子操作的特性,所以我們完全可以利用redis的INCR、INCRBY、DECR、DECRBY等指令來實現原子計數的效果,假如,在某種場景下有3個客戶端同時讀取了mynum的值(值為2),然后對其同時進行了加1的操作,那么,最后mynum的值一定是5。不少網站都利用redis的這個特性來實現業務上的統計計數需求。
【redis數據結構 – lists】
redis的另一個重要的數據結構叫做lists,翻譯成中文叫做“列表”。
首先要明確一點,redis中的lists在底層實現上并不是數組,而是鏈表,也就是說對于一個具有上百萬個元素的lists來說,在頭部和尾部插入一個新元素,其時間復雜度是常數級別的,比如用LPUSH在10個元素的lists頭部插入新元素,和在上千萬元素的lists頭部插入新元素的速度應該是相同的。
雖然lists有這樣的優勢,但同樣有其弊端,那就是,鏈表型lists的元素定位會比較慢,而數組型lists的元素定位就會快得多。
lists的常用操作包括LPUSH、RPUSH、LRANGE等。我們可以用LPUSH在lists的左側插入一個新元素,用RPUSH在lists的右側插入一個新元素,用LRANGE命令從lists中指定一個范圍來提取元素。我們來看幾個例子:
復制代碼代碼如下:
//新建一個list叫做mylist,并在列表頭部插入元素"1" 127.0.0.1:6379>?lpush?mylist?"1"? //返回當前mylist中的元素個數 (integer)?1? //在mylist右側插入元素"2" 127.0.0.1:6379>?rpush?mylist?"2"? (integer)?2 //在mylist左側插入元素"0" 127.0.0.1:6379>?lpush?mylist?"0"? (integer)?3 //列出mylist中從編號0到編號1的元素 127.0.0.1:6379>?lrange?mylist?0?1? 1)?"0" 2)?"1" //列出mylist中從編號0到倒數第一個元素 127.0.0.1:6379>?lrange?mylist?0?-1? 1)?"0" 2)?"1" 3)?"2"
?
lists的應用相當廣泛,隨便舉幾個例子:
1.我們可以利用lists來實現一個消息隊列,而且可以確保先后順序,不必像mysql那樣還需要通過ORDER BY來進行排序。
2.利用LRANGE還可以很方便的實現分頁的功能。
3.在博客系統中,每片博文的評論也可以存入一個單獨的list中。
【redis數據結構 – 集合】
redis的集合,是一種無序的集合,集合中的元素沒有先后順序。
集合相關的操作也很豐富,如添加新元素、刪除已有元素、取交集、取并集、取差集等。我們來看例子:
復制代碼代碼如下:
//向集合myset中加入一個新元素"one" 127.0.0.1:6379>?sadd?myset?"one"? (integer)?1 127.0.0.1:6379>?sadd?myset?"two" (integer)?1 //列出集合myset中的所有元素 127.0.0.1:6379>?smembers?myset? 1)?"one" 2)?"two" //判斷元素1是否在集合myset中,返回1表示存在 127.0.0.1:6379>?sismember?myset?"one"? (integer)?1 //判斷元素3是否在集合myset中,返回0表示不存在 127.0.0.1:6379>?sismember?myset?"three"? (integer)?0 //新建一個新的集合yourset 127.0.0.1:6379>?sadd?yourset?"1"? (integer)?1 127.0.0.1:6379>?sadd?yourset?"2" (integer)?1 127.0.0.1:6379>?smembers?yourset 1)?"1" 2)?"2" //對兩個集合求并集 127.0.0.1:6379>?sunion?myset?yourset? 1)?"1" 2)?"one" 3)?"2" 4)?"two"
?
對于集合的使用,也有一些常見的方式,比如,QQ有一個社交功能叫做“好友標簽”,大家可以給你的好友貼標簽,比如“大美女”、“土豪”、“歐巴”等等,這時就可以使用redis的集合來實現,把每一個用戶的標簽都存儲在一個集合之中。
【redis數據結構 – 有序集合】
redis不但提供了無需集合(sets),還很體貼的提供了有序集合(sorted sets)。有序集合中的每個元素都關聯一個序號(score),這便是排序的依據。
很多時候,我們都將redis中的有序集合叫做zsets,這是因為在redis中,有序集合相關的操作指令都是以z開頭的,比如zrange、zadd、zrevrange、zrangebyscore等等
老規矩,我們來看幾個生動的例子:
//新增一個有序集合myzset,并加入一個元素baidu.com,給它賦予的序號是1:
復制代碼代碼如下:
127.0.0.1:6379>?zadd?myzset?1?baidu.com? (integer)?1 //向myzset中新增一個元素360.com,賦予它的序號是3 127.0.0.1:6379>?zadd?myzset?3?360.com? (integer)?1 //向myzset中新增一個元素google.com,賦予它的序號是2 127.0.0.1:6379>?zadd?myzset?2?google.com? (integer)?1 //列出myzset的所有元素,同時列出其序號,可以看出myzset已經是有序的了。 127.0.0.1:6379>?zrange?myzset?0?-1?with?scores? 1)?"baidu.com" 2)?"1" 3)?"google.com" 4)?"2" 5)?"360.com" 6)?"3" //只列出myzset的元素 127.0.0.1:6379>?zrange?myzset?0?-1? 1)?"baidu.com" 2)?"google.com" 3)?"360.com"
?
【redis數據結構 – 哈希】
最后要給大家介紹的是hashes,即哈希。哈希是從redis-2.0.0版本之后才有的數據結構。
hashes存的是字符串和字符串值之間的映射,比如一個用戶要存儲其全名、姓氏、年齡等等,就很適合使用哈希。
我們來看一個例子:
復制代碼代碼如下:
//建立哈希,并賦值 127.0.0.1:6379>?HMSET?user:001?username?antirez?password?P1pp0?age?34? OK //列出哈希的內容 127.0.0.1:6379>?HGETALL?user:001? 1)?"username" 2)?"antirez" 3)?"password" 4)?"P1pp0" 5)?"age" 6)?"34" //更改哈希中的某一個值 127.0.0.1:6379>?HSET?user:001?password?12345? (integer)?0 //再次列出哈希的內容 127.0.0.1:6379>?HGETALL?user:001? 1)?"username" 2)?"antirez" 3)?"password" 4)?"12345" 5)?"age" 6)?"34"
?
有關hashes的操作,同樣很豐富,需要時,大家可以從這里查詢。
【聊聊redis持久化 – 兩種方式】
redis提供了兩種持久化的方式,分別是RDB(Redis DataBase)和AOF(Append Only File)。
RDB,簡而言之,就是在不同的時間點,將redis存儲的數據生成快照并存儲到磁盤等介質上;
AOF,則是換了一個角度來實現持久化,那就是將redis執行過的所有寫指令記錄下來,在下次redis重新啟動時,只要把這些寫指令從前到后再重復執行一遍,就可以實現數據恢復了。
其實RDB和AOF兩種方式也可以同時使用,在這種情況下,如果redis重啟的話,則會優先采用AOF方式來進行數據恢復,這是因為AOF方式的數據恢復完整度更高。
如果你沒有數據持久化的需求,也完全可以關閉RDB和AOF方式,這樣的話,redis將變成一個純內存數據庫,就像memcache一樣。
【聊聊redis持久化 – RDB】
RDB方式,是將redis某一時刻的數據持久化到磁盤中,是一種快照式的持久化方法。
redis在進行數據持久化的過程中,會先將數據寫入到一個臨時文件中,待持久化過程都結束了,才會用這個臨時文件替換上次持久化好的文件。正是這種特性,讓我們可以隨時來進行備份,因為快照文件總是完整可用的。
對于RDB方式,redis會單獨創建(fork)一個子進程來進行持久化,而主進程是不會進行任何IO操作的,這樣就確保了redis極高的性能。
如果需要進行大規模數據的恢復,且對于數據恢復的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
雖然RDB有不少優點,但它的缺點也是不容忽視的。如果你對數據的完整性非常敏感,那么RDB方式就不太適合你,因為即使你每5分鐘都持久化一次,當redis故障時,仍然會有近5分鐘的數據丟失。所以,redis還提供了另一種持久化方式,那就是AOF。
【聊聊redis持久化 – AOF】
AOF,英文是Append Only File,即只允許追加不允許改寫的文件。
如前面介紹的,AOF方式是將執行過的寫指令記錄下來,在數據恢復時按照從前到后的順序再將指令都執行一遍,就這么簡單。
我們通過配置redis.conf中的appendonly yes就可以打開AOF功能。如果有寫操作(如SET等),redis就會被追加到AOF文件的末尾。
默認的AOF持久化策略是每秒鐘fsync一次(fsync是指把緩存中的寫指令記錄到磁盤中),因為在這種情況下,redis仍然可以保持很好的處理性能,即使redis故障,也只會丟失最近1秒鐘的數據。
如果在追加日志時,恰好遇到磁盤空間滿、inode滿或斷電等情況導致日志寫入不完整,也沒有關系,redis提供了redis-check-aof工具,可以用來進行日志修復。
因為采用了追加方式,如果不做任何處理的話,AOF文件會變得越來越大,為此,redis提供了AOF文件重寫(rewrite)機制,即當AOF文件的大小超過所設定的閾值時,redis就會啟動AOF文件的內容壓縮,只保留可以恢復數據的最小指令集。舉個例子或許更形象,假如我們調用了100次INCR指令,在AOF文件中就要存儲100條指令,但這明顯是很低效的,完全可以把這100條指令合并成一條SET指令,這就是重寫機制的原理。
在進行AOF重寫時,仍然是采用先寫臨時文件,全部完成后再替換的流程,所以斷電、磁盤滿等問題都不會影響AOF文件的可用性,這點大家可以放心。
AOF方式的另一個好處,我們通過一個“場景再現”來說明。某同學在操作redis時,不小心執行了FLUSHALL,導致redis內存中的數據全部被清空了,這是很悲劇的事情。不過這也不是世界末日,只要redis配置了AOF持久化方式,且AOF文件還沒有被重寫(rewrite),我們就可以用最快的速度暫停redis并編輯AOF文件,將最后一行的FLUSHALL命令刪除,然后重啟redis,就可以恢復redis的所有數據到FLUSHALL之前的狀態了。是不是很神奇,這就是AOF持久化方式的好處之一。但是如果AOF文件已經被重寫了,那就無法通過這種方法來恢復數據了。
雖然優點多多,但AOF方式也同樣存在缺陷,比如在同樣數據規模的情況下,AOF文件要比RDB文件的體積大。而且,AOF方式的恢復速度也要慢于RDB方式。
如果你直接執行BGREWRITEAOF命令,那么redis會生成一個全新的AOF文件,其中便包括了可以恢復現有數據的最少的命令集。
如果運氣比較差,AOF文件出現了被寫壞的情況,也不必過分擔憂,redis并不會貿然加載這個有問題的AOF文件,而是報錯退出。這時可以通過以下步驟來修復出錯的文件:
1.備份被寫壞的AOF文件
2.運行redis-check-aof –fix進行修復
3.用diff -u來看下兩個文件的差異,確認問題點
4.重啟redis,加載修復后的AOF文件
【聊聊redis持久化 – AOF重寫】
AOF重寫的內部運行原理,我們有必要了解一下。
在重寫即將開始之際,redis會創建(fork)一個“重寫子進程”,這個子進程會首先讀取現有的AOF文件,并將其包含的指令進行分析壓縮并寫入到一個臨時文件中。
與此同時,主工作進程會將新接收到的寫指令一邊累積到內存緩沖區中,一邊繼續寫入到原有的AOF文件中,這樣做是保證原有的AOF文件的可用性,避免在重寫過程中出現意外。
當“重寫子進程”完成重寫工作后,它會給父進程發一個信號,父進程收到信號后就會將內存中緩存的寫指令追加到新AOF文件中。
當追加結束后,redis就會用新AOF文件來代替舊AOF文件,之后再有新的寫指令,就都會追加到新的AOF文件中了。
【聊聊redis持久化 – 如何選擇RDB和AOF】
對于我們應該選擇RDB還是AOF,官方的建議是兩個同時使用。這樣可以提供更可靠的持久化方案。
【聊聊主從 – 用法】
像MySQL一樣,redis是支持主從同步的,而且也支持一主多從以及多級從結構。
主從結構,一是為了純粹的冗余備份,二是為了提升讀性能,比如很消耗性能的SORT就可以由從服務器來承擔。
redis的主從同步是異步進行的,這意味著主從同步不會影響主邏輯,也不會降低redis的處理性能。
主從架構中,可以考慮關閉主服務器的數據持久化功能,只讓從服務器進行持久化,這樣可以提高主服務器的處理性能。
在主從架構中,從服務器通常被設置為只讀模式,這樣可以避免從服務器的數據被誤修改。但是從服務器仍然可以接受CONFIG等指令,所以還是不應該將從服務器直接暴露到不安全的網絡環境中。如果必須如此,那可以考慮給重要指令進行重命名,來避免命令被外人誤執行。
【聊聊主從 – 同步原理】
從服務器會向主服務器發出SYNC指令,當主服務器接到此命令后,就會調用BGSAVE指令來創建一個子進程專門進行數據持久化工作,也就是將主服務器的數據寫入RDB文件中。在數據持久化期間,主服務器將執行的寫指令都緩存在內存中。
在BGSAVE指令執行完成后,主服務器會將持久化好的RDB文件發送給從服務器,從服務器接到此文件后會將其存儲到磁盤上,然后再將其讀取到內存中。這個動作完成后,主服務器會將這段時間緩存的寫指令再以redis協議的格式發送給從服務器。
另外,要說的一點是,即使有多個從服務器同時發來SYNC指令,主服務器也只會執行一次BGSAVE,然后把持久化好的RDB文件發給多個下游。在redis2.8版本之前,如果從服務器與主服務器因某些原因斷開連接的話,都會進行一次主從之間的全量的數據同步;而在2.8版本之后,redis支持了效率更高的增量同步策略,這大大降低了連接斷開的恢復成本。
主服務器會在內存中維護一個緩沖區,緩沖區中存儲著將要發給從服務器的內容。從服務器在與主服務器出現網絡瞬斷之后,從服務器會嘗試再次與主服務器連接,一旦連接成功,從服務器就會把“希望同步的主服務器ID”和“希望請求的數據的偏移位置(replication offset)”發送出去。主服務器接收到這樣的同步請求后,首先會驗證主服務器ID是否和自己的ID匹配,其次會檢查“請求的偏移位置”是否存在于自己的緩沖區中,如果兩者都滿足的話,主服務器就會向從服務器發送增量內容。
增量同步功能,需要服務器端支持全新的PSYNC指令。這個指令,只有在redis-2.8之后才具有。
【聊聊redis的事務處理】
眾所周知,事務是指“一個完整的動作,要么全部執行,要么什么也沒有做”。
在聊redis事務處理之前,要先和大家介紹四個redis指令,即MULTI、EXEC、DISCARD、WATCH。這四個指令構成了redis事務處理的基礎。
1.MULTI用來組裝一個事務;
2.EXEC用來執行一個事務;
3.DISCARD用來取消一個事務;
4.WATCH用來監視一些key,一旦這些key在事務執行之前被改變,則取消事務的執行。
紙上得來終覺淺,我們來看一個MULTI和EXEC的例子:
復制代碼代碼如下:
redis>?MULTI?//標記事務開始 OK redis>?INCR?user_id?//多條命令按順序入隊 QUEUED redis>?INCR?user_id QUEUED redis>?INCR?user_id QUEUED redis>?PING QUEUED redis>?EXEC?//執行 1)?(integer)?1 2)?(integer)?2 3)?(integer)?3 4)?PONG
?
在上面的例子中,我們看到了QUEUED的字樣,這表示我們在用MULTI組裝事務時,每一個命令都會進入到內存隊列中緩存起來,如果出現QUEUED則表示我們這個命令成功插入了緩存隊列,在將來執行EXEC時,這些被QUEUED的命令都會被組裝成一個事務來執行。
對于事務的執行來說,如果redis開啟了AOF持久化的話,那么一旦事務被成功執行,事務中的命令就會通過write命令一次性寫到磁盤中去,如果在向磁盤中寫的過程中恰好出現斷電、硬件故障等問題,那么就可能出現只有部分命令進行了AOF持久化,這時AOF文件就會出現不完整的情況,這時,我們可以使用redis-check-aof工具來修復這一問題,這個工具會將AOF文件中不完整的信息移除,確保AOF文件完整可用。
有關事務,大家經常會遇到的是兩類錯誤:
1.調用EXEC之前的錯誤
2.調用EXEC之后的錯誤
“調用EXEC之前的錯誤”,有可能是由于語法有誤導致的,也可能時由于內存不足導致的。只要出現某個命令無法成功寫入緩沖隊列的情況,redis都會進行記錄,在客戶端調用EXEC時,redis會拒絕執行這一事務。(這時2.6.5版本之后的策略。在2.6.5之前的版本中,redis會忽略那些入隊失敗的命令,只執行那些入隊成功的命令)。我們來看一個這樣的例子:
復制代碼代碼如下:
127.0.0.1:6379>?multi OK 127.0.0.1:6379>?haha?//一個明顯錯誤的指令 (error)?ERR?unknown?command?'haha' 127.0.0.1:6379>?ping QUEUED 127.0.0.1:6379>?exec //redis無情的拒絕了事務的執行,原因是“之前出現了錯誤” (error)?EXECABORT?Transaction?discarded?because?of?previous?errors.
?
而對于“調用EXEC之后的錯誤”,redis則采取了完全不同的策略,即redis不會理睬這些錯誤,而是繼續向下執行事務中的其他命令。這是因為,對于應用層面的錯誤,并不是redis自身需要考慮和處理的問題,所以一個事務中如果某一條命令執行失敗,并不會影響接下來的其他命令的執行。我們也來看一個例子:
復制代碼代碼如下:
127.0.0.1:6379>?multi OK 127.0.0.1:6379>?set?age?23 QUEUED //age不是集合,所以如下是一條明顯錯誤的指令 127.0.0.1:6379>?sadd?age?15? QUEUED 127.0.0.1:6379>?set?age?29 QUEUED 127.0.0.1:6379>?exec?//執行事務時,redis不會理睬第2條指令執行錯誤 1)?OK 2)?(error)?WRONGTYPE?Operation?against?a?key?holding?the?wrong?kind?of?value 3)?OK 127.0.0.1:6379>?get?age "29"?//可以看出第3條指令被成功執行了
?
好了,我們來說說最后一個指令“WATCH”,這是一個很好用的指令,它可以幫我們實現類似于“樂觀鎖”的效果,即CAS(check and set)。
WATCH本身的作用是“監視key是否被改動過”,而且支持同時監視多個key,只要還沒真正觸發事務,WATCH都會盡職盡責的監視,一旦發現某個key被修改了,在執行EXEC時就會返回nil,表示事務無法觸發。
復制代碼代碼如下:
127.0.0.1:6379>?set?age?23 OK 127.0.0.1:6379>?watch?age?//開始監視age OK 127.0.0.1:6379>?set?age?24?//在EXEC之前,age的值被修改了 OK 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?set?age?25 QUEUED 127.0.0.1:6379>?get?age QUEUED 127.0.0.1:6379>?exec?//觸發EXEC (nil)?//事務無法被執行
?
【教你看懂redis配置 – 簡介】
我們可以在啟動redis-server時指定應該加載的配置文件,方法如下:
復制代碼代碼如下:
$?./redis-server?/path/to/redis.conf
?
接下來,我們就來講解下redis配置文件的各個配置項的含義,注意,本文是基于redis-2.8.4版本進行講解的。
redis官方提供的redis.conf文件,足有700+行,其中100多行為有效配置行,另外的600多行為注釋說明。
在配置文件的開頭部分,首先明確了一些度量單位:
復制代碼代碼如下:
#?1k?=>?1000?bytes #?1kb?=>?1024?bytes #?1m?=>?1000000?bytes #?1mb?=>?1024*1024?bytes #?1g?=>?1000000000?bytes #?1gb?=>?1024*1024*1024?bytes
?
可以看出,redis配置中對單位的大小寫不敏感,1GB、1Gb和1gB都是相同的。由此也說明,redis只支持bytes,不支持bit單位。
redis支持“主配置文件中引入外部配置文件”,很像C/C++中的include指令,比如:
復制代碼代碼如下:
include /path/to/other.conf
如果你看過redis的配置文件,會發現還是很有條理的。redis配置文件被分成了幾大塊區域,它們分別是:
1.通用(general)
2.快照(snapshotting)
3.復制(replication)
4.安全(security)
5.限制(limits)
6.追加模式(append only mode)
7.LUA腳本(lua scripting)
8.慢日志(slow log)
9.事件通知(event notification)
下面我們就來逐一講解。
【教你看懂redis配置 -通用】
默認情況下,redis并不是以daemon形式來運行的。通過daemonize配置項可以控制redis的運行形式,如果改為yes,那么redis就會以daemon形式運行:
復制代碼代碼如下:
daemonize?no
當以daemon形式運行時,redis會生成一個pid文件,默認會生成在/var/run/redis.pid。當然,你可以通過pidfile來指定pid文件生成的位置,比如:
復制代碼代碼如下:
pidfile?/path/to/redis.pid
默認情況下,redis會響應本機所有可用網卡的連接請求。當然,redis允許你通過bind配置項來指定要綁定的IP,比如:
復制代碼代碼如下:
bind?192.168.1.2?10.8.4.2
redis的默認服務端口是6379,你可以通過port配置項來修改。如果端口設置為0的話,redis便不會監聽端口了。
復制代碼代碼如下:
port?6379
有些同學會問“如果redis不監聽端口,還怎么與外界通信呢”,其實redis還支持通過unix socket方式來接收請求。可以通過unixsocket配置項來指定unix socket文件的路徑,并通過unixsocketperm來指定文件的權限。
復制代碼代碼如下:
unixsocket?/tmp/redis.sock unixsocketperm?755
當一個redis-client一直沒有請求發向server端,那么server端有權主動關閉這個連接,可以通過timeout來設置“空閑超時時限”,0表示永不關閉。
復制代碼代碼如下:
timeout?0
TCP連接保活策略,可以通過tcp-keepalive配置項來進行設置,單位為秒,假如設置為60秒,則server端會每60秒向連接空閑的客戶端發起一次ACK請求,以檢查客戶端是否已經掛掉,對于無響應的客戶端則會關閉其連接。所以關閉一個連接最長需要120秒的時間。如果設置為0,則不會進行保活檢測。
復制代碼代碼如下:
tcp-keepalive?0
redis支持通過loglevel配置項設置日志等級,共分四級,即debug、verbose、notice、warning。
復制代碼代碼如下:
loglevel?notice
redis也支持通過logfile配置項來設置日志文件的生成位置。如果設置為空字符串,則redis會將日志輸出到標準輸出。假如你在daemon情況下將日志設置為輸出到標準輸出,則日志會被寫到/dev/null中。
復制代碼代碼如下:
logfile?""
如果希望日志打印到syslog中,也很容易,通過syslog-enabled來控制。另外,syslog-ident還可以讓你指定syslog里的日志標志,比如:
復制代碼代碼如下:
syslog-ident?redis
而且還支持指定syslog設備,值可以是USER或LOCAL0-LOCAL7。具體可以參考syslog服務本身的用法。
復制代碼代碼如下:
syslog-facility?local0
對于redis來說,可以設置其數據庫的總數量,假如你希望一個redis包含16個數據庫,那么設置如下:
復制代碼代碼如下:
databases?16
這16個數據庫的編號將是0到15。默認的數據庫是編號為0的數據庫。用戶可以使用select
?
【教你看懂redis配置 – 快照】
快照,主要涉及的是redis的RDB持久化相關的配置,我們來一起看一看。
我們可以用如下的指令來讓數據保存到磁盤上,即控制RDB快照功能:
復制代碼代碼如下:
save?<seconds>?<changes></changes></seconds>
舉例來說:
復制代碼代碼如下:
save?900?1?//表示每15分鐘且至少有1個key改變,就觸發一次持久化 save?300?10?//表示每5分鐘且至少有10個key改變,就觸發一次持久化 save?60?10000?//表示每60秒至少有10000個key改變,就觸發一次持久化
如果你想禁用RDB持久化的策略,只要不設置任何save指令就可以,或者給save傳入一個空字符串參數也可以達到相同效果,就像這樣:
復制代碼代碼如下:
save?""
如果用戶開啟了RDB快照功能,那么在redis持久化數據到磁盤時如果出現失敗,默認情況下,redis會停止接受所有的寫請求。這樣做的好處在于可以讓用戶很明確的知道內存中的數據和磁盤上的數據已經存在不一致了。如果redis不顧這種不一致,一意孤行的繼續接收寫請求,就可能會引起一些災難性的后果。
如果下一次RDB持久化成功,redis會自動恢復接受寫請求。
當然,如果你不在乎這種數據不一致或者有其他的手段發現和控制這種不一致的話,你完全可以關閉這個功能,以便在快照寫入失敗時,也能確保redis繼續接受新的寫請求。配置項如下:
復制代碼代碼如下:
stop-writes-on-bgsave-error?yes
對于存儲到磁盤中的快照,可以設置是否進行壓縮存儲。如果是的話,redis會采用LZF算法進行壓縮。如果你不想消耗CPU來進行壓縮的話,可以設置為關閉此功能,但是存儲在磁盤上的快照會比較大。
復制代碼代碼如下:
rdbcompression?yes
在存儲快照后,我們還可以讓redis使用CRC64算法來進行數據校驗,但是這樣做會增加大約10%的性能消耗,如果你希望獲取到最大的性能提升,可以關閉此功能。
復制代碼代碼如下:
rdbchecksum?yes
我們還可以設置快照文件的名稱,默認是這樣配置的:
復制代碼代碼如下:
dbfilename?dump.rdb
最后,你還可以設置這個快照文件存放的路徑。比如默認設置就是當前文件夾:
復制代碼代碼如下:
dir?./
【教你看懂redis配置 – 復制】
redis提供了主從同步功能。
通過slaveof配置項可以控制某一個redis作為另一個redis的從服務器,通過指定IP和端口來定位到主redis的位置。一般情況下,我們會建議用戶為從redis設置一個不同頻率的快照持久化的周期,或者為從redis配置一個不同的服務端口等等。
復制代碼代碼如下:
slaveof?<masterip>?<masterport></masterport></masterip>
如果主redis設置了驗證密碼的話(使用requirepass來設置),則在從redis的配置中要使用masterauth來設置校驗密碼,否則的話,主redis會拒絕從redis的訪問請求。
復制代碼代碼如下:
masterauth?<master-password></master-password>
當從redis失去了與主redis的連接,或者主從同步正在進行中時,redis該如何處理外部發來的訪問請求呢?這里,從redis可以有兩種選擇:
第一種選擇:如果slave-serve-stale-data設置為yes(默認),則從redis仍會繼續響應客戶端的讀寫請求。
第二種選擇:如果slave-serve-stale-data設置為no,則從redis會對客戶端的請求返回“SYNC with master in progress”,當然也有例外,當客戶端發來INFO請求和SLAVEOF請求,從redis還是會進行處理。
你可以控制一個從redis是否可以接受寫請求。將數據直接寫入從redis,一般只適用于那些生命周期非常短的數據,因為在主從同步時,這些臨時數據就會被清理掉。自從redis2.6版本之后,默認從redis為只讀。
復制代碼代碼如下:
slave-read-only?yes
只讀的從redis并不適合直接暴露給不可信的客戶端。為了盡量降低風險,可以使用rename-command指令來將一些可能有破壞力的命令重命名,避免外部直接調用。比如:
復制代碼代碼如下:
rename-command?CONFIG?b840fc02d524045429941cc15f59e41cb7be6c52
從redis會周期性的向主redis發出PING包。你可以通過repl_ping_slave_period指令來控制其周期。默認是10秒。
復制代碼代碼如下:
repl-ping-slave-period?10
在主從同步時,可能在這些情況下會有超時發生:
1.以從redis的角度來看,當有大規模IO傳輸時。 2.以從redis的角度來看,當數據傳輸或PING時,主redis超時 3.以主redis的角度來看,在回復從redis的PING時,從redis超時
用戶可以設置上述超時的時限,不過要確保這個時限比repl-ping-slave-period的值要大,否則每次主redis都會認為從redis超時。
復制代碼代碼如下:
repl-timeout?60
我們可以控制在主從同步時是否禁用TCP_NODELAY。如果開啟TCP_NODELAY,那么主redis會使用更少的TCP包和更少的帶寬來向從redis傳輸數據。但是這可能會增加一些同步的延遲,大概會達到40毫秒左右。如果你關閉了TCP_NODELAY,那么數據同步的延遲時間會降低,但是會消耗更多的帶寬。(如果你不了解TCP_NODELAY,可以到這里來科普一下)。
復制代碼代碼如下:
repl-disable-tcp-nodelay?no
我們還可以設置同步隊列長度。隊列長度(backlog)是主redis中的一個緩沖區,在與從redis斷開連接期間,主redis會用這個緩沖區來緩存應該發給從redis的數據。這樣的話,當從redis重新連接上之后,就不必重新全量同步數據,只需要同步這部分增量數據即可。
復制代碼代碼如下:
repl-backlog-size?1mb
如果主redis等了一段時間之后,還是無法連接到從redis,那么緩沖隊列中的數據將被清理掉。我們可以設置主redis要等待的時間長度。如果設置為0,則表示永遠不清理。默認是1個小時。
復制代碼代碼如下:
repl-backlog-ttl?3600
我們可以給眾多的從redis設置優先級,在主redis持續工作不正常的情況,優先級高的從redis將會升級為主redis。而編號越小,優先級越高。比如一個主redis有三個從redis,優先級編號分別為10、100、25,那么編號為10的從redis將會被首先選中升級為主redis。當優先級被設置為0時,這個從redis將永遠也不會被選中。默認的優先級為100。
復制代碼代碼如下:
slave-priority?100
假如主redis發現有超過M個從redis的連接延時大于N秒,那么主redis就停止接受外來的寫請求。這是因為從redis一般會每秒鐘都向主redis發出PING,而主redis會記錄每一個從redis最近一次發來PING的時間點,所以主redis能夠了解每一個從redis的運行情況。
復制代碼代碼如下:
min-slaves-to-write?3 min-slaves-max-lag?10
上面這個例子表示,假如有大于等于3個從redis的連接延遲大于10秒,那么主redis就不再接受外部的寫請求。上述兩個配置中有一個被置為0,則這個特性將被關閉。默認情況下min-slaves-to-write為0,而min-slaves-max-lag為10。
【教你看懂redis配置 – 安全】
我們可以要求redis客戶端在向redis-server發送請求之前,先進行密碼驗證。當你的redis-server處于一個不太可信的網絡環境中時,相信你會用上這個功能。由于redis性能非常高,所以每秒鐘可以完成多達15萬次的密碼嘗試,所以你最好設置一個足夠復雜的密碼,否則很容易被黑客破解。
復制代碼代碼如下:
requirepass?zhimakaimen
這里我們通過requirepass將密碼設置成“芝麻開門”。
redis允許我們對redis指令進行更名,比如將一些比較危險的命令改個名字,避免被誤執行。比如可以把CONFIG命令改成一個很復雜的名字,這樣可以避免外部的調用,同時還可以滿足內部調用的需要:
復制代碼代碼如下:
rename-command?CONFIG?b840fc02d524045429941cc15f59e41cb7be6c89
我們甚至可以禁用掉CONFIG命令,那就是把CONFIG的名字改成一個空字符串:
復制代碼代碼如下:
rename-command?CONFIG?""
但需要注意的是,如果你使用AOF方式進行數據持久化,或者需要與從redis進行通信,那么更改指令的名字可能會引起一些問題。
【教你看懂redis配置 -限制】
我們可以設置redis同時可以與多少個客戶端進行連接。默認情況下為10000個客戶端。當你無法設置進程文件句柄限制時,redis會設置為當前的文件句柄限制值減去32,因為redis會為自身內部處理邏輯留一些句柄出來。
如果達到了此限制,redis則會拒絕新的連接請求,并且向這些連接請求方發出“max number of clients reached”以作回應。
復制代碼代碼如下:
maxclients?10000
我們甚至可以設置redis可以使用的內存量。一旦到達內存使用上限,redis將會試圖移除內部數據,移除規則可以通過maxmemory-policy來指定。
如果redis無法根據移除規則來移除內存中的數據,或者我們設置了“不允許移除”,那么redis則會針對那些需要申請內存的指令返回錯誤信息,比如SET、LPUSH等。但是對于無內存申請的指令,仍然會正常響應,比如GET等。
復制代碼代碼如下:
maxmemory?<bytes></bytes>
需要注意的一點是,如果你的redis是主redis(說明你的redis有從redis),那么在設置內存使用上限時,需要在系統中留出一些內存空間給同步隊列緩存,只有在你設置的是“不移除”的情況下,才不用考慮這個因素。
對于內存移除規則來說,redis提供了多達6種的移除規則。他們是:
1.volatile-lru:使用LRU算法移除過期集合中的key 2.allkeys-lru:使用LRU算法移除key 3.volatile-random:在過期集合中移除隨機的key 4.allkeys-random:移除隨機的key 5.volatile-ttl:移除那些TTL值最小的key,即那些最近才過期的key。 6.noeviction:不進行移除。針對寫操作,只是返回錯誤信息。
無論使用上述哪一種移除規則,如果沒有合適的key可以移除的話,redis都會針對寫請求返回錯誤信息。
復制代碼代碼如下:
maxmemory-policy?volatile-lru
LRU算法和最小TTL算法都并非是精確的算法,而是估算值。所以你可以設置樣本的大小。假如redis默認會檢查三個key并選擇其中LRU的那個,那么你可以改變這個key樣本的數量。
復制代碼代碼如下:
maxmemory-samples?3
最后,我們補充一個信息,那就是到目前版本(2.8.4)為止,redis支持的寫指令包括了如下這些:
復制代碼代碼如下:
set?setnx?setex?append incr?decr?rpush?lpush?rpushx?lpushx?linsert?lset?rpoplpush?sadd sinter?sinterstore?sunion?sunionstore?sdiff?sdiffstore?zadd?zincrby zunionstore?zinterstore?hset?hsetnx?hmset?hincrby?incrby?decrby getset?mset?msetnx?exec?sort
【教你看懂redis配置 – 追加模式】
默認情況下,redis會異步的將數據持久化到磁盤。這種模式在大部分應用程序中已被驗證是很有效的,但是在一些問題發生時,比如斷電,則這種機制可能會導致數分鐘的寫請求丟失。
如博文上半部分中介紹的,追加文件(Append Only File)是一種更好的保持數據一致性的方式。即使當服務器斷電時,也僅會有1秒鐘的寫請求丟失,當redis進程出現問題且操作系統運行正常時,甚至只會丟失一條寫請求。
我們建議大家,AOF機制和RDB機制可以同時使用,不會有任何沖突。對于如何保持數據一致性的討論,請參見本文。
復制代碼代碼如下:
appendonly?no
我們還可以設置aof文件的名稱:
復制代碼代碼如下:
appendfilename?"appendonly.aof"
fsync()調用,用來告訴操作系統立即將緩存的指令寫入磁盤。一些操作系統會“立即”進行,而另外一些操作系統則會“盡快”進行。
redis支持三種不同的模式:
1.no:不調用fsync()。而是讓操作系統自行決定sync的時間。這種模式下,redis的性能會最快。
2.always:在每次寫請求后都調用fsync()。這種模式下,redis會相對較慢,但數據最安全。
3.everysec:每秒鐘調用一次fsync()。這是性能和安全的折衷。
默認情況下為everysec。有關數據一致性的揭秘,可以參考本文。
復制代碼代碼如下:
appendfsync?everysec
當fsync方式設置為always或everysec時,如果后臺持久化進程需要執行一個很大的磁盤IO操作,那么redis可能會在fsync()調用時卡住。目前尚未修復這個問題,這是因為即使我們在另一個新的線程中去執行fsync(),也會阻塞住同步寫調用。
為了緩解這個問題,我們可以使用下面的配置項,這樣的話,當BGSAVE或BGWRITEAOF運行時,fsync()在主進程中的調用會被阻止。這意味著當另一路進程正在對AOF文件進行重構時,redis的持久化功能就失效了,就好像我們設置了“appendsync none”一樣。如果你的redis有時延問題,那么請將下面的選項設置為yes。否則請保持no,因為這是保證數據完整性的最安全的選擇。
復制代碼代碼如下:
no-appendfsync-on-rewrite?no
我們允許redis自動重寫aof。當aof增長到一定規模時,redis會隱式調用BGREWRITEAOF來重寫log文件,以縮減文件體積。
redis是這樣工作的:redis會記錄上次重寫時的aof大小。假如redis自啟動至今還沒有進行過重寫,那么啟動時aof文件的大小會被作為基準值。這個基準值會和當前的aof大小進行比較。如果當前aof大小超出所設置的增長比例,則會觸發重寫。另外,你還需要設置一個最小大小,是為了防止在aof很小時就觸發重寫。
復制代碼代碼如下:
auto-aof-rewrite-percentage?100 auto-aof-rewrite-min-size?64mb
如果設置auto-aof-rewrite-percentage為0,則會關閉此重寫功能。
【教你看懂redis配置 – LUA腳本】
lua腳本的最大運行時間是需要被嚴格限制的,要注意單位是毫秒:
復制代碼代碼如下:
lua-time-limit?5000
如果此值設置為0或負數,則既不會有報錯也不會有時間限制。
【教你看懂redis配置 – 慢日志】
redis慢日志是指一個系統進行日志查詢超過了指定的時長。這個時長不包括IO操作,比如與客戶端的交互、發送響應內容等,而僅包括實際執行查詢命令的時間。
針對慢日志,你可以設置兩個參數,一個是執行時長,單位是微秒,另一個是慢日志的長度。當一個新的命令被寫入日志時,最老的一條會從命令日志隊列中被移除。
單位是微秒,即1000000表示一秒。負數則會禁用慢日志功能,而0則表示強制記錄每一個命令。
復制代碼代碼如下:
slowlog-log-slower-than?10000
慢日志最大長度,可以隨便填寫數值,沒有上限,但要注意它會消耗內存。你可以使用SLOWLOG RESET來重設這個值。
復制代碼代碼如下:
slowlog-max-len?128
【教你看懂redis配置 – 事件通知】
redis可以向客戶端通知某些事件的發生。這個特性的具體解釋可以參見本文。
【教你看懂redis配置 – 高級配置】
有關哈希數據結構的一些配置項:
復制代碼代碼如下:
hash-max-ziplist-entries?512 hash-max-ziplist-value?64
有關列表數據結構的一些配置項:
復制代碼代碼如下:
list-max-ziplist-entries?512 list-max-ziplist-value?64
有關集合數據結構的配置項:
復制代碼代碼如下:
set-max-intset-entries?512
有關有序集合數據結構的配置項:
復制代碼代碼如下:
zset-max-ziplist-entries?128 zset-max-ziplist-value?64
關于是否需要再哈希的配置項:
復制代碼代碼如下:
activerehashing?yes
關于客戶端輸出緩沖的控制項:
復制代碼代碼如下:
client-output-buffer-limit?normal?0?0?0 client-output-buffer-limit?slave?256mb?64mb?60 client-output-buffer-limit?pubsub?32mb?8mb?60
有關頻率的配置項:
復制代碼代碼如下:
hz?10
有關重寫aof的配置項
復制代碼代碼如下:
aof-rewrite-incremental-fsync?yes
相關推薦:php教程