緩存系列之一:buffer、cache與瀏覽器緩存php
一:緩存是爲了調節速度不一致的兩個或多個不一樣的物質的速度,在中間對速度較快的一方起到一個加速訪問速度較慢的一方的做用,好比CPU的一級、二級緩存是保存了CPU最近常常訪問的數據,內存是保存CPU常常訪問硬盤的數據,並且硬盤也有大小不一的緩存,甚至是物理服務器的raid 卡有也緩存,都是爲了起到加速CPU 訪問硬盤數據的目的,由於CPU的速度太快了,CPU須要的數據硬盤每每不能在短期內知足CPU的需求,所以PCU緩存、內存、Raid 卡以及硬盤緩存就在必定程度上知足了CPU的數據需求,即CPU 從緩存讀取數據能夠大幅提升CPU的工做效率。html
1.1:理解buffer和cache:
buffer:緩衝也叫寫緩衝,通常用於寫操做,能夠將數據先寫入內存在寫入磁盤,buffer 通常用於寫緩衝,用於解決不一樣介質的速度不一致的緩衝,先將數據臨時寫入到裏本身最近的地方,以提升寫入速度。
CPU會把數據線寫到內存的磁盤緩衝區,而後就認爲數據已經寫入完成看,而後內核的線程在後面的時間在寫入磁盤,因此服務器忽然斷電會丟失內存中的部分數據。
cache:緩存也叫讀緩存,通常用於讀操做,CPU讀文件從內存讀,若是內存沒有就先從硬盤讀到內存再讀到CPU,將須要頻繁讀取的數據放在裏本身最近的緩存區域,下次讀取的時候便可快速讀取。前端
1.2:cache的保存位置:
客戶端:瀏覽器
內存:本地服務器、遠程服務器
硬盤:本機硬盤、遠程服務器硬盤
速度對比:
客戶端瀏覽器-內存-遠程內存-硬盤-遠程硬盤java
1.3:cache的特性:node
1.過時時間
2.強制過時,源網站更新圖片後CDN是不會更新的,須要強制是圖片緩存過時
3.命中率,即緩存的讀取命中率python
1.4:將內存的數據保存到硬盤,而後清空內存,可能有些內存的數據是進程死掉沒法釋放的:
#sync # 將緩衝區中的數據快速寫入到硬盤
# cat /proc/sys/vm/drop_caches
0
#1是用來清空最近放問過的文件頁面緩存
#2是用來清空文件節點緩存和目錄項緩存
#3是用來清空1和2全部內容的緩存。linux
二:用戶層緩存:
2.1:DNS 緩存:
2.1.1:默認爲60秒,即60秒以內在訪問同一個域名就不在進行DNS解析:
查看chrome瀏覽器的DNS緩存:
chrome://net-internals/#dnsnginx

2.1.2:DNS 預獲取,僅在HTML 5中支持,當一個頁面中包含多個域名的時候瀏覽器會先嚐試解析域名並進行緩存,以後再使用的時候便可直接只有不須要再進行DNS 解析:

2.2:瀏覽器緩存:
2.2.1:火狐瀏覽器的緩存位置:c++

2.2.2:文件的訪問時間、最後修改時間和更改時間:git
# stat index.php
File: ‘index.php’
Size: 4311 Blocks: 16 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 68497957 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 497/ nginx) Gid: ( 497/ nginx)
Access: 2017-07-21 02:00:03.046492759 +0800 # 最後一次讀取的時間
Modify: 2016-04-07 18:32:47.000000000 +0800 # 最後一次更改內容致使block內容發生變化的時間
Change: 2017-01-11 15:55:35.872038074 +0800 # 權限等發生更改致使inode發送變化的時間
2.2.3:緩存協商機制之最後修改時間:系統調用會獲取文件的最後修改時間,若是沒有發生變化就返回給瀏覽器304的狀態碼,表示沒有發生變化,而後瀏覽器就使用的本地的緩存展現資源

2.2.4:緩存協商之Etag:
瀏覽器在返回的報文中包含一個etag的標記,而後瀏覽器將etag保存,再次收到Etag的時候會進行判斷,若是Etag沒有發生變化就使用本地緩存

2.2.5:緩存協商之過時時間,以上兩種都須要發送請求,即無論資源是否過時都要發送請求進行協商,這樣會消耗沒必要要的時間,所以有了緩存的過時時間,即第一次請求資源的時候帶一個資源的過時時間,默認爲30天,當前這種方式使用的比表較多,可是沒法保證客戶的時間都是準確而且一致的,所以假如一個最大生存週期,使用用戶本地的時間計算緩存數據是否超過多少天,下面的過時時間爲2017年,可是緩存的最大生存週期計算爲天等於691200秒即2天,過時時間以下:

最大生存週期,單位爲秒,根據客戶端的時間日後計算是否超出緩存天數
三:關於刷新:
3.1:在瀏覽器輸入地址欄直接按回車:
瀏覽器的全部沒有過時的數據直接使用本地緩存,即沒有過時的數據不會發送緩存協商的請求。
3.2:按F5或者瀏覽器上的刷新按鈕:
瀏覽器會在請求頭部附加緩存協商報文,瀏覽器不能直接使用本地緩存,須要經過驗證纔可使用,可是過時時間沒有超過日期的緩存不受影響,受影響的是最後修改時間和Etag。
3.3:ctrl+F5或者是按住ctrl+刷新,這是強制刷新,瀏覽器將發送全部的請求到服務器,不會使用本地緩存
3.4:如何讓客戶端獲取最新的服務器數據資源:
3.4.1:更改資源名稱,這樣每次都得改,比較麻煩並且容易出錯
3.4.2:增長時間戳,新版本的使用較新的時間戳,瀏覽器發現時間較新就會獲取新的資源,例如xxx.js?20170724比xxx.js?20170101新
3.4.3:靜態資源使用CDN要加參數,好比URL 能夠帶參數,帶參數的話CND會對該url進行hash計算,當源url資源發送變化(故意的把參數更改,由於靜態資源更新了,要求CND也更新)CDN 發現hash值不同就會進行更新,另外CDN 能夠根據後綴名判斷加不加參數,即某些後綴的有參數有些後綴沒有參數
緩存系列之二:CDN與其餘層面緩存
一:內容分發網絡(Content Delivery Network),經過將服務內容分發至全網加速節點,利用全球調度系統使用戶可以就近獲取,有效下降訪問延遲,提高服務可用性,CDN 第一下降機房的使用帶寬,由於不少資源經過CDN就直接返回用戶了,第二解決不一樣運營商之間的互聯,由於可讓聯通的網絡訪問聯通讓電信的網絡訪問電信,起到加速用戶訪問的目的, 第三:解決用戶訪問的地域問題,就近返回用戶資源。
百度CDN:https://cloud.baidu.com/product/cdn.html
阿里CDN:https://www.aliyun.com/product/cdn?spm=5176.8269123.416540.50.728y8n
騰訊CDN:https://www.qcloud.com/product/cdn
1.1:用戶請求的具體流程:

1.2:關於302調度:
如用的是是聯通的網絡,可是設置了一個電信的DNS,或者電信的用戶設置了一個聯通的DNS,在剛創建鏈接的時候CDN法獲取到用戶的真實IP,而是隻能獲取到用戶的local DNS而斷定用戶是聯通仍是電信的網絡,假如設置了錯誤的運營商DNS會被調度到錯誤的CDN 邊緣節點,當和邊緣節點鏈接以後就能夠獲取到用戶的真實IP從而判斷用戶是聯通仍是電信的網絡,若是是電信的網絡被調度到了聯通的CDN邊緣節點或者是電信的網絡被調度到了聯通的CND邊緣節點,那麼能夠給用戶再發送一個302重定向的回覆,用戶的瀏覽器再根據新的地址進行鏈接,便可訪問到正確的CND 邊緣節點。
1.3:內容分發與分層:
提早對靜態內容進行預緩存,避免大量的請求回源,致使主站網絡帶寬被打滿而致使數據沒法更新,另外CDN能夠將數據根據訪問的熱度不通而進行不通級別的緩存,例如訪問量最高的資源訪問CDN 邊緣節點的內存,其次的放在SSD或者SATA,再其次的放在雲存儲,這樣兼顧了速度與成本。
1.4:CND的主要優點:
緩存-緩存到最快的地方如內存,緩存的數據準確命中率高,訪問速度就快
調度準確-將用戶調度到最近的邊緣節點
性能優化-CDN 性能相關
安全相關-抵禦攻擊等
1.5:自建CDN優缺點:
nginx+squid、nginx+varnish、nginx+ATS等方式能夠自建
優勢:
自建CDN 比較靈活,能夠在訪問用戶較多的地方多部署服務器
成本比較容易控制
缺點:
費用高
團隊技術要求高
問題不便排查,出問題不容易搞的定
二:應用層緩存:
2.1:應用程序級別的緩存:
指的是編譯性語言須要編譯成二進制可執行代碼,好比c/c++/go等,其編譯好以後就能夠直接運行,另外還有解釋性語言,好比php/python先編譯成operate code即中間碼也叫字節碼,中間碼不能直接運行須要解釋器解釋成機器碼以後才能執行,所以中間碼也算是緩存,php在5.5.0以後已經綁定了OPCache擴展,對於PHP 5.2,5.3,5.4等版本中可使用PECL 擴展中的OPcache庫,在5.5版本以前可使用APC/Xcache等進行緩存也能夠實現,可是5.5以後已經內置OPcache 就不須要APC和Xcache了,開啓的話在編譯PHP的時候使用–enable-opcache便可,所以使用PHP 推薦使用5.5以後的版本並打開OPcache以提高性能,另外若是在開啓OPcache的狀況下使用了軟鏈接的方式部署代碼會致使代碼不更新,當代碼更新以後須要重啓php-fpm才能夠識別並將新的代碼進行編譯成字節碼並經過解釋器解釋給訪問用戶,apache 的mod_cache如今通常不使用,nginx的FastCGI緩存會致使代碼代碼更新後用戶訪問不生效,所以也不使用,因此動態語言就使用OPcache,FastCGI會致使不生效就直接關閉。
2.2:動態頁面靜態化:
將java的動態頁面靜態化,好比將每一個具體產品的web頁面靜態化爲html文件,而後經過nginx 的rewrite功能發佈,即用戶最終訪問到的某個產品的web 頁面是靜態的頁面,靜態頁面的訪問速度是比較快的,生成的靜態頁面能夠經過nfs、rsync、分佈式存儲等方式推送到各web服務器,若是靜態頁面生成的信息是錯誤的,能夠將信息更改後經過推送平臺從新生成新的web頁面並同步到各web服務器,平時能夠經過每間隔幾個小時自動生成靜態頁面,好比每6小時生成一次動態頁面並同步到各web服務器。
三:其餘緩存:
3.1數據緩存
3.1.1:分佈式緩存:redis、memcached
3.1.2:數據庫:MySQL的Innodb緩存、MYISA緩存
3.2:系統層:
3.2.1:操做系統
CPU緩存(L1的數據緩存和L1的指令緩存)、二級緩存、三級緩存
內存:buffer和cache、內存表緩存
3.3:物理層:
3.3.1:磁盤緩存:磁盤有本身的緩存,用RAID 卡的時候磁盤的緩存是關閉的。
3.3.2:RAID 卡緩存:服務器在使用raid 卡的時候磁盤的緩存默認是關閉的,避免由於忽然斷電而致使的緩存裏面的數據丟失,看看到磁盤的換粗是關閉的,由於raid 卡能夠帶電池供電。
3.3.3:RAID 卡的基本操做命令:
查看當前RAID卡緩存策略
MegaCli64 -LDinfo -Lall -aAll
Default Cache Policy: WriteThrough, ReadAheadNone, Direct, No Write Cache if Bad BBU
Current Cache Policy: WriteThrough, ReadAheadNone, Direct, No Write Cache if Bad BBU
第一部分:
WriteBack:寫緩存策略
WriteThrough:直接寫入磁盤,不使用RAID卡緩存。
第二部分:
ReadAheadNone:不開啓預讀
ReadAhead:開啓預讀,在讀操做的時候,預先把後面順序的數據載入raid卡緩存,在順序讀的環境中能提供很好的性能,可是在隨機讀的環境中反而下降讀的性能(適合文件系統,不適合數據庫系統)
ReadAdaptive:自適應預讀,在緩存和I/O空閒時選擇預讀,默認策略。
第三部分:
Direct:讀操做不緩存到RAID卡緩存。
Cached:讀操做緩存到RAID卡緩存。
第四部分:若是BBU(電池)出現問題是否啓用Write Cache
No Write Cache if Bad BBU:若是BBU出現問題不使用Write Cache,從WriteBack自動切換到WriteThrough,默認配置。
Write Cache OK if Bad BBU: 若是BBU出現問題仍啓用Write Cache,這種配置是很是不安全的,除非是有UPS或者雙電源的狀況下。
RAID卡策略更改
修改WriteBack:
MegaCli64 -LDSetProp -WB -Lall -aAll
修改WriteThrough:
MegaCli64 -LDSetProp -WT -Lall -aAll
修改No Write Cache if Bad BBU:
MegaCli64 -LDSetProp -NoCachedBadBBU -Lall -aAll
修改Write Cache OK if Bad BBU:
MegaCli64 -LDSetProp -CachedBadBBU -Lall -aAll
4.其它相關命令
查看機器型號 # dmidecode | grep"Product"
查看廠商 # dmidecode| grep "Manufacturer"
查看序列號 # dmidecode | grep "Serial Number"
查看CPU信息 # dmidecode | grep "CPU"
查看CPU個數 # dmidecode | grep "Socket Designation: CPU" |wc –l
查看出廠日期 # dmidecode | grep"Date"
查看充電狀態 # MegaCli64 -AdpBbuCmd-GetBbuStatus -aALL |grep "Charger Status"
顯示BBU狀態信息 # MegaCli64 -AdpBbuCmd-GetBbuStatus –aALL
顯示BBU容量信息 # MegaCli64 -AdpBbuCmd-GetBbuCapacityInfo –aALL
顯示BBU設計參數 # MegaCli64 -AdpBbuCmd-GetBbuDesignInfo –aALL
顯示當前BBU屬性 # MegaCli64 -AdpBbuCmd-GetBbuProperties –aALL
查看充電進度百分比 # MegaCli64 -AdpBbuCmd-GetBbuStatus -aALL |grep "Relative State of Charge"
查詢Raid陣列數 # MegaCli64 -cfgdsply -aALL|grep "Number of DISK GROUPS:"
顯示Raid卡型號,Raid設置,Disk相關信息 # MegaCli64-cfgdsply –aALL
顯示全部物理信息 # MegaCli64 -PDList-aALL
顯示全部邏輯磁盤組信息 # MegaCli64 -LDInfo -LALL–aAll
查看物理磁盤重建進度(重要) # MegaCli64 -PDRbld-ShowProg -PhysDrv [1:5] -a0
查看適配器個數 #MegaCli64 –adpCount
查看適配器時間 #MegaCli64 -AdpGetTime–aALL
顯示全部適配器信息 #MegaCli64 -AdpAllInfo–aAll
查看Cache 策略設置 # MegaCli64 -cfgdsply -aALL|grep Polic
################################################################################
一:Redis是一個開源的key-value存儲系統。與Memcached相似,Redis將大部分數據存儲在內存中,支持的數據類型包括:字符串、哈希表、鏈表、集合、有序集合以及基於這些數據類型的相關操做。Redis使用C語言開發,在大多數像Linux、BSD和Solaris等POSIX系統上無需任何外部依賴就可使用。Redis支持的客戶端語言也很是豐富,經常使用的計算機語言如C、C#、C++、Object-C、PHP、Python、 Java、Perl、Lua、Erlang等均有可用的客戶端來訪問Redis服務器。當前Redis的應用已經很是普遍,國內像新浪、淘寶,國外像 Flickr、Github等均在使用Redis的緩存服務。 Redis的安裝很是方便,只需從http://redis.io/download獲取源碼,而後make && make install便可。默認狀況下,Redis的服務器啓動程序和客戶端程序會安裝到/usr/local/bin目錄下。在啓動Redis服務器時,咱們須要爲其指定一個配置文件,缺省狀況下配置文件在Redis的源碼目錄下,文件名爲redis.conf。
1.1:二進制安裝redis:
# cd /usr/local/src/
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
tar -zxvf redis-3.2.9.tar.gz
cd redis-3.2.9
ln -sv /usr/local/src/redis-3.2.9 /usr/local/redis
make
# cp utils/redis_init_script /etc/init.d/redis #啓動腳本
# chmod a+x /etc/init.d/redis
1.2:啓動腳本默認的配置內容:
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
REDISPORT=6379
EXEC=/usr/local/redis/src/redis-server
CLIEXEC=/usr/local/redis/src/redis-cli
PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
添加環境變量:
# vim /etc/profile
export REDIS_HOME=/usr/local/redis
export PATH=$REDIS_HOME/src:$PATH
1.3:準備配置文件:
# mkdir /etc/redis
# cp redis.conf /etc/redis/6379.conf
1.4:啓動redis服務:
# /etc/init.d/redis start
Starting Redis server...
9164:M 10 Jul 17:54:47.959 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 9164
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
9164:M 10 Jul 17:54:47.962 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
9164:M 10 Jul 17:54:47.962 # Server started, Redis version 3.2.9
9164:M 10 Jul 17:54:47.962 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
9164:M 10 Jul 17:54:47.962 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
9164:M 10 Jul 17:54:47.963 * The server is now ready to accept connections on port 6379
1.4:配置文件信息:
#daemonize no 默認狀況下, redis 不是在後臺運行的,若是須要在後臺運行,把該項的值更改成 yes
daemonize yes
# 當 redis 在後臺運行的時候, Redis 默認會把 pid 文件放在 /var/run/redis.pid ,你能夠配置到其餘地址。
# 當運行多個 redis 服務時,須要指定不一樣的 pid 文件和端口
pidfile /var/run/redis_6379.pid
# 指定 redis 運行的端口,默認是 6379
port 6379
# 在高併發的環境中,爲避免慢客戶端的鏈接問題,須要設置一個高速後臺日誌
tcp-backlog 511
# 指定 redis 只接收來自於該 IP 地址的請求,若是不進行設置,那麼將處理全部請求
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1
# 設置客戶端鏈接時的超時時間,單位爲秒。當客戶端在這段時間內沒有發出任何指令,那麼關閉該鏈接
# 0 是關閉此設置
timeout 0
# TCP keepalive
# 在 Linux 上,指定值(秒)用於發送 ACKs 的時間。注意關閉鏈接須要雙倍的時間。默認爲 0 。
tcp-keepalive 0
# 指定日誌記錄級別,生產環境推薦 notice
# Redis 總共支持四個級別: debug 、 verbose 、 notice 、 warning ,默認爲 verbose
# debug 記錄不少信息,用於開發和測試
# varbose 有用的信息,不像 debug 會記錄那麼多
# notice 普通的 verbose ,經常使用於生產環境
# warning 只有很是重要或者嚴重的信息會記錄到日誌
loglevel notice
# 配置 log 文件地址
# 默認值爲 stdout ,標準輸出,若後臺模式會輸出到 /dev/null 。
logfile /var/log/redis/redis.log
# 可用數據庫數
# 默認值爲 16 ,默認數據庫爲 0 ,數據庫範圍在 0- ( database-1 )之間
databases 16
################################ 快照#################################
# 保存數據到磁盤,格式以下 :
# save
# 指出在多長時間內,有多少次更新操做,就將數據同步到數據文件 rdb 。
# 至關於條件觸發抓取快照,這個能夠多個條件配合
# 好比默認配置文件中的設置,就設置了三個條件
# save 900 1 900 秒內至少有 1 個 key 被改變
# save 300 10 300 秒內至少有 300 個 key 被改變
# save 60 10000 60 秒內至少有 10000 個 key 被改變
# save 900 1
# save 300 10
# save 60 10000
# 後臺存儲錯誤中止寫。
stop-writes-on-bgsave-error yes
# 存儲至本地數據庫時(持久化到 rdb 文件)是否壓縮數據,默認爲 yes
rdbcompression yes
# RDB 文件的是否直接偶像 chcksum
rdbchecksum yes
# 本地持久化數據庫文件名,默認值爲 dump.rdb
dbfilename dump.rdb
# 工做目錄
# 數據庫鏡像備份的文件放置的路徑。
# 這裏的路徑跟文件名要分開配置是由於 redis 在進行備份時,先會將當前數據庫的狀態寫入到一個臨時文件中,等備份完成,
# 再把該該臨時文件替換爲上面所指定的文件,而這裏的臨時文件和上面所配置的備份文件都會放在這個指定的路徑當中。
# AOF 文件也會存放在這個目錄下面
# 注意這裏必須制定一個目錄而不是文件
dir /var/lib/redis-server/
################################# 複製 #################################
# 主從複製 . 設置該數據庫爲其餘數據庫的從數據庫 .
# 設置當本機爲 slav 服務時,設置 master 服務的 IP 地址及端口,在 Redis 啓動時,它會自動從 master 進行數據同步
# slaveof
# 當 master 服務設置了密碼保護時 ( 用 requirepass 制定的密碼 )
# slave 服務鏈接 master 的密碼
# masterauth
# 當從庫同主機失去鏈接或者複製正在進行,從機庫有兩種運行方式:
# 1) 若是 slave-serve-stale-data 設置爲 yes( 默認設置 ) ,從庫會繼續響應客戶端的請求
# 2) 若是 slave-serve-stale-data 是指爲 no ,出去 INFO 和 SLAVOF 命令以外的任何請求都會返回一個
# 錯誤 "SYNC with master in progress"
slave-serve-stale-data yes
# 配置 slave 實例是否接受寫。寫 slave 對存儲短暫數據(在同 master 數據同步後能夠很容易地被刪除)是有用的,但未配置的狀況下,客戶端寫可能會發送問題。
# 從 Redis2.6 後,默認 slave 爲 read-only
slaveread-only yes
# 從庫會按照一個時間間隔向主庫發送 PINGs. 能夠經過 repl-ping-slave-period 設置這個時間間隔,默認是 10 秒
# repl-ping-slave-period 10
# repl-timeout 設置主庫批量數據傳輸時間或者 ping 回覆時間間隔,默認值是 60 秒
# 必定要確保 repl-timeout 大於 repl-ping-slave-period
# repl-timeout 60
# 在 slave socket 的 SYNC 後禁用 TCP_NODELAY
# 若是選擇「 yes 」 ,Redis 將使用一個較小的數字 TCP 數據包和更少的帶寬將數據發送到 slave , 可是這可能致使數據發送到 slave 端會有延遲 , 若是是 Linux kernel 的默認配置,會達到 40 毫秒 .
# 若是選擇 "no" ,則發送數據到 slave 端的延遲會下降,但將使用更多的帶寬用於複製 .
repl-disable-tcp-nodelay no
# 設置複製的後臺日誌大小。
# 複製的後臺日誌越大, slave 斷開鏈接及後來可能執行部分複製花的時間就越長。
# 後臺日誌在至少有一個 slave 鏈接時,僅僅分配一次。
# repl-backlog-size 1mb
# 在 master 再也不鏈接 slave 後,後臺日誌將被釋放。下面的配置定義從最後一個 slave 斷開鏈接後須要釋放的時間(秒)。
# 0 意味着從不釋放後臺日誌
# repl-backlog-ttl 3600
# 若是 master 不能再正常工做,那麼會在多個 slave 中,選擇優先值最小的一個 slave 提高爲 master ,優先值爲 0 表示不能提高爲 master 。
slave-priority 100
# 若是少於 N 個 slave 鏈接,且延遲時間 <=M 秒,則 master 可配置中止接受寫操做。
# 例如須要至少 3 個 slave 鏈接,且延遲 <=10 秒的配置:
# min-slaves-to-write 3
# min-slaves-max-lag 10
# 設置 0 爲禁用
# 默認 min-slaves-to-write 爲 0 (禁用), min-slaves-max-lag 爲 10
################################## 安全 ###################################
# 設置客戶端鏈接後進行任何其餘指定前須要使用的密碼。
# 警告:由於 redis 速度至關快,因此在一臺比較好的服務器下,一個外部的用戶能夠在一秒鐘進行 150K 次的密碼嘗試,這意味着你須要指定很是很是強大的密碼來防止暴力破解
# requirepass foobared
# 命令重命名 .
# 在一個共享環境下能夠重命名相對危險的命令。好比把 CONFIG 重名爲一個不容易猜想的字符。
# 舉例 :
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
# 若是想刪除一個命令,直接把它重命名爲一個空字符 "" 便可,以下:
# rename-command CONFIG ""
################################### 約束###################################
#設置同一時間最大客戶端鏈接數,默認無限制,
#Redis 能夠同時打開的客戶端鏈接數爲 Redis 進程能夠打開的最大文件描述符數,
#若是設置 maxclients 0 ,表示不做限制。
#當客戶端鏈接數到達限制時, Redis 會關閉新的鏈接並向客戶端返回 max number of clients reached 錯誤信息
# maxclients 10000
# 指定 Redis 最大內存限制, Redis 在啓動時會把數據加載到內存中,達到最大內存後, Redis 會按照清除策略嘗試清除已到期的 Key
# 若是 Redis 依照策略清除後沒法提供足夠空間,或者策略設置爲 」noeviction」 ,則使用更多空間的命令將會報錯,例如 SET, LPUSH 等。但仍然能夠進行讀取操做
# 注意: Redis 新的 vm 機制,會把 Key 存放內存, Value 會存放在 swap 區
# 該選項對 LRU 策略頗有用。
# maxmemory 的設置比較適合於把 redis 看成於相似 memcached 的緩存來使用,而不適合當作一個真實的 DB 。
# 當把 Redis 當作一個真實的數據庫使用的時候,內存使用將是一個很大的開銷
# maxmemory
# 當內存達到最大值的時候 Redis 會選擇刪除哪些數據?有五種方式可供選擇
# volatile-lru -> 利用 LRU 算法移除設置過過時時間的 key (LRU: 最近使用 Least RecentlyUsed )
# allkeys-lru -> 利用 LRU 算法移除任何 key
# volatile-random -> 移除設置過過時時間的隨機 key
# allkeys->random -> remove a randomkey, any key
# volatile-ttl -> 移除即將過時的 key(minor TTL)
# noeviction -> 不移除任何能夠,只是返回一個寫錯誤
# 注意:對於上面的策略,若是沒有合適的 key 能夠移除,當寫的時候 Redis 會返回一個錯誤
# 默認是 : volatile-lru
# maxmemory-policy volatile-lru
# LRU 和 minimal TTL 算法都不是精準的算法,可是相對精確的算法 ( 爲了節省內存 ) ,隨意你能夠選擇樣本大小進行檢測。
# Redis 默認的灰選擇 3 個樣本進行檢測,你能夠經過 maxmemory-samples 進行設置
# maxmemory-samples 3
############################## AOF###############################
# 默認狀況下, redis 會在後臺異步的把數據庫鏡像備份到磁盤,可是該備份是很是耗時的,並且備份也不能很頻繁,若是發生諸如拉閘限電、拔插頭等情況,那麼將形成比較大範圍的數據丟失。
# 因此 redis 提供了另一種更加高效的數據庫備份及災難恢復方式。
# 開啓 append only 模式以後, redis 會把所接收到的每一次寫操做請求都追加到 appendonly.aof 文件中,當 redis 從新啓動時,會從該文件恢復出以前的狀態。
# 可是這樣會形成 appendonly.aof 文件過大,因此 redis 還支持了 BGREWRITEAOF 指令,對 appendonly.aof 進行從新整理。
# 你能夠同時開啓 asynchronous dumps 和 AOF
appendonly no
# AOF 文件名稱 ( 默認 : "appendonly.aof")
# appendfilename appendonly.aof
# Redis 支持三種同步 AOF 文件的策略 :
# no: 不進行同步,系統去操做 . Faster.
# always: always 表示每次有寫操做都進行同步 . Slow, Safest.
# everysec: 表示對寫操做進行累積,每秒同步一次 . Compromise.
# 默認是 "everysec" ,按照速度和安全折中這是最好的。
# 若是想讓 Redis 能更高效的運行,你也能夠設置爲 "no" ,讓操做系統決定何時去執行
# 或者相反想讓數據更安全你也能夠設置爲 "always"
# 若是不肯定就用 "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no
# AOF 策略設置爲 always 或者 everysec 時,後臺處理進程 ( 後臺保存或者 AOF 日誌重寫 ) 會執行大量的 I/O 操做
# 在某些 Linux 配置中會阻止過長的 fsync() 請求。注意如今沒有任何修復,即便 fsync 在另一個線程進行處理
# 爲了減緩這個問題,能夠設置下面這個參數 no-appendfsync-on-rewrite
no-appendfsync-on-rewrite no
# AOF 自動重寫
# 當 AOF 文件增加到必定大小的時候 Redis 可以調用 BGREWRITEAOF 對日誌文件進行重寫
# 它是這樣工做的: Redis 會記住上次進行些日誌後文件的大小 ( 若是從開機以來還沒進行太重寫,那日子大小在開機的時候肯定 )
# 基礎大小會同如今的大小進行比較。若是如今的大小比基礎大小大制定的百分比,重寫功能將啓動
# 同時須要指定一個最小大小用於 AOF 重寫,這個用於阻止即便文件很小可是增加幅度很大也去重寫 AOF 文件的狀況
# 設置 percentage 爲 0 就關閉這個特性
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
################################ LUASCRIPTING #############################
# 一個 Lua 腳本最長的執行時間爲 5000 毫秒( 5 秒),若是爲 0 或負數表示無限執行時間。
lua-time-limit 5000
################################LOW LOG################################
# Redis Slow Log 記錄超過特定執行時間的命令。執行時間不包括 I/O 計算好比鏈接客戶端,返回結果等,只是命令執行時間
# 能夠經過個參數設置 slow log :一個是告訴 Redis 執行超過多少時間被記錄的參數 slowlog-log-slower-than( 微妙 ) ,
# 另外一個是 slow log 的長度。當一個新命令被記錄的時候最先的命令將被從隊列中移除
# 下面的時間以微妙爲單位,所以 1000000 表明一秒。
# 注意指定一個負數將關閉慢日誌,而設置爲 0 將強制每一個命令都會記錄
slowlog-log-slower-than 10000
# 對日誌長度沒有限制,只是要注意它會消耗內存
# 能夠經過 SLOWLOG RESET 回收被慢日誌消耗的內存
# 推薦使用默認值 128 ,當慢日誌超過 128 時,最早進入隊列的記錄會被踢出
slowlog-max-len 128
################################ 事件通知 #############################
# 當事件發生時, Redis 能夠通知 Pub/Sub 客戶端。
# 能夠在下表中選擇 Redis 要通知的事件類型。事件類型由單個字符來標識:
# K Keyspace 事件,以 _keyspace@_ 的前綴方式發佈
# E Keyevent 事件,以 _keysevent@_ 的前綴方式發佈
# g 通用事件(不指定類型),像 DEL, EXPIRE, RENAME, …
# $ String 命令
# s Set 命令
# h Hash 命令
# z 有序集合命令
# x 過時事件(每次 key 過時時生成)
# e 清除事件(當 key 在內存被清除時生成)
# A g$lshzxe 的別稱,所以 」AKE」 意味着全部的事件
# notify-keyspace-events 帶一個由 0 到多個字符組成的字符串參數。空字符串意思是通知被禁用。
# 例子:啓用 list 和通用事件:
# notify-keyspace-events Elg
# 默認所用的通知被禁用,由於用戶一般不須要改特性,而且該特性會有性能損耗。
# 注意若是你不指定至少 K 或 E 之一,不會發送任何事件。
notify-keyspace-events 「」
############################## 高級配置 ###############################
# 當 hash 中包含超過指定元素個數而且最大的元素沒有超過臨界時,
# hash 將以一種特殊的編碼方式(大大減小內存使用)來存儲,這裏能夠設置這兩個臨界值
# Redis Hash 對應 Value 內部實際就是一個 HashMap ,實際這裏會有 2 種不一樣實現,
# 這個 Hash 的成員比較少時 Redis 爲了節省內存會採用相似一維數組的方式來緊湊存儲,而不會採用真正的 HashMap 結構,對應的 valueredisObject 的 encoding 爲 zipmap,
# 當成員數量增大時會自動轉成真正的 HashMap, 此時 encoding 爲 ht 。
hash-max-zipmap-entries 512
hash-max-zipmap-value 64
# 和 Hash 同樣,多個小的 list 以特定的方式編碼來節省空間。
# list 數據類型節點值大小小於多少字節會採用緊湊存儲格式。
list-max-ziplist-entries 512
list-max-ziplist-value 64
# set 數據類型內部數據若是所有是數值型,且包含多少節點如下會採用緊湊格式存儲。
set-max-intset-entries 512
# 和 hashe 和 list 同樣 , 排序的 set 在指定的長度內以指定編碼方式存儲以節省空間
# zsort 數據類型節點值大小小於多少字節會採用緊湊存儲格式。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# Redis 將在每 100 毫秒時使用 1 毫秒的 CPU 時間來對 redis 的 hash 表進行從新 hash ,能夠下降內存的使用
# 當你的使用場景中,有很是嚴格的實時性須要,不可以接受 Redis 時不時的對請求有 2 毫秒的延遲的話,把這項配置爲 no 。
# 若是沒有這麼嚴格的實時性要求,能夠設置爲 yes ,以便可以儘量快的釋放內存
activerehashing yes
# 客戶端的輸出緩衝區的限制,由於某種緣由客戶端從服務器讀取數據的速度不夠快,
# 可用於強制斷開鏈接(一個常見的緣由是一個發佈 / 訂閱客戶端消費消息的速度沒法遇上生產它們的速度)。
# 能夠三種不一樣客戶端的方式進行設置:
# normal -> 正常客戶端
# slave -> slave 和 MONITOR 客戶端
# pubsub -> 至少訂閱了一個 pubsub channel 或 pattern 的客戶端
# 每一個 client-output-buffer-limit 語法 :
# client-output-buffer-limit
# 一旦達到硬限制客戶端會當即斷開,或者達到軟限制並保持達成的指定秒數(連續)。
# 例如,若是硬限制爲 32 兆字節和軟限制爲 16 兆字節 /10 秒,客戶端將會當即斷開
# 若是輸出緩衝區的大小達到 32 兆字節,客戶端達到 16 兆字節和連續超過了限制 10 秒,也將斷開鏈接。
# 默認 normal 客戶端不作限制,由於他們在一個請求後未要求時(以推的方式)不接收數據,
# 只有異步客戶端可能會出現請求數據的速度比它能夠讀取的速度快的場景。
# 把硬限制和軟限制都設置爲 0 來禁用該特性
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb60
client-output-buffer-limit pubsub 32mb 8mb60
# Redis 調用內部函數來執行許多後臺任務,如關閉客戶端超時的鏈接,清除過時的 Key ,等等。
# 不是全部的任務都以相同的頻率執行,但 Redis 依照指定的「 Hz 」值來執行檢查任務。
# 默認狀況下,「 Hz 」的被設定爲 10 。
# 提升該值將在 Redis 空閒時使用更多的 CPU 時,但同時當有多個 key 同時到期會使 Redis 的反應更靈敏,以及超時能夠更精確地處理。
# 範圍是 1 到 500 之間,可是值超過 100 一般不是一個好主意。
# 大多數用戶應該使用 10 這個預設值,只有在很是低的延遲的狀況下有必要提升最大到 100 。
hz 10
# 當一個子節點重寫 AOF 文件時,若是啓用下面的選項,則文件每生成 32M 數據進行同步。
aof-rewrite-incremental-fsync yes
二:redis數據類型的基本操做:
2.1:字符串:
2.1.1:設置和獲取key的值:
# redis-cli -h 127.0.0.1
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> get key1 #不能一次獲取多個key的值
"value1"
2.1.2:顯示全部的key:
127.0.0.1:6379> KEYS *
1) "key2"
2) "key1"
2.1.3:判斷key是否存在:
127.0.0.1:6379> EXISTS key1
(integer) 1 # 1表示存在
127.0.0.1:6379> EXISTS key10
(integer) 0 # 0表示不存在
2.1.4:刪除指定的key:
127.0.0.1:6379> del key1 key3
(integer) 2 #1爲刪除了幾個key的數量,沒有的key刪除不報錯
2.1.5:獲取key的類型:
127.0.0.1:6379> LPUSH l1 "1,2,3"
(integer) 1
127.0.0.1:6379> KEYS l1
1) "l1"
127.0.0.1:6379> type l1
list
127.0.0.1:6379> type key2
string
2.1.6:INCR:若是key不存在就建立並設置value默認爲1並遞增,DECR爲遞減
127.0.0.1:6379> INCR num
(integer) 1
127.0.0.1:6379> INCR num
(integer) 2
127.0.0.1:6379> INCR num
(integer) 3
127.0.0.1:6379> INCR num
(integer) 4
127.0.0.1:6379> INCR num
(integer) 5
127.0.0.1:6379> DECR num
(integer) 4
127.0.0.1:6379> DECR num
(integer) 3
127.0.0.1:6379> DECR num
(integer) 2
127.0.0.1:6379> DECR num
(integer) 1
127.0.0.1:6379> DECR num
(integer) 0
127.0.0.1:6379> DECR num
(integer) -1
2.1.7:INCRBY遞增和DECRBY遞減:
127.0.0.1:6379> get num
"4"
127.0.0.1:6379> DECRBY num 10
(integer) -6
127.0.0.1:6379> DECRBY num 10
(integer) -16
127.0.0.1:6379> get num
"-16"
127.0.0.1:6379> INCRBY num 5
(integer) -11
127.0.0.1:6379> INCRBY num 5
(integer) -6
2.1.8:設置浮點數INCRBYFLOAT :
127.0.0.1:6379> INCRBYFLOAT num1 3.1415926
"3.1415926"
127.0.0.1:6379> INCRBYFLOAT num2 -0.45
"-0.45"
127.0.0.1:6379> get num1
"3.1415926"
127.0.0.1:6379> get num2
"-0.45"
2.1.9:MSET批量建立和MGET批量獲取key:
127.0.0.1:6379> MSET k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> MGET k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
2.1.10:獲取key字符串的長度:
127.0.0.1:6379> set a 12345
OK
127.0.0.1:6379> STRLEN a
(integer) 5
2.2:HASH哈希表(散列數據類型):
2.2.1:HSET:命令用於爲哈希表中的字段賦值,若是哈希表不存在,一個新的哈希表被建立並進行 HSET 操做,若是字段已經存在於哈希表中,舊值將被覆蓋
2.2.2:HGET:獲取key:
127.0.0.1:6379> HSET phone name iphone
(integer) 1
127.0.0.1:6379> HSET phone color white
(integer) 1
127.0.0.1:6379> HSET phone price 5000
(integer) 1
127.0.0.1:6379> HGET phone name
"iphone"
127.0.0.1:6379> HGET phone color
"white"
127.0.0.1:6379> HGET phone price
"5000"
2.2.3:HGETALL:獲取key的全部值
127.0.0.1:6379> HGETALL phone
1) "name"
2) "iphone"
3) "color"
4) "white"
5) "price"
6) "5000"
2.2.4:HMSET、HMGET、HMGETALL:批量建立、批量獲取並獲取全部的key:
127.0.0.1:6379> HMSET phone name huawei_honor8 color black storage 64G # 批量設置key
OK
127.0.0.1:6379> HMGET phone name storage # 批量獲取key
1) "huawei_honor8"
2) "64G"
127.0.0.1:6379> HGETALL phone # 獲取全部的key
1) "name"
2) "huawei_honor8"
3) "color"
4) "black"
5) "price"
6) "5000"
7) "storage"
8) "64G"
2.2.5:刪除指定的key:
127.0.0.1:6379> HGETALL phone #查看當前全部的key和值
1) "name"
2) "huawei_honor8"
3) "color"
4) "black"
5) "price"
6) "5000"
7) "storage"
8) "64G"
127.0.0.1:6379> HDEL phone storage # 刪除指定的key
(integer) 1
127.0.0.1:6379> HGETALL phone # 再次查看當前全部的key
1) "name"
2) "huawei_honor8"
3) "color"
4) "black"
5) "price"
6) "5000"
2.3: 列表:不一樣的數據類型的命令是不通用的,如list與string的命令是不能通用的,除了set命令以外
2.3.1:從列表頭部添加數據LPUSH和從列表尾部添加數據RPUSH,列表不存在會建立:
127.0.0.1:6379> LPUSH list1 1
(integer) 1
127.0.0.1:6379> LPUSH list1 2
(integer) 2
127.0.0.1:6379> LPUSH list1 a
(integer) 3
127.0.0.1:6379> RPUSH list1 b
(integer) 4
2.3.2:獲取列表的長度:
127.0.0.1:6379> LLEN list1
(integer) 4
2.3.3:LPOP 與 RPOP:從頭部和尾部彈出列表中的值:
127.0.0.1:6379> LPUSH list2 1
(integer) 1
127.0.0.1:6379> LPUSH list2 2
(integer) 2
127.0.0.1:6379> LPUSH list2 3
(integer) 3
127.0.0.1:6379> LPUSH list2 4 v
(integer) 5
127.0.0.1:6379> LPOP list2
"v"
127.0.0.1:6379> RPOP list1
"1"
2.3.4:LINDEX,返回列表中下表爲INDEX的元素值:
127.0.0.1:6379> LINDEX list2 1
"3"
127.0.0.1:6379> LINDEX list2 2
"2"
2.3.5:LRANGE,返回指定下表位置的元素,0爲第一個,1爲第二個,-1爲最後一個。。。,即獲取到列表中的全部數據了:
127.0.0.1:6379> LRANGE list2 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
2.4:(set)集合數據類型的操做:集合默認是無序的,列表是有序的,有序是隻按照添加的循序保持位置,而不是數值的從小到大的排序:
2.4.1:SADD:建立並給集合賦值,會自動將值去重:
127.0.0.1:6379> SADD set1 s1 s2 s3 s4
(integer) 4
127.0.0.1:6379> SADD set2 s1 s2 s3 s4 s5
(integer) 5
127.0.0.1:6379> SADD set3 s1 s2 s3 s4 s5 s6
(integer) 6
127.0.0.1:6379> SADD set4 s1 s2 s3 s4 s5 s6 s3 # 若是有重複的值就會只保留一個
(integer) 6
2.4.2:獲取一個集合中的全部的值:
127.0.0.1:6379> SMEMBERS set2
1) "s4"
2) "s3"
3) "s2"
4) "s1"
5) "s5"
127.0.0.1:6379> SMEMBERS set1
1) "s4"
2) "s3"
3) "s2"
4) "s1"
2.4.3:SISMEMBER:判斷一個值是否是在集合當中,在返回1,不然返回0
127.0.0.1:6379> SISMEMBER set1 s0
(integer) 0 # 不在集合中
127.0.0.1:6379> SISMEMBER set1 s3
(integer) 1 # 在集合中
2.4.4:SDIFF:求兩個set的差集,以屬於A而不屬於B的元素爲元素的集合成爲A與B的差(集),即以第一個set的爲基準對比第二個,且第一個set有的而第二個set沒有的部分:
192.168.10.15:6379> SMEMBERS set1
1) "s4"
2) "s1"
3) "s3"
4) "s2"
192.168.10.15:6379> SMEMBERS set2
1) "s4"
2) "s3"
3) "s5"
4) "s1"
5) "s2"
127.0.0.1:6379> SDIFF set1 set2 # 若是第一個在前面就對比不到
(empty list or set)
127.0.0.1:6379> SDIFF set2 set1 # 第二個在前面就能夠對出第二個的s5在第一個裏面沒有
1) "s5"
2.4.5:SINTER:返回集合的交集,屬於A且屬於B的元素爲元素的集合成爲A與B的交(集) ,即集合同時包含的數值:
127.0.0.1:6379> SMEMBERS set1
1) "s4"
2) "s3"
3) "s2"
4) "s1"
127.0.0.1:6379> SMEMBERS set4
1) "s2"
2) "s1"
3) "s4"
4) "s3"
5) "s5"
6) "s6"
127.0.0.1:6379> SINTER set1 set4 # 交集只保留雙方都有的值
1) "s4"
2) "s3"
3) "s2"
4) "s1"
2.4.6:SUNION,返回集合的並集,屬於A或屬於B的元素爲元素的集合成爲A與B的並(集) ,每一個數據的保留一份,即自動去掉重複的:
127.0.0.1:6379> SUNION set1 set4
1) "s4"
2) "s3"
3) "s1" #在多個集合屢次出現的值只統計一次
4) "s5"
5) "s2"
6) "s6"
2.5:有序隊列:經過給key設置分數保持值得index位置固定,集合是無序的:
2.5.1:ZADD 根據分數建立有序隊列,ZSCORE獲取到值的分數:
127.0.0.1:6379> ZADD number 1 a 2 b 3 c 4 d # 按照分數設置有序隊列
(integer) 4
127.0.0.1:6379> ZSCORE number c # 獲取值得分數
"3"
2.5.2: 根據值的分數排序獲取值:
127.0.0.1:6379> ZRANGE number 0 -1 #0和-1爲取值的下標範圍,超出值隊列的總長度並不報錯
1) "a"
2) "b"
3) "c"
4) "d"
2.6:info 命令,查看redis服務器的運行狀態:
127.0.0.1:6379> info
# Server
redis_version:3.2.9
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:3a11faa19c76ca1d
redis_mode:standalone
os:Linux 3.10.0-514.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.5
process_id:9164
run_id:4980c0e52073860e058750304f6ccddc28b19dd6
tcp_port:6379
uptime_in_seconds:12384
uptime_in_days:0
hz:10
lru_clock:6520647
executable:/usr/local/redis/src/redis-server
config_file:/etc/redis/6379.conf
# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
# Memory
used_memory:824712
used_memory_human:805.38K
used_memory_rss:8245248
used_memory_rss_human:7.86M
used_memory_peak:824712
used_memory_peak_human:805.38K
total_system_memory:3958329344
total_system_memory_human:3.69G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:10.00
mem_allocator:jemalloc-4.0.3
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1499692781
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
# Stats
total_connections_received:2
total_commands_processed:118
instantaneous_ops_per_sec:0
total_net_input_bytes:4240
total_net_output_bytes:12054709
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:50
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:111284
migrate_cached_sockets:0
# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
# CPU
used_cpu_sys:14.96
used_cpu_user:3.88
used_cpu_sys_children:0.57
used_cpu_user_children:0.00
# Cluster
cluster_enabled:0
# Keyspace
db0:keys=18,expires=0,avg_ttl=0
2.7:config命令,用於查看當前配置、在不重啓服務器的狀況下修改配置:
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"
127.0.0.1:6379> CONFIG SET maxmemory 512000000
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "512000000"
2.8:select切換數據庫,dbsize查看當前庫的key數量:
127.0.0.1:6379> KEYS *
1) "key10"
2) "set1"
3) "phone"
4) "set4"
5) "list1"
6) "k2"
7) "num"
8) "number"
9) "l1"
10) "set2"
11) "key2"
12) "num2"
13) "num1"
14) "a"
15) "list2"
16) "k3"
17) "k1"
18) "set3"
127.0.0.1:6379> SELECT 0 #select用於在各庫在之間進行切換
OK
127.0.0.1:6379> DBSIZE
(integer) 18
127.0.0.1:6379> set name jack
OK
127.0.0.1:6379> DBSIZE
(integer) 19 # 當前有19個key
127.0.0.1:6379> keys *
1) "key10"
2) "set1"
3) "phone"
4) "set4"
5) "list1"
6) "k2"
7) "num"
8) "number"
9) "l1"
10) "set2"
11) "key2"
12) "num2"
13) "num1"
14) "a"
15) "list2"
16) "k3"
17) "k1"
18) "set3"
19) "name"
一:redis 雖然是一個內存級別的緩存程序,即redis 是使用內存進行數據的緩存的,可是其能夠將內存的數據按照必定的策略保存到硬盤上,從而實現數據持久保存的目的,redis支持兩種不一樣方式的數據持久化保存機制,分別是RDB和AOF,具體實現以下:
1.1:redis數據持久化歸納:
redis 支持兩種數據持久保存方式,分別是RDB和APF
RDB能夠設置在多長時間內有多少個key發生變化就執行RDB快照。
AOF持久化是服務器記錄和保存redis執行的全部命令,並在服務重啓的時候從新執行所有的命令來還原數據,AOF文件的命令所有使用redis 協議格式保存,執行的命令會被以追加的命令保存到文件的末尾,另外redis還能夠在後臺對AOF文件進行rewrite即重寫,這樣可使文件的大小不會超過保存數據所須要的實際大小。
redis能夠同時使用AOF和RDB進行數據持久化,可是當redis重啓的時候會優先使用AOF文件來還原數據,這是由於AOF保存的文件一般要比RDB文件保存的數據更加完整。
1.2:RDB的實現與優缺點:
1.2.1:實現原理:
RDB是redis從主進程先fork出一個子進程,使用寫時複製機制,子進程將內存的數據保存爲一個臨時文件,好比dump.rdb.temp,當數據保存完成以後再將上一次保存的RDB文件替換掉,而後關閉子進程,這樣能夠保存每一次作RDB快照的時候保存的數據都是完整的,由於直接替換RDB文件的時候可能會出現忽然斷電等問題而致使RDB文件尚未保存完整就忽然關機中止保存而致使數據丟失的狀況,能夠手動將每次生成的RDB文件進程備份,這樣能夠最大化保存歷史數據。
1.2.2:RDB的優勢:
保存了某個時間點的數據,能夠經過腳本執行bgsave命令自定義時間點北備份,能夠保留多個備份,當出現問題能夠恢復到不一樣時間點的版本。
能夠最大化io的性能,由於父進程在保存RDB 文件的時候惟一要作的是fork出一個子進程,而後的操做都會有這個子進程操做,父進程無需任何的IO操做
RDB在大量數據好比幾個G的數據,恢復的速度比AOF的快
1.2.3:RDB的缺點:
不能時時的保存數據,會丟失自上一次執行RDB備份到當前的內存數據
數據量很是大的時候,從父進程fork的時候須要一點時間,多是毫秒或者秒
1.3:AOF的實現和優缺點:
1.3.1:AOF的實現機制:
AOF和RDB同樣使用了寫時複製機制,AOF默認爲每秒鐘fsync一次,即將執行的命令保存到AOF文件當中,這樣即便redis服務器發生故障的話頂多也就丟失1秒鐘以內的數據,也能夠設置不一樣的fsync策略,或者設置每次執行命令的時候執行fsync,fsync會在後臺執行線程,因此主線程能夠繼續處理用戶的正常請求而不受到寫入AOF文件的IO影響
AOF文件是一個進行追加操做的日誌文件(append only log),即操做的命令都會被追加到文件的末尾,若是由於磁盤滿、忽然停機等問題致使寫入了不完整的命令,能夠經過redis自帶的命令redis-check-aof命令輕易的修復AOF文件,以下:
# redis-check-aof /data/redis/appendonly.aof
AOF analyzed: size=7683, ok_up_to=7683, diff=0
AOF is valid
redis能夠在AOF文件變得過大的時候自帶在後臺對文件進行重寫,重寫後的新APF文件保存了恢復的時候須要的最新數據和最小的命令集合,這個操做是絕對安全的,由於redis 在建立新AOF文件的過程當中會繼續將命令追加到以前的AOF文件,這樣即便服務器宕機也不會影響到當前redis 使用的AOF文件,而一旦新的AOF文件建立完成,redis就會從舊AOF文件切換到新的AOF文件,並將命令追加到新的AOF文件
AOF文件按照命令的執行順序保存了對redis 的因此操做,使用的是redis協議,所以能夠對AOF文件進行讀取和分析,也能夠導出,假如不當心執行了一個FLUSHALL命令,可是隻要AOF文件尚未被重寫能夠當即中止服務器,而後刪除AOF文件末尾的FLUSHALL命令並重啓redis,即將能夠將數恢復到FLUSHALL命令以前的數據狀態。
1.3.2:AOF的缺點:
AOF的文件大小要大於RDB格式的文件
曾經有bug致使AOF從新載入AOF文件的時候沒法將數據恢復到保存的時候遠洋,好比執行阻塞命令BRPOPLPUSH就曾引發bug
根據所使用的fsync策略(fsync是同步內存中redis全部已經修改的文件到存儲設備),默認是appendfsync everysec即每秒執行一次fsync
1.4:redis 持久化的配置參數:
1.4.1:編輯配置那文件:
# vim /etc/redis/6379.conf
save 900 1 #900秒之內有1個key發生變化就快照
save 300 10 #300秒之內有10個key發生變化就快照
save 60 10000 #60秒內有10000個key變化就快照
rdbcompression yes #持久化到RDB文件時,是否壓縮,"yes"爲壓縮,"no"則反之
rdbchecksum yes #讀取和寫入的時候是否支持CRC64校驗,默認是開啓的
dbfilename dump.rdb #文件名
dir /data/redis #保存路徑
slave-read-only yes #從redis 只讀
maxmemory 512M #限制redis 最大使用內存
appendonly yes #是否開啓AOF
appendfilename "appendonly.aof" #保存路徑,和RDB在一塊兒
appendfsync everysec #每秒執行一次fsync,即將內存更改的數據寫入磁盤
[root@node1 src]# egrep '^[a-z]' /etc/redis/6379.conf
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
maxmemory 512M
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
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-rewrite-incremental-fsync yes
SAVE 與 BGSAVE:
SAVE:阻塞保存
BGSAVE:在後臺保存,不阻塞
KILL -9 會丟失自上次保存之後到如今的數據
1.4.2:重啓redis服務:
[root@node1 ~]# /etc/init.d/redis stop
Stopping ...
Redis stopped
[root@node1 ~]# /etc/init.d/redis start
Starting Redis server...
1.4.2:經過python鏈接到redis 寫入幾個key,驗證持久保存:
#!/bin/env python
import redis
pool = redis.ConnectionPool(host='192.168.3.199',port=6379)
r = redis.Redis(connection_pool = pool)
for i in range(1000):
r.set('k%d' % i,'v%d' % i)
data = r.get('k%d' % i)
print(data)
1.4.3:redis服務器驗證數據:
[root@node1 ~]# redis-cli -h 192.168.3.199
192.168.3.199:6379> keys *
1) "k941"
2) "k863"
3) "k699"
4) "k646"
5) "k833"
6) "k945"
7) "k286"
8) "k310"
9) "k546"
10) "k313"
11) "k135"
12) "k458"
......
1.4.4:驗證AOF和RDB持久化保存的文件,保存的文件路徑是在redis.conf文件定義的:
[root@node1 ~]# ll /data/redis/
total 48
-rw-r--r-- 1 root root 32803 Jul 11 01:51 appendonly.aof
-rw-r--r-- 1 root root 10862 Jul 11 02:03 dump.rdb
AOF是時時寫入到文件的,rdb須要等達到指定的策略後纔會備份
二:redis主從:
redis支持主從複製的功能,可讓從服務器從主服務器備份數據,並且從服務器還可與有從服務器,即另一臺redis服務器能夠從一臺從服務器進行數據同步,redis 的主從同步是非阻塞的,其收到從服務器的sync(2.8版本以前是PSYNC)命令會fork一個子進程在後臺執行bgsave命令,並將新寫入的數據寫入到一個緩衝區裏面,bgsave執行完成以後並生成的將RDB文件發送給客戶端,客戶端將收到後的RDB文件載入本身的內存,而後主redis將緩衝區的內容在所有發送給從redis,以後的同步從服務器會發送一個offset的位置(等同於MySQL的binlog的位置)給主服務器,主服務器檢查後位置沒有錯誤將此位置以後的數據包括寫在緩衝區的積壓數據發送給redis從服務器,從服務器將主服務器發送的擠壓數據寫入內存,這樣一次完整的數據同步,再以後再同步的時候從服務器只要發送當前的offset位 置給主服務器,而後主服務器根據響應的位置將以後的數據發送給從服務器保存到其內存便可。
另外redis的key 大小不建議超過2MB,由於2MB如下的key的性能是最佳的,key比較大的時候可使用列表、key分級等方式將key進行拆分保存到不一樣的hash裏面,另外第一次主從同步若是有數十G的數據,若是在主redis服務器寫入頻繁的時候同步,可能會出現RDB文件尚未向從服務器傳輸完成但主服務器的緩衝區已經寫滿致使從服務器發送sync的時候出現數據不一致致使再次全量同步的狀況發生,所以建議在晚上住redis寫入較少的時候在作同步,避免此類的狀況發生
2.1:主從同步的一些概念:
redis使用異複製數據,從redis 2.8開始,從服務器會以每秒一次的頻率向主服務器報告複製流(replication stream)的處理進度
一個主服務器能夠同時有多個從服務器
從服務器還能夠有本身的從服務器
複製功能不會阻塞從服務器,只要在redis.conf中作了設置,及時從服務器正在和主服務器進行初次同步,從服務器也可使用以前的數據類處理客戶端請求,不過從服務器刪除就版本數據並載入新數據的時間段內,鏈接請求會被阻塞,能夠設置從服務器讓他在和主服務器之間斷開鏈接時,向客戶端發送一個錯誤信息
複製功能用於實現數據冗餘,能夠在從服務器執行復雜的命令在從服務器執行,以減輕主服務器的壓力
能夠在從服務器執行數據持久化而關閉主服務器的持久化功能,而後在從服務器執行數據持久化便可
2.2:是否須要在主服務器打開持久化功能:
有一個場景,有三個服務器,主服務器,從服務器A和從服務器B,從服務器A從主服務器同步數據,而從服務器B從服務器A同步數據,假如主服務器沒有開啓數據持久化,那麼當主服務器出現問題重啓redis服務後因爲沒有作數據持久會丟失因此數據爲空,而從服務器A同步主服務器後也沒有數據,從服務器B同步從服務器A的數據以後也會沒有數據,所以主服務器仍是推薦開啓數據持久化以免產生一系列的問題。
另外
2.3:配置redis主從同步,在另一臺服務器安裝同版本的redis,並執行如下操做:
2.3.1:在從服務器進行操做:
[root@node1 src]# redis-cli -h 192.168.3.13
192.168.3.13:6379> SLAVEOF 192.168.3.199 6379 # 配置3.199爲主服務器
OK
2.3.2:查看redis從服務器的狀態:
192.168.3.13:6379> info
#其餘信息省略
# Replication
role:slave # 狀態爲從服務器
master_host:192.168.3.199 # 主服務器的IP和端口信息
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:15
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
192.168.3.13:6379> set key001 value001 #從服務器默認爲read only即只讀模式,沒法寫入數據
(error) READONLY You can't write against a read only slave
2.3.3:在redis主服務器執行INFO查看服務器信息:
# Replication
#其餘信息省略
role:master #狀態爲主服務器
connected_slaves:1 #已經有一個從服務器鏈接
slave0:ip=192.168.3.13,port=6379,state=online,offset=477,lag=1
master_repl_offset:477
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:476
2.3.4:redis主從之間的心跳檢測,能夠經過MONITOR命令查看:
192.168.3.13:6379> MONITOR
OK
1499680760.936254 [0 192.168.3.199:6379] "PING"
1499680770.341823 [0 192.168.3.199:6379] "PING"
1499680779.735807 [0 192.168.3.199:6379] "PING"
1499680789.117626 [0 192.168.3.199:6379] "PING"
2.4:將從服務器設置爲主服務器:
192.168.3.13:6379> SLAVEOF no one #將從服務器切換爲主服務器
OK
192.168.3.13:6379> info
# 其餘信息省略
# Replication
role:master #即切換爲主服務器
connected_slaves:0
master_repl_offset:981
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
####################################################################################
經過codis3.2實現redis3.2.8集羣
一:Codis 是一個分佈式 Redis 解決方案, 對於上層的應用來講, 鏈接到 Codis Proxy 和鏈接原生的 Redis Server 沒有明顯的區別 (不支持的命令列表https://github.com/CodisLabs/codis/blob/release3.1/doc/unsupported_cmds.md), 上層應用能夠像使用單機的 Redis 同樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工做, 全部後邊的一切事情, 對於前面的客戶端來講是透明的, 能夠簡單的認爲後邊鏈接的是一個內存無限大的 Redis 服務:
Codis是豌豆莢的開源方案,目前在redis集羣實現方式對比,codis集羣比較穩定的方案,而且客戶端不須要作任何修改,相對redis cluster兼容性更強,可節約大量開發成本並減小大量後期維護成本,豌豆莢gitlab地址https://github.com/pingcap,豌豆莢codis項目官方github地址https://github.com/CodisLabs/codis,codis 主要由如下特色:
能夠無縫遷移到codis,自帶遷移工具,而且案例較多
能夠動態擴容和縮容
多業務徹底透明,業務不知道運行的是codis
支持多核心CPU,twemproxy只能單核
codis是中心基於proxy的設計,是客戶端像鏈接單機同樣操做proxy
有部分命令不能支持,好比keys *等
支持group劃分,組內能夠設置一個主多個從,經過sentinel 監控redis主從,當主down了自動將從切換爲主
設置的進程要最大等於CPU的核心,不能超過CPU的核心數
其依賴於zookeeper,裏面保存的是key保存的redis主機位置,所以zookeeper要作高可用
監控可使用接口和dashboard

1.1:安裝go環境,codis基於go開發:
1.1.1:架構環境:
codis-proxy至關於redis,即鏈接codis-proxy和鏈接redis是沒有任何區別的,codis-proxy無狀態,不負責記錄是否在哪保存,數據在zookeeper記錄,即codis proxy向zookeeper查詢key的記錄位置,proxy 將請求轉發到一個組進行處理,一個組裏面有一個master和一個或者多個slave組成,默認有1024個槽位,redis cluster 默認有16384個槽位,其把不一樣的槽位的內容放在不通的group。
部署環境:3臺服務器
1.1.2:codis是基於go語言編寫的,所以要安裝go語言環境:
# cd /usr/local/src
[root@node1 src]# yum install -y gcc glibc gcc-c++ make git
[root@node1 src]# wget https://storage.googleapis.com/golang/go1.7.3.linux-amd64.tar.gz
[root@node1 src]# tar zxf go1.7.3.linux-amd64.tar.gz
[root@node1 src]# mv go /usr/local/
[root@node1 src]# mkdir /usr/local/go/work
[root@node1 src]# vim /root/.bash_profile
export PATH=$PATH:/usr/local/go/bin
export GOROOT=/usr/local/go
export GOPATH=/usr/local/go/work
path=$PATH:$HOME/bin:$GOROOT/bin:$GOPATH/bin
[root@node1 src]# source /root/.bash_profile
[root@node1 src]# echo $GOPATH
/usr/local/go/work
[root@node1 ~]# go version
go version go1.7.3 linux/amd64
1.1.3:每臺服務器安裝java環境和zookeeper,zookeeper集羣最少須要3臺服務器,推薦5臺,由於zookeeper是基於java開發的:
# tar zxf jdk-8u131-linux-x64.gz
# mv jdk1.8.0_131 /usr/local/
加入腳本
# vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_131
export PATH=$JAVA_HOME/bin:$PATH
[root@node1 jdk1.8.0_131]# source /etc/profile
[root@node1 jdk1.8.0_131]# java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
[root@node1 jdk1.8.0_131]# echo $JAVA_HOME
/usr/local/jdk1.8.0_131
# tar zxf zookeeper-3.4.6.tar.gz
# mv zookeeper-3.4.6 /usr/local/
[root@node1 src]# ln -sv /usr/local/zookeeper-3.4.6/ /usr/local/zookeeper
‘/usr/local/zookeeper’ -> ‘/usr/local/zookeeper-3.4.6/’
[root@node1 src]# cd /opt
[root@node1 opt]# mkdir zk1 zk2 zk3 #準備zookeeper 服務ID,每一個服務器的ID是不一樣的
[root@node1 opt]# echo 1 > zk1/myid
[root@node1 opt]# echo 2 > zk2/myid
[root@node1 opt]# echo 3 > zk3/myid
[root@node1 opt]# cp /usr/local/zookeeper-3.4.6/conf/zoo_sample.cfg /opt/zk1/zk1.cfg
#準備配置文件
#第一個zookeeper的配置文件:
[root@redis1 opt]# grep "^[a-Z]" /opt/zk1/zk1.cfg
tickTime=6000 #服務器和客戶端的心跳維持間隔,間隔多久發送心跳 ,6000微秒等於6毫秒
initLimit=10 #選舉的時候的時間間隔是10次,10次 * 6000微秒 即60秒
syncLimit=10 # Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度
dataDir=/opt/zk1 # 數據保存目錄
clientPort=2181 # 客戶端鏈接的端口
# 集羣端口和ID配置
server.1=192.168.3.198:2887:3887
server.2=192.168.3.198:2888:3888
server.3=192.168.3.198:2889:3889
1.1.4:配置第二個zookeeper服務:
#配置第二個zookeeper服務,每一個服務對應不用的配置文件和數據目錄:
[root@node1 opt]# cp /opt/zk1/zk1.cfg /opt/zk2/zk2.cfg
[root@node1 opt]# grep "^[a-Z]" /opt/zk2/zk2.cfg
tickTime=6000
initLimit=20
syncLimit=10
dataDir=/opt/zk2 # 須要修改配置
clientPort=2182 # 須要修改監聽端口
server.1=192.168.3.198:2887:3887
server.2=192.168.3.198:2888:3888
server.3=192.168.3.198:2889:3889
1.1.5:配置第三個zookeeper服務:
#配置第三個zookeeper服務,每一個服務對應不用的配置文件和數據目錄:
[root@node1 opt]# cp /opt/zk1/zk1.cfg /opt/zk3/zk3.cfg
[root@node1 opt]# vim /opt/zk3/zk3.cfg
[root@node1 opt]# grep "^[a-Z]" /opt/zk3/zk3.cfg
tickTime=6000
initLimit=20
syncLimit=10
dataDir=/opt/zk3 # 須要修改配置
clientPort=2183 # 須要修改監聽端口
server.1=192.168.3.198:2887:3887
server.2=192.168.3.198:2888:3888
server.3=192.168.3.198:2889:3889
1.1.6:參數詳解:
詳細解釋:
tickTime:這個時間是做爲 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每一個 tickTime 時間就會發送一個心跳。
dataDir:顧名思義就是 Zookeeper 保存數據的目錄,默認狀況下,Zookeeper 將寫數據的日誌文件也保存在這個目錄裏。
clientPort:這個端口就是客戶端鏈接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。
initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裏所說的客戶端不是用戶鏈接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集羣中鏈接到 Leader 的 Follower 服務器)初始化鏈接時最長能忍受多少個心跳時間間隔數。當已經超過 5個心跳的時間(也就是 tickTime)長度後 Zookeeper 服務器尚未收到客戶端的返回信息,那麼代表這個客戶端鏈接失敗。總的時間長度就是 10*6000=60 秒
syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 5*6000=30 秒
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集羣中的 Leader 服務器交換信息的端口;D 表示的是萬一集羣中的 Leader 服務器掛了,須要一個端口來從新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通訊的端口。若是是僞集羣的配置方式,因爲 B 都是同樣,因此不一樣的 Zookeeper 實例通訊端口號不能同樣,因此要給它們分配不一樣的端口號。
1.1.7:分別啓動各zookeeper服務:
[root@node1 opt]# /usr/local/zookeeper/bin/zkServer.sh start /opt/zk1/zk1.cfg
[root@node1 opt]# /usr/local/zookeeper/bin/zkServer.sh start /opt/zk2/zk2.cfg
[root@node1 opt]# /usr/local/zookeeper/bin/zkServer.sh start /opt/zk3/zk3.cfg
[root@node1 opt]# ss -tnlp|grep 218*
LISTEN 0 50 :::2181 :::* users:(("java",pid=2893,fd=24))
LISTEN 0 50 :::2182 :::* users:(("java",pid=3055,fd=24))
LISTEN 0 50 :::2183 :::* users:(("java",pid=3099,fd=24))
1.1.9:查看各個zookeeper節點的狀態:
[root@node1 opt]# /usr/local/zookeeper/bin/zkServer.sh status /opt/zk1/zk1.cfg
JMX enabled by default
Using config: /opt/zk1/zk1.cfg
Mode: follower # 備用節點
[root@node1 opt]# /usr/local/zookeeper/bin/zkServer.sh status /opt/zk2/zk2.cfg
JMX enabled by default
Using config: /opt/zk2/zk2.cfg
Mode: leader # 主節點
[root@node1 opt]# /usr/local/zookeeper/bin/zkServer.sh status /opt/zk3/zk3.cfg
JMX enabled by default
Using config: /opt/zk3/zk3.cfg
Mode: follower # 備用節點
1.1.10:測試鏈接到zookeeper節點:
[root@node1 opt]# /usr/local/zookeeper/bin/zkCli.sh -server 192.168.10.101:2181
Connecting to 192.168.10.101:2181
2017-05-12 17:27:41,481 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.6-1569965, built on 02/20/2014 09:09 GMT
2017-05-12 17:27:41,485 [myid:] - INFO [main:Environment@100] - Client environment:host.name=www.chinasoft.com
2017-05-12 17:27:41,485 [myid:] - INFO [main:Environment@100] - Client environment:java.version=1.8.0_131
2017-05-12 17:27:41,488 [myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2017-05-12 17:27:41,488 [myid:] - INFO [main:Environment@100] - Client environment:java.home=/usr/local/jdk1.8.0_131/jre
2017-05-12 17:27:41,488 [myid:] - INFO [main:Environment@100] - Client environment:java.class.path=/usr/local/zookeeper/bin/../build/classes:/usr/local/zookeeper/bin/../build/lib/*.jar:/usr/local/zookeeper/bin/../lib/slf4j-log4j12-1.6.1.jar:/usr/local/zookeeper/bin/../lib/slf4j-api-1.6.1.jar:/usr/local/zookeeper/bin/../lib/netty-3.7.0.Final.jar:/usr/local/zookeeper/bin/../lib/log4j-1.2.16.jar:/usr/local/zookeeper/bin/../lib/jline-0.9.94.jar:/usr/local/zookeeper/bin/../zookeeper-3.4.6.jar:/usr/local/zookeeper/bin/../src/java/lib/*.jar:/usr/local/zookeeper/bin/../conf:..:/usr/local/jdk/lib:/usr/local/jdk/jre/lib:/usr/local/jdk/lib/tools.jar:/usr/local/jdk/lib:/usr/local/jdk/jre/lib:/usr/local/jdk/lib/tools.jar
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:java.compiler=<NA>
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:os.name=Linux
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:os.arch=amd64
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:os.version=3.10.0-514.el7.x86_64
2017-05-12 17:27:41,489 [myid:] - INFO [main:Environment@100] - Client environment:user.name=root
2017-05-12 17:27:41,490 [myid:] - INFO [main:Environment@100] - Client environment:user.home=/root
2017-05-12 17:27:41,490 [myid:] - INFO [main:Environment@100] - Client environment:user.dir=/opt
2017-05-12 17:27:41,491 [myid:] - INFO [main:ZooKeeper@438] - Initiating client connection, connectString=192.168.10.101:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@799f7e29
Welcome to ZooKeeper!
2017-05-12 17:27:41,534 [myid:] - INFO [main-SendThread(192.168.10.101:2181):ClientCnxn$SendThread@975] - Opening socket connection to server 192.168.10.101/192.168.10.101:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
[zk: 192.168.10.101:2181(CONNECTING) 0]
1.1.11:獲取zookeeper命令行幫助:
[zk: 192.168.10.101:2181(CONNECTING) 0] help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port
[zk: 192.168.10.101:2181(CONNECTING) 1]
1.2.12:下載codis 3.2版本:
# mkdir -p $GOPATH/src/github.com/CodisLabs
[root@node1 work]# cd /usr/local/go/work/src/github.com/CodisLabs
[root@node1 CodisLabs]# git clone https://github.com/CodisLabs/codis.git -b release3.2
[root@node1 CodisLabs]# cd $GOPATH/src/github.com/CodisLabs/codis
[root@node1 codis]# pwd
/usr/local/go/work/src/github.com/CodisLabs/codis
1.1.13:執行make進行編譯:
安裝依賴
[root@node1 codis]# yum install autoconf automake libtool -y
[root@node1 codis]# make
make -j4 -C extern/redis-3.2.8/
make[1]: Entering directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8'
cd src && make all
make[2]: Entering directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8/src'
...
lazy_lock : 0
tls : 1
cache-oblivious : 1
===============================================================================
go build -i -o bin/codis-dashboard ./cmd/dashboard
go build -i -tags "cgo_jemalloc" -o bin/codis-proxy ./cmd/proxy
go build -i -o bin/codis-admin ./cmd/admin
go build -i -o bin/codis-fe ./cmd/fe
1.1.14:執行測試:
[root@node1 codis]# make gotest
go test ./cmd/... ./pkg/...
? github.com/CodisLabs/codis/cmd/admin [no test files]
? github.com/CodisLabs/codis/cmd/dashboard [no test files]
? github.com/CodisLabs/codis/cmd/fe [no test files]
? github.com/CodisLabs/codis/cmd/proxy [no test files]
? github.com/CodisLabs/codis/pkg/models [no test files]
? github.com/CodisLabs/codis/pkg/models/etcd [no test files]
? github.com/CodisLabs/codis/pkg/models/fs [no test files]
? github.com/CodisLabs/codis/pkg/models/zk [no test files]
ok github.com/CodisLabs/codis/pkg/proxy 2.525s
ok github.com/CodisLabs/codis/pkg/proxy/redis 0.530s
ok github.com/CodisLabs/codis/pkg/topom 6.560s
ok github.com/CodisLabs/codis/pkg/utils 0.009s
? github.com/CodisLabs/codis/pkg/utils/assert [no test files]
ok github.com/CodisLabs/codis/pkg/utils/bufio2 0.006s
ok github.com/CodisLabs/codis/pkg/utils/bytesize 0.004s
? github.com/CodisLabs/codis/pkg/utils/errors [no test files]
? github.com/CodisLabs/codis/pkg/utils/log [no test files]
ok github.com/CodisLabs/codis/pkg/utils/math2 0.002s
? github.com/CodisLabs/codis/pkg/utils/redis [no test files]
? github.com/CodisLabs/codis/pkg/utils/rpc [no test files]
? github.com/CodisLabs/codis/pkg/utils/sync2 [no test files]
? github.com/CodisLabs/codis/pkg/utils/sync2/atomic2 [no test files]
ok github.com/CodisLabs/codis/pkg/utils/timesize 0.009s
? github.com/CodisLabs/codis/pkg/utils/trace [no test files]
ok github.com/CodisLabs/codis/pkg/utils/unsafe2 0.003s
1.1.15:執行所有指令後,會在 bin 文件夾內生成 codis-proxy、codis-server三個可執行文件。另外, bin/assets 文件夾是 dashboard http 服務須要的前端資源)
[root@node1 codis]# ll bin
total 75680
drwxr-xr-x 4 root root 117 May 12 18:00 assets
-rwxr-xr-x 1 root root 15474864 May 12 18:00 codis-admin
-rwxr-xr-x 1 root root 17093776 May 12 18:00 codis-dashboard
-rwxr-xr-x 1 root root 15365824 May 12 18:00 codis-fe
-rwxr-xr-x 1 root root 19167944 May 12 18:00 codis-proxy # 代理
-rwxr-xr-x 1 root root 5357008 May 12 18:00 codis-server # codis 開發的codis server
-rwxr-xr-x 1 root root 2431984 May 12 18:00 redis-benchmark
-rwxr-xr-x 1 root root 2586040 May 12 18:00 redis-cli
-rw-r--r-- 1 root root 169 May 12 18:00 version
[root@node1 codis]# cat bin/version
version = 2017-05-12 17:22:43 +0800 @07352186632fafd45ca31b0cbde4a541862d46fe @3.2-rc1-32-g0735218
compile = 2017-05-12 18:00:10 +0800 by go version go1.7.3 linux/amd64
編譯codis3.2錯誤記錄:
make[2]: Leaving directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8/src'
make[1]: Leaving directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8'
autoconf
./autogen.sh: line 5: autoconf: command not found
Error 0 in autoconf
make[2]: *** [config] Error 1
make[1]: *** [build] Error 2
make: *** [codis-deps] Error 2
解決:
安裝依賴
[root@node1 codis]# yum install autoconf automake libtool -y
1.2:默認啓動的會讀取config目錄的dashboard.toml文件,編輯以下:
1.2.1:dashboard 的配置文件:
vim /usr/local/go/work/src/github.com/CodisLabs/codis/config/dashboard.toml
主要配置信息以下:
coordinator_name = "zookeeper"
coordinator_addr = "192.168.3.198:2181,192.168.3.198:2182,192.168.3.198:2183"
product_name = "codis-chinasoft"

啓動dashboard:
[root@node1 codis]# nohup ./bin/codis-dashboard --ncpu=1 --config=config/dashboard.toml --log=dashboard.log --log-level=WARN >> /var/log/codis_dashboard.log &
# 默認配置文件獲取方式:./bin/codis-dashboard --default-config | tee dashboard.toml
啓動代理
[root@node1 codis]# nohup ./bin/codis-proxy --ncpu=1 --config=config/proxy.toml --log=proxy.log --log-level=WARN >> /var/log/codis_proxy.log &
主要配置信息以下:
product_name = "codis-chinasoft"
product_auth = "123456"
jodis_name = "zookeeper"
jodis_addr = "192.168.3.198:2181,192.168.3.198:2182,192.168.3.198:2183"
jodis_timeout = "20s"
jodis_compatible = true
./bin/codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080
其中 127.0.0.1:18080 以及 127.0.0.1:11080 分別爲 dashboard 和 proxy 的 admin_addr 地址;
./bin/codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080
./bin/codis-admin --dashboard=192.168.3.198:18080 --create-proxy -x 192.168.3.198:11080

啓動codis-server,即建立redis實例(此處咱們建立4個redis實例,給予codis修改過的redis-3.2.8非原生redis)
[root@node1 codis]# mkdir -pv /var/lib/redis_638{1..4}
mkdir: created directory ¡®/var/lib/redis_6381¡¯
mkdir: created directory ¡®/var/lib/redis_6382¡¯
mkdir: created directory ¡®/var/lib/redis_6383¡¯
mkdir: created directory ¡®/var/lib/redis_6384¡¯
[root@node1 redis-3.2.8]# pwd
/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8
[root@node1 redis-3.2.8]# cp redis.conf /usr/local/go/work/src/github.com/CodisLabs/codis/
[root@node1 redis-3.2.8]# cd /usr/local/go/work/src/github.com/CodisLabs/codis/
修改redis.conf
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump_6381.rdb
dir /var/lib/redis_6381
logfile "/tmp/redis_6381.log"
maxmemory 1g #必定要設置最大內存,不然後面的codis沒法使用
[root@node1 codis]# cp redis.conf redis_6381.conf
[root@node1 codis]# cp redis_6381.conf redis_6382.conf
[root@node1 codis]# cp redis_6381.conf redis_6383.conf
[root@node1 codis]# cp redis_6381.conf redis_6384.conf
[root@node1 codis]# sed -i 's/6381/6382/g' redis_6382.conf
[root@node1 codis]# sed -i 's/6381/6383/g' redis_6383.conf
[root@node1 codis]# sed -i 's/6381/6384/g' redis_6384.conf
1.2.3:經過codis-server指定redis.conf文件啓動redis服務,不能經過redis命令啓動redis服務,經過redis啓動的redis 服務加到codis集羣沒法正常使用:
[root@redis1 codis]# ./bin/codis-server ./redis_6381.conf
[root@redis1 codis]# ./bin/codis-server ./redis_6382.conf
[root@redis1 codis]# ./bin/codis-server ./redis_6383.conf
[root@redis1 codis]# ./bin/codis-server ./redis_6384.conf
1.2.4:驗證經過codis啓動redis 服務成功:
[root@node1 codis]# ss -tnlp|grep 638*
LISTEN 0 128 127.0.0.1:6381 *:* users:(("codis-server",pid=11726,fd=4))
LISTEN 0 128 127.0.0.1:6382 *:* users:(("codis-server",pid=11733,fd=4))
LISTEN 0 128 127.0.0.1:6383 *:* users:(("codis-server",pid=11738,fd=4))
LISTEN 0 128 127.0.0.1:6384 *:* users:(("codis-server",pid=11743,fd=4))
啓動codis-fe,Listen監聽端口不要爲8080,指定8090
nohup ./bin/codis-fe --ncpu=1 --log=fe.log --log-level=WARN --zookeeper=192.168.3.198:2181 --listen=192.168.3.198:8090 &
經過網頁訪問:http://192.168.3.198:8090 能夠看到codis的管理頁面

管理界面的配置實用:
一、經過fe添加group
經過web瀏覽器訪問集羣管理頁面(fe地址:192.168.3.198:8090) 選擇咱們剛搭建的集羣 codis-chinasoft,在 Proxy 欄可看到咱們已經啓動的 Proxy, 可是 Group 欄爲空,由於咱們啓動的 codis-server 並未加入到集羣 添加 NEW GROUP,NEW GROUP 行輸入 1,再點擊 NEW GROUP 便可 添加 Codis Server,

二、添加實例(即添加後端的redis服務器)
Add Server 行輸入咱們剛剛啓動的 codis-server 地址,添加到咱們剛新建的 Group,而後再點擊 Add Server 按鈕便可,以下圖所示

刪除實例
三、對slots進行分組
以下圖所示,輸入所要分組的slots的起和止的範圍,而後輸入組ID,點擊後面按鈕便可。



四、添加管理proxy
在框內輸入proxy所對應的ip地址和端口號點擊Add proxy便可。
五、經過codis-proxy鏈接redis進行測試
[root@node2 ~]# redis-cli -h 192.168.3.198 -p 19000
192.168.3.198:19000> info
# Server
redis_version:3.2.8
redis_git_sha1:07352186
redis_git_dirty:0
redis_build_id:ff8148d434e43f05
redis_mode:standalone
os:Linux 3.10.0-514.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.5
process_id:11726
run_id:5832460909b887822ce81723b33e1e6ecd84e203
tcp_port:6381
uptime_in_seconds:5015
uptime_in_days:0
hz:10
lru_clock:1664676
executable:/usr/local/go/work/src/github.com/CodisLabs/codis/./bin/codis-server
config_file:/usr/local/go/work/src/github.com/CodisLabs/codis/./redis_6381.conf
# Clients
connected_clients:17
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
# Memory
used_memory:4630728
used_memory_human:4.42M
used_memory_rss:14225408
used_memory_rss_human:13.57M
used_memory_peak:4671664
used_memory_peak_human:4.46M
total_system_memory:1912111104
total_system_memory_human:1.78G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:50000000
maxmemory_human:47.68M
maxmemory_policy:noeviction
mem_fragmentation_ratio:3.07
mem_allocator:jemalloc-4.0.3
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1494834582
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
# Stats
total_connections_received:70
total_commands_processed:13563
instantaneous_ops_per_sec:3
total_net_input_bytes:369067
total_net_output_bytes:17298971
instantaneous_input_kbps:0.09
instantaneous_output_kbps:4722.65
rejected_connections:0
sync_full:1
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:948
migrate_cached_sockets:0
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6382,state=online,offset=5468,lag=0
master_repl_offset:5468
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:937
repl_backlog_histlen:4532
# CPU
used_cpu_sys:3.93
used_cpu_user:1.91
used_cpu_sys_children:0.02
used_cpu_user_children:0.00
# Cluster
cluster_enabled:0
# Keyspace
192.168.3.198:19000> set name jack
OK
192.168.3.198:19000> get name
"jack"
192.168.3.198:19000> set address shenzhen
OK
192.168.3.198:19000> get address
"shenzhen"
web界面驗證key是否添加完成,能夠看到已經添加到了group2中:

鏈接zookeeper,能夠看到codis的group,slots,proxy等信息都記錄在zook中
/usr/local/zookeeper/bin/zkCli.sh -server

*************************************
codis3.2安裝報錯dashboard.go:369: [PANIC] call rpc create-proxy to dashboard 127.0.0.1:18080 failed的處理
執行如下命令時報錯:
# pwd
/usr/local/go/work/src/github.com/CodisLabs/codis
# ./bin/codis-admin --dashboard=192.168.3.198:18080 --create-proxy -x 192.168.3.198:11080
[root@node1 codis]# ./bin/codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080
2017/05/12 19:13:51 dashboard.go:369: [PANIC] call rpc create-proxy to dashboard 127.0.0.1:18080 failed
[error]: [Remote Error] proxy@127.0.0.1:11080 fetch model failed, Get http://127.0.0.1:11080/api/proxy/model: dial tcp 127.0.0.1:11080: getsockopt: connection refused
2 /usr/local/go/work/src/github.com/CodisLabs/codis/pkg/topom/topom_proxy.go:24
github.com/CodisLabs/codis/pkg/topom.(*Topom).CreateProxy
1 /usr/local/go/work/src/github.com/CodisLabs/codis/pkg/topom/topom_api.go:244
github.com/CodisLabs/codis/pkg/topom.(*apiServer).CreateProxy
0 /usr/local/go/work/src/github.com/CodisLabs/codis/pkg/topom/topom_api.go:81
github.com/CodisLabs/codis/pkg/topom.(*apiServer).CreateProxy-fm
... ...
[stack]:
2 /usr/local/go/work/src/github.com/CodisLabs/codis/cmd/admin/dashboard.go:369
main.(*cmdDashboard).handleProxyCommand
1 /usr/local/go/work/src/github.com/CodisLabs/codis/cmd/admin/dashboard.go:52
main.(*cmdDashboard).Main
0 /usr/local/go/work/src/github.com/CodisLabs/codis/cmd/admin/main.go:82
main.main
... ...
知乎上的答案:https://www.zhihu.com/question/52519151,感受沒有說清楚問題和解決辦法
實際上通過看前面的啓動dashboard命令:
官方文檔是這樣啓動dashboard的
nohup ./bin/codis-dashboard --ncpu=4 --config=dashboard.toml \
--log=dashboard.log --log-level=WARN &
問題出在--config=dashboard.toml上,沒有顯示指定config文件,就用默認的,而實際上咱們須要啓動本身的配置文件
加上config便可,以下:
[root@node1 codis]# nohup ./bin/codis-dashboard --ncpu=1 --config=config/dashboard.toml --log=dashboard.log --log-level=WARN >> /var/log/codis_dashboard.log &