原文連結:http://www.cnblogs.com/xrq730/p/8890896.html,轉載請註明出處,謝謝
Redis從入門到精通:初級篇
平時陸陸續續看了不少Redis的文章了,工作中也一直在用Redis,感覺是時候對過往Redis的所學進行一次系統性的總結。《Redis從入門到精通》系列會分為初級、中級、高階三篇,從淺入深講解Redis相關知識點。
在本文中,我們將看到以下內容:
- Redis簡介
- Redis安裝、啟動
- Redis登入授權
- Redis配置檔案redis.conf中引數詳細的一個解讀
- Redis效能測試
這些內容無關具體用法,作為一些初級的知識,系統地先認識一下Redis。
Redis簡介
Redis是一款開源的使用ANSI C語言編寫、遵守BSD協議、支援網路、可基於記憶體也可持久化的日誌型、Key-Value高效能資料庫。Redis與其他Key-Value快取產品相比有以下三個特點:
- 支援資料持久化,可以將記憶體中的資料儲存在磁碟中,重啟可再次載入使用
- 支援簡單的Key-Value型別的資料,同時還提供List、Set、Zset、Hash等資料結構的儲存
- 支援資料的備份,即Master-Slave模式的資料備份
同時,我們再看下Redis有什麼優勢:
- 讀速度為110000次/s,寫速度為81000次/s,效能極高
- 具有豐富的資料型別,這個上面已經提過了
- Redis所有操作都是原子的,意思是要麼成功執行要麼失敗完全不執行,多個操作也支援事務
- 豐富的特性,比如Redis支援publish/subscribe、notify、key過期等
Redis安裝、啟動
這次寫Redis系列的文章,LZ特意去阿里雲上買了一個月的伺服器,作業系統是Linux,因為Redis專案本身不正式支援Windows系統。不過微軟開放技術小組開發和維護了Windows版本的Redis,下載地址為https://github.com/MicrosoftArchive/redis/releases,感興趣的可以自己去試下,LZ在自己筆記本上安裝啟動過,沒有問題,但就不細說了。
下面說一下在Linux系統上安裝並啟動Redis的步驟(我的Redis安裝在/data/component/redis目錄下,每一步使用的命令標紅加粗):
- 進入目錄,cd /data/component/redis
- 下載Redis,wget http://download.redis.io/releases/redis-3.2.11.tar.gz,可以看到LZ使用的Redis版本是3.2.11,在LZ寫這篇文章的時候,Redis最新版本為4.0.9,地址為http://download.redis.io/releases/redis-4.0.9.tar.gz,感興趣的朋友也可以用這個版本
- 解壓下載下來的tar包,tar -zxvf redis-3.2.11.tar.gz,解壓完畢的資料夾名稱為redis-3.2.11
- 進入redis-3.2.11,cd redis-3.2.11
- 由於我們下載下來的是原始檔,因此使用make命令對原始檔進行一個構建,構建完畢我們會發現src目錄下多出了redis-benchmark、redis-check-aof、redis-check-rdb、redis-cli、redis-sentinel、redis-server幾個可執行檔案,這幾個可執行檔案後面會說到
- 由於上述幾個命令在/data/component/redis/redis-3.2.11/src目錄下,為了更方便地使用這幾個命令而不需要指定全路徑,配置一下環境變數。這裡我是以非root使用者進行登入的,因此配置使用者變數,先執行cd命令回到初始目錄,再vi ./.bash_profile,在path這一行加入PATH=$PATH:$HOME/.local/bin:$HOME/bin:/data/component/redis/redis-3.2.11/src,使用:wq儲存並退出
- 使環境變數生效,執行source ./.bash_profile
- 使用redis-server即可啟動redis,redis-server /data/component/redis/redis-3.2.11/redis.conf
不過這個時候我們的啟動稍微有點問題,不是後臺啟動的,即ctrl+c之後Redis就停了:
為了解決這個問題,我們需要修改一下redis.conf,將Redis設定為以守護程式的方式進行啟動,開啟redis.conf,找到daemonize,將其設定為yes即可:
這個時候先關閉一下再啟動,Redis就在後臺自動執行了,關閉Redis有兩種方式:
- redis-cli shutdown,這是種安全關閉redis的方式,但這種寫法只適用於沒有配置密碼的場景,比較不安全,配置密碼下一部分會講
- kill -9 pid,這種方式就是強制關閉,可能會造成資料未儲存
重啟後,我們可以使用ps -ef | grep redis,netstat -ant | grep 6379命令來驗證Redis已經啟動。
Redis登入授權
上面我們安裝了Redis,但這種方式是非常不安全的,因為沒有密碼,這樣任何連線上Redis伺服器的使用者都可以對Redis執行操作,所以這一部分我們來講一下給Redis設定密碼。
開啟redis.conf,找到"requirepass"部分,開啟原本關閉的註釋,替換一下自己想要的密碼即可:
重啟Redis,授權登入有兩種做法:
- 連線的時候直接指定密碼,redis-cli -h 127.0.0.1 -p 6379 -a 123456
- 連線後授權,redis-cli -h 127.0.0.1 -p 6379,auth 123456
在配置了密碼的情況下,沒有進行授權,那麼對Redis傳送的命令,將返回"(error) NOAUTH Authentication required."。
Redis配置檔案redis.conf
上面兩小節,設定使用守護執行緒啟動、設定密碼,都需要修改redis.conf,說明redis.conf是Redis核心的配置檔案,本小節我們來看一下redis.conf中一些常用配置:
配置 | 作用 | 預設 |
bind |
當配置了bind之後:
|
127.0.0.1 |
protected-mode |
protected-mode是Redis3.2之後的新特性,用於加強Redis的安全管理,當滿足以下兩種情況時,protected-mode起作用:
當滿足以上兩種情況且protected-mode=yes的時候,訪問Redis將報錯,即密碼未設定的情況下,無密碼訪問Redis只能通過安裝Redis的本機進行訪問 |
yes |
port | Redis訪問埠,由於Redis是單執行緒模型,因此單機開多個Redis程式的時候會修改埠,不然一般使用大家比較熟悉的6379埠就可以了 | 6379 |
tcp-backlog | 半連線佇列的大小,對半連線佇列不熟的可以看我以前的文章TCP:三次握手、四次握手、backlog及其他 | 511 |
timeout | 指定在一個client空閒多少秒之後就關閉它,0表示不管 | 0 |
tcp-keepalive |
設定tcp協議的keepalive,從Redis的註釋來看,這個引數有兩個作用:
|
300 |
daemonize | 這個前面說過了,指定Redis是否以守護程式的方式啟動 | no |
supervised | 這個參數列示可以通過upstart和systemd管理Redis守護程式,這個具體和作業系統相關,資料也不是很多,就暫時不管了 | no |
pidfile | 當Redis以守護程式的方式執行的時候,Redis預設會把pid寫到pidfile指定的檔案中 | /var/run/redis_6379.pid |
loglevel |
指定Redis的日誌級別,Redis本身的日誌級別有notice、verbose、notice、warning四種,按照文件的說法,這四種日誌級別的區別是:
|
notice |
logfile | 配置log檔案地址,預設列印在命令列終端的視窗上 | "" |
databases | 設定Redis資料庫的數量,預設使用0號DB | 16 |
save | 把Redis資料儲存到磁碟上,這個是在RDB的時候用的,介紹RDB的時候專門說這個 |
save 900 1 save 300 10 save 60 10000 |
stop-writes-on-bgsave-error |
當啟用了RDB且最後一次後臺儲存資料失敗,Redis是否停止接收資料。 這會讓使用者意識到資料沒有正確持久化到磁碟上,否則沒有人會注意到災難(disaster)發生了。 如果Redis重啟了,那麼又可以重新開始接收資料了 |
yes |
rdbcompression | 是否在RBD的時候使用LZF壓縮字串,如果希望省點CPU,那就設為no,不過no的話資料集可能就比較大 | yes |
rdbchecksum | 是否校驗RDB檔案,在RDB檔案中有一個checksum專門用於校驗 | yes |
dbfilename | dump的檔案位置 | dump.rdb |
dir | Redis工作目錄 | ./ |
slaveof | 主從複製,使用slaveof讓一個節點稱為某個節點的副本,這個只需要在副本上配置 | 關閉 |
masterauth | 如果主機使用了requirepass配置進行密碼保護,使用這個配置告訴副本連線的時候需要鑑權 | 關閉 |
slave-serve-stale-data |
當一個Slave與Master失去聯絡或者複製正在進行中,Slave可能會有兩種表現:
|
yes |
slave-read-only | 配置Redis的Slave例項是否接受寫操作,即Slave是否為只讀Redis | yes |
slave-priority | 從站優先順序是可以從redis的INFO命令輸出中查到的一個整數。當主站不能正常工作時,redis sentinel使用它來選擇一個從站並將它提升為主站。 低優先順序的從站被認為更適合於提升,因此如果有三個從站優先順序分別是10, 100, 25,sentinel會選擇優先順序為10的從站,因為它的優先順序最低。 然而優先順序值為0的從站不能執行主站的角色,因此優先順序為0的從站永遠不會被redis sentinel提升。 |
100 |
requirepass | 設定客戶端認證密碼 | 關閉 |
rename-command |
命令重新命名,對於一些危險命令例如:
作為服務端redis-server,常常需要禁用以上命令來使得伺服器更加安全,禁用的具體做法是是:
也可以保留命令但是不能輕易使用,重新命名這個命令即可:
這樣,重啟伺服器後則需要使用新命令來執行操作,否則伺服器會報錯unknown command |
關閉 |
maxclients | 設定同時連線的最大客戶端數量,一旦達到了限制,Redis會關閉所有的新連線併傳送一個"max number of clients reached"的錯誤 | 關閉,預設10000 |
maxmemory | 不要使用超過指定數量的記憶體,一旦達到了,Redis會嘗試使用驅逐策略來移除鍵 | 關閉 |
maxmemory-policy |
當達到了maxmemory之後Redis如何移除資料,有以下的一些策略:
注意,當寫操作且Redis發現沒有合適的資料可以移除的時候,將會報錯 |
關閉,noeviction |
appendonly | 是否開啟AOF,關於AOF後面再說 | no |
appendfilename | AOF檔名稱 | appendonly.aof |
appendfsync |
作業系統實際寫資料到磁碟的頻率,有以下幾個選項:
當不確定是使用哪種的時候,官方推薦使用everysec,它是速度與資料安全之間的一種折衷方案 |
everysec |
no-appendfsync-on-rewrite |
aof持久化機制有一個致命的問題,隨著時間推移,aof檔案會膨脹,當server重啟時嚴重影響資料庫還原時間,因此係統需要定期重寫aof檔案。 重寫aof的機制為bgrewriteaof(另外一種被廢棄了,就不說了),即在一個子程式中重寫從而不阻塞主程式對其他命令的處理,但是這依然有個問題。 bgrewriteaof和主程式寫aof,都會操作磁碟,而bgrewriteaof往往涉及大量磁碟操作,這樣就會讓主程式寫aof檔案阻塞。 針對上述問題,可以使用此時可以使用no-appendfsync-on-rewrite引數做一個選擇:
|
no |
auto-aof-rewrite-percentage | 本次aof檔案超過上次aof檔案該值的百分比時,才會觸發rewrite | 100 |
auto-aof-rewrite-min-size | aof檔案最小值,只有到達這個值才會觸發rewrite,即rewrite由auto-aof-rewrite-percentage+auto-aof-rewrite-min-size共同保證 | 64mb |
aof-load-truncated |
redis在以aof方式恢復資料時,對最後一條可能出問題的指令的處理方式:
|
yes |
slowlog-log-slower-than | Redis慢查詢的最低條件,單位微妙,即查詢時間>這個值的會被記錄 | 10000 |
slowlog-max-len | Redis儲存的慢查詢最大條數,超過該值之後會將最早的slowlog剔除 | 128 |
lua-time-limit | 一個lua指令碼執行的最大時間,單位為ms | 5000 |
cluster-enabled | 正常來說Redis例項是無法稱為叢集的一部分的,只有以叢集方式啟動的節點才可以。為了讓Redis以叢集方式啟動,就需要此引數。 | 關閉 |
cluster-config-file | 每個叢集節點應該有自己的配置檔案,這個檔案是不應該手動修改的,它只能被Redis節點建立且更新,每個Redis叢集節點需要不同的叢集配置檔案 | 關閉,nodes-6379.conf |
cluster-node-timeout | 叢集中一個節點向其他節點傳送ping命令時,必須收到回執的毫秒數 | 關閉,15000 |
cluster-slave-validity-factor |
如果該項設定為0,不管Slave節點和Master節點間失聯多久都會一直嘗試failover。 比如timeout為5,該值為10,那麼Master與Slave之間失聯50秒,Slave不會去failover它的Master |
關閉,10 |
cluster-migration-barrier |
當一個Master擁有多少個好的Slave時就要割讓一個Slave出來。 例如設定為2,表示當一個Master擁有2個可用的Slave時,它的一個Slave會嘗試遷移 |
關閉,1 |
cluster-require-full-coverage |
有節點當機導致16384個Slot全部被覆蓋,整個叢集是否停止服務,這個值一定要改為no |
關閉,yes |
以上把redis.conf裡面幾乎所有的配置都寫了一遍(除了ADVANCED CONFIG部分),感覺其他部落格很少有看到比我這個還全的了^_^,給大家作為參考吧。
Redis效能測試
之前說過Redis在make之後有一個redis-benchmark,這個就是Redis提供用於做效能測試的,它可以用來模擬N個客戶端同時發出M個請求。首先看一下redis-benchmark自帶的一些引數:
引數 | 作用 | 預設值 |
-h | 伺服器名稱 | 127.0.0.1 |
-p | 伺服器埠 | 6379 |
-s | 伺服器Socket | 無 |
-c | 並行連線數 | 50 |
-n | 請求書 | 10000 |
-d | SET/GET值的位元組大小 | 2 |
-k | 1表示keep alive,0表示重連 | 1 |
-r |
SET/GET/INC使用隨機Key而不是常量,在形式上key樣子為mykey_ran:000000012456 -r的值決定了value的最大值 |
無 |
-p | 使用管道請求 | 1,即不使用管道 |
-q | 安靜模式,只顯示query/sec值 | 無 |
--csv | 使用csv格式輸出 | 無 |
-l | 迴圈,無限執行測試 | 無 |
-t | 只執行使用逗號分割的命令的測試 | 無 |
-I | 空閒模式,只開啟N個空閒執行緒並且等待 | 無 |
拋開配置只談效能的都是耍流氓,說一下我買的阿里雲伺服器的配置:
- 單核CPU,CPU型別為Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
- 記憶體4G
- 頻寬1M
- 作業系統為Centos7
首先我們執行最簡單的redis-benchmark -q,執行結果為:
列印了每個命令的QPS,看到基本都在讀寫速度基本都在100000次/s以上。
接著換一個命令進行測試,因為實際場景中我們的Key和Value一定是非常豐富的,不可能是單一的Key和單一的Value,因此接著去的測試使用-r模擬value到100000且將執行次數提高到1000000次,具體命令為redis-benchmark -q -r 100000 -n 1000000,執行結果為:
看到整個讀寫效率基本都在110000次/s以上,證明了讀寫的高效率。
簡單對於Redis的效能測試就到這兒,這個測試結果看起來很美,但是實際應用卻完全不是,主要體現在以下幾點:
- 網路與頻寬,這是現實中最主要的影響因素,上面的測試還是太過於低階,現實使用中Redis裡面存一個使用者資訊、訂單資訊,幾KB的大小,100000qps根本不可能大家可以算算需要多大的頻寬,粗粗算一下超過1個G吧,很多線上服務的頻寬根本達不到1G/s,所以Redis的吞吐量最先會被網路頻寬限制住
- Redis由於是單執行緒模型,因此CPU效能非常重要,尤其是大快取的快速CPU,我這裡的CPU上面寫過了,Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz總體還是可以的
- 客戶端連線數,上面使用了預設的連線數50,實際上10W、20W甚至100W+呢?不過得益於epoll模型,整個下降的可以接受,下面有一張連線數和qps的關係,我也是網上找來的
- RDB和AOF可能會對Redis造成的阻塞並未考慮進去
- 儘可能使用大記憶體,避免SWAP
無論如何,總而言之,Redis整個效能是非常不錯的,個人認為如果要選一款儲存系統,那麼Redis應當是首選。