前言
Redis 是一種基於 鍵值對 的 NoSQL 數據庫。與很多鍵值對數據庫不同,Redis 提供了豐富的 值數據存儲結構,包括 string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、bitmap(位圖)等等。
正文
Redis 是一個使用 ANSI C 編寫的開源、支持 網絡、基於 內存、單線程模型、可選持久性 的 鍵值對存儲數據庫。
1. Redis的特性
- 速度快,最快可達到 10w QPS(基於 內存,C 語言,單線程 架構);
- 基於 鍵值對 (key/value) 的數據結構服務器。全稱 Remote Dictionary Server。包括 string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、bitmap(位圖)。同時在 字符串 的基礎上演變出 位圖(BitMaps)和 HyperLogLog 兩種數據結構。3.2 版本中加入 GEO(地理信息位置)。
- 豐富的功能。例如:鍵過期(緩存),發佈訂閱(消息隊列), Lua 腳本(自己實現 Redis 命令),事務,流水線(Pipeline,用於減少網絡開銷)。
- 簡單穩定。無外部庫依賴,單線程模型。
- 客戶端語言多。
- 持久化(支持兩種 持久化 方式 RDB 和 AOF)。
- 主從複製(分佈式的基礎)。
- 高可用(Redis Sentinel),分佈式(Redis Cluster)和 水平擴容。
2. Redis的應用場景
2.1. 緩存
合理的使用 緩存 能夠明顯加快訪問的速度,同時降低數據源的壓力。這也是 Redis 最常用的功能。Redis 提供了 鍵值過期時間(EXPIRE key seconds)設置,並且也提供了靈活控制 最大內存 和 內存溢出 後的 淘汰策略。
2.2. 排行榜
每個網站都有自己的排行榜,例如按照 熱度排名 的排行榜,發佈時間 的排行榜,答題排行榜 等等。Redis 提供了 列表(list)和 有序集合(zset)數據結構,合理的使用這些數據結構,可以很方便的構建各種排行榜系統。
2.3. 計數器
計數器 在網站應用中非常重要。例如:點贊數加 1,瀏覽數 加 1。還有常用的 限流操作,限制每個用戶每秒 訪問系統的次數 等等。Redis 支持 計數功能(INCR key),而且計數的 性能 也非常好,計數的同時也可以設置 超時時間,這樣就可以 實現限流。
2.4. 社交網絡
贊/踩,粉絲,共同好友/喜好,推送,下拉刷新等是社交網站必備的功能。由於社交網站 訪問量通常比較大,而且 傳統的數據庫 不太適合保存這類數據,Redis 提供的 數據結構 可以相對比較容易實現這些功能。
2.5. 消息隊列
Redis 提供的 發佈訂閱(PUB/SUB)和 阻塞隊列 的功能,雖然和專業的消息隊列比,還 不夠強大,但對於一般的消息隊列功能基本滿足。
3. Redis的安裝配置
下面介紹一下 Redis 的安裝流程。我會按照如下的順序,逐步搭建出 高可用 的 Redis 緩存服務器集群。
- Redis 單機服務器 搭建
- Redis 主從複製 搭建
- Redis-Sentinel 高可用 搭建
3.1. Redis單機服務器安裝
3.1.1. 下載並解壓
首先從 Redis 官網下載 Redis 源代碼並解壓,這裡使用的是 最新穩定版本 4.0.11。依次執行如下命令:
cd /usr/local/
wget http://download.redis.io/releases/redis-4.0.11.tar.gz
tar -zxvf redis-4.0.2.tar.gz
3.1.2. 編譯並安裝
下載並解壓完畢後,則對 源碼包 進行 編譯安裝,這裡 Redis 安裝路徑為 /usr/local/redis。
注意:make install PREFIX=目標安裝路徑
cd /usr/local/redis-4.0.11
make install PREFIX=/usr/local/redis
安裝完成時,/usr/local/redis/bin 目錄下會生成的幾個可執行的文件。
複製 Redis 相關命令到 /usr/local/bin 目錄下,這樣就可以直接執行這些命令,不用寫全路徑。
$ cd /usr/local/redis/bin/
$ sudo sudo cp redis-cli redis-server redis-sentinel /usr/local/bin
3.1.3. 修改Redis配置文件
安裝完成之後將 Redis 配置文件拷貝到 /usr/local 下,redis.conf 是 Redis 的配置文件,redis.conf 在 Redis 源碼目錄,port 默認是 6379。
$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/
Redis 配置文件主要參數解析參考:
# redis進程是否以守護進程的方式運行,yes為是,no為否(不以守護進程的方式運行會佔用一個終端)。
daemonize no
# 指定redis進程的PID文件存放位置
pidfile /var/run/redis.pid
# redis進程的端口號
port 6379
# 綁定的主機地址
bind 127.0.0.1
# 客戶端閒置多長時間後關閉連接,默認此參數為0即關閉此功能
timeout 300
# redis日誌級別,可用的級別有debug.verbose.notice.warning
loglevel verbose
# log文件輸出位置,如果進程以守護進程的方式運行,此處又將輸出文件設置為stdout的話,就會將日誌信息輸出到/dev/null裡面去了
logfile stdout
# 設置數據庫的數量,默認為0可以使用select <dbid>命令在連接上指定數據庫id
databases 16
# 指定在多少時間內刷新次數達到多少的時候會將數據同步到數據文件
save <seconds> <changes>
# 指定存儲至本地數據庫時是否壓縮文件,默認為yes即啟用存儲
rdbcompression yes
# 指定本地數據庫文件名
dbfilename dump.db
# 指定本地數據問就按存放位置
dir ./
# 指定當本機為slave服務時,設置master服務的IP地址及端口,在redis啟動的時候他會自動跟master進行數據同步
slaveof <masterip> <masterport>
# 當master設置了密碼保護時,slave服務連接master的密碼
masterauth <master-password>
# 設置redis連接密碼,如果配置了連接密碼,客戶端在連接redis是需要通過AUTH<password>命令提供密碼,默認關閉
requirepass footbared
# 設置同一時間最大客戶連接數,默認無限制。redis可以同時連接的客戶端數為redis程序可以打開的最大文件描述符,如果設置 maxclients 0,表示不作限制。當客戶端連接數到達限制時,Redis會關閉新的連接並向客戶端返回 max number of clients reached 錯誤信息
maxclients 128
# 指定Redis最大內存限制,Redis在啟動時會把數據加載到內存中,達到最大內存後,Redis會先嚐試清除已到期或即將到期的Key。當此方法處理後,仍然到達最大內存設置,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis新的vm機制,會把Key存放內存,Value會存放在swap區
maxmemory<bytes>
# 指定是否在每次更新操作後進行日誌記錄,Redis在默認情況下是異步的把數據寫入磁盤,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為redis本身同步數據文件是按上面save條件來同步的,所以有的數據會在一段時間內只存在於內存中。默認為no。
appendonly no
# 指定跟新日誌文件名默認為appendonly.aof
appendfilename appendonly.aof
# 指定更新日誌的條件,有三個可選參數 - no:表示等操作系統進行數據緩存同步到磁盤(快),always:表示每次更新操作後手動調用fsync()將數據寫到磁盤(慢,安全), everysec:表示每秒同步一次(折衷,默認值);
appendfsync everysec
- 設置後臺啟動
由於 Redis 默認是 前臺啟動,不建議使用。修改 Redis 配置文件,把 daemonize no 改為 daemonize yes。
daemonize yes
- 設置遠程訪問
Redis 默認只允許 本機訪問,把 bind 修改為 bind 0.0.0.0 此設置會變成 允許所有遠程訪問。如果想指定限制訪問,可設置對應的 IP。
bind 0.0.0.0
- 配置 Redis 日誌記錄
找到 logfile 配置,默認是:logfile "",改為自定義日誌文件路徑。
logfile /var/log/redis_6379.log
- 設置 Redis 請求密碼
把 requirepass 修改為 123456,修改之後重啟下服務
requirepass "123456"
有了密碼之後,進入客戶端,就得這樣訪問:
$ redis-cli -h 127.0.0.1 -p 6379 -a 123456
3.1.4. Redis的常用命令
- 啟動命令
$ redis-server /usr/local/redis.conf
- 關閉命令
$ redis-cli -h 127.0.0.1 -p 6379 shutdown
- 查看是否啟動
$ ps -ef | grep redis
- 進入客戶端
$ redis-cli
- 關閉客戶端
$ redis-cli shutdown
注意:不建議使用 kill -9,這種方式不但不會做持久化操作,還會造成緩衝區等資源不能優雅關閉。極端情況下造成 AOF 和 複製丟失數據 的情況。shutdown 還有一個參數,代表是否在關閉 redis 前,生成 持久化文件,命令為 redis-cli shutdown nosave|save。
- 設置為開機自動啟動
$ echo "redis-server /usr/local/redis.conf" >> /etc/rc.local
- 開放防火牆端口
# 添加規則
iptables -I INPUT -p tcp -m tcp --dport 6379 -j ACCEPT
# 保存規則
service iptables save
# 重啟iptables
service iptables restart
3.1.5. 註冊Redis為系統服務
在 /etc/init.d 目錄下添加 Redis 服務的 啟動,暫停 和 重啟 腳本:
$ sudo /etc/init.d/redis
腳本的內容如下:
#!/bin/sh
#
# redis - this script starts and stops the redis-server daemon
#
# chkconfig: - 85 15
# description: Redis is a persistent key-value database
# processname: redis-server
# config: /usr/local/redis/bin/redis-server
# config: /etc/redis.conf
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
redis="/usr/local/redis/bin/redis-server"
prog=$(basename $redis)
REDIS_CONF_FILE="/etc/redis.conf"
[ -f /etc/sysconfig/redis ] && . /etc/sysconfig/redis
lockfile=/var/lock/subsys/redis
start() {
[ -x $redis ] || exit 5
[ -f $REDIS_CONF_FILE ] || exit 6
echo -n $"Starting $prog: "
daemon $redis $REDIS_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading $prog: "
killproc $redis -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|orce-reload}"
exit 2
esac
賦予腳本文件可執行權限:
$ chmod 755 /etc/init.d/redis
啟動、停止和重啟 redis 服務:
service redis start
service redis stop
service redis restart
3.2. Redis主從複製集群安裝
3.2.1. Redis-Server配置說明
3.2.2. Redis主從架構配置
- 編輯 從機 的 Redis 配置文件,找到 210 行(大概)- #slaveof <masterip> <masterport>
- 。去掉該註釋,填寫 主服務器 的 IP 和 端口。
slaveof 10.206.20.231 16379
- 如果 主服務器 設置了密碼,還需要找到 masterauth <master-password> 這一行,去掉註釋,改為 masterauth 的主機密碼。
masterauth 123456
- 配置完成後重啟 從服務器 的 Redis 服務。
$ service redis restart
- 重啟完成之後,進入 主服務器 的 redis-cli 模式下,命令為 redis-cli -h 127.0.0.1 -p 16379 -a 123456。輸入 INFO replication 查詢到 當前主機 的 Redis 的狀態,連接上 主服務器 的 從服務器。
Redis 主服務器 的配置文件:
- redis.conf
daemonize yes
pidfile /var/run/redis-16379.pid
logfile /var/log/redis/redis-16379.log
port 16379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-16379.db
dir ./redis-workdir
masterauth 123456
requirepass 123456
Redis 從服務器 的配置文件:
- redis.conf
daemonize yes
pidfile /var/run/redis-26379.pid
logfile /var/log/redis/redis-26379.log
port 26379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-26379.db
dir ./redis-workdir
masterauth 123456
requirepass 123456
slaveof 127.0.0.1 16379
Redis 主服務器 的狀態如下:
# Replication
role:master
connected_slaves:1
slave0:ip=10.206.20.231,port=16379,state=online,offset=28,lag=1
master_replid:625ae9f362643da5337835beaeabfdca426198c7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
Redis 從服務器 的狀態如下:
# Replication
role:slave
master_host:10.206.20.231
master_port:26379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:210
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:625ae9f362643da5337835beaeabfdca426198c7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:210
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:210
3.2.3. Redis主從配置驗證
上面完成了基本的 主從配置,可以簡單的測試一下效果:
- 進入 主服務器 的 redis-cli 模式,然後 set 一個值,比如:
> set master_port "16379"
OK
- 切換進入 從服務器 的 redis-cli 的模式,查詢剛剛設置的值看是否存在:
> get master_port
"16379"
此時,我們可以發現是可以獲取到值的,Redis 的 主從模式 正常工作。
小結
本文簡單的說明了 Redis 的相關 特性 和 應用場景,詳細地給出 Redis 單服務器的 編譯,安裝,配置 和 啟動,進一步引入了 Redis 主從複製 的相關原理和詳細配置。關於 Redis 的 高可用機制 和 集群搭建,下文將給出詳細的說明。