說明:此爲整理文章。主要是通過Redis提供的命令和配置文件參數等來進行服務器調優,“凡調優皆以實際業務爲基礎,背離者可謂捨本逐末、亂來。”
Redis官方提供的命令:https://redis.io/commands 請參閱。
1、redis-benchmark
redis基準信息,redis服務器性能檢測
例如:
檢測redis服務器性能,本機6379端口的實例,100個併發連接,100000個請求
[root@redis-server ~]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
2、redis-cli monitor 監控
例如,監控本機6379端口的實例的數據操作,redis的連接及讀寫操作
redis-cli -h localhost -p 6379 monitor
演示時,開兩個客戶端,一個正確連接Redis操作,另一個使用monitor監控
3.使用info命令(不包含延遲信息),查詢Redis信息
info命令輸出的數據可分爲10個類別,分別是:
server
clients
memory
persistence
stats
replication
cpu
commandstats
cluster
keyspace
這裏演示三個常用的指標memory,stats和clients。
通過Redis提供的info命令查看吞吐量
src/redis-cli -h 127.0.0.1 info | grep -e "connected_clients" -e "blocked_clients" -e "used_memory_human" -e "used_memory_peak_human" -e "rejected_connections" -e "evicted_keys" -e "instantaneous"
指定info命令的參數來獲取單個分類下的數據。比如輸入info memory命令,會只返回與內存相關的數據。
3.1 memory指標
used_memory #Redis分配器分配的內存總量,單位爲(byte)
used_memory #是Redis服務器使用的內存總量(注意未進行內存碎片這塊的統計)
其他字段代表的含義,都以字節爲單位:
used_memory_rss:從操作系統上顯示已經分配的內存總量(從而可以計算出可用內存空間的大小)。
mem_fragmentation_ratio: 內存碎片率。
used_memory_lua: Lua腳本引擎所使用的內存大小。
mem_allocator: 在編譯時指定的Redis使用的內存分配器,可以是libc、jemalloc、tcmalloc。
used_memory(使用內存) 大於 "分配給Redis的內存"或"當前機器上的最大可用內存"(分配一個新的Redis實例需要分配內存空間,Redis實例運行期間也需要內存空間且是可變的), 那麼
操作系統開始進行內存與swap空間交換,把內存中舊的或不再使用的內容寫入硬盤上(硬盤上的這塊空間叫Swap分區),以便騰出新的物理內存給新頁或活動頁(page)使用。
在Redis配置文件中(一般叫Redis.conf),通過設置“maxmemory”來給Redis分配多大的內存,就像玩Eclipse中玩java VM一樣eclipse.ini中可以設置分配多大的內存空間給java VM
優化 user_memory開銷的途徑:
(i)儘可能的使用Hash數據結構。因爲Redis在儲存小於100個字段的Hash結構上,其存儲效率是非常高的。
(ii)設置key的過期時間(expire,expireat, pexpire, pexpireat命令設置過期時間)
(iii)回收key,若是啓用了Redis快照功能,應該設置“maxmemory”值爲系統可使用內存的45%,因爲快照時需要一倍的內存來複制整個數據集,
也就是說如果當前已使用45%,在快照期間會變成95%(45%+45%+5%),其中5%是預留給其他的開銷。
如果沒開啓快照功能,maxmemory最高能設置爲系統可用內存的95%。
優化 maxmemory-policy #當Redis內存使用達到最大內存時,採取內存回收策略,可在Redis.conf配置中配置。
採用以下幾種策略:
volatile-lru:使用LRU算法從已設置過期時間的數據集合中淘汰數據。
volatile-ttl:從已設置過期時間的數據集合中挑選即將過期的數據淘汰。
volatile-random:從已設置過期時間的數據集合中隨機挑選數據淘汰。
allkeys-lru:使用LRU算法從所有數據集合中淘汰數據。
allkeys-random:從數據集合中任意選擇數據淘汰
no-enviction:禁止淘汰數據。
優化 mem_fragmentation_ratio #內存碎片率,公式爲 used_memory_rss/used_memory
如果內存碎片率超過1.5,那就說明Redis消耗了實際需要物理內存的150%,其中50%是內存碎片率。
若是內存碎片率低於1的話,說明Redis內存分配超出了物理內存,操作系統正在進行內存交換。
額外碎片的產生是由於Redis釋放了內存塊,但內存分配器並沒有返回內存給操作系統,這個內存分配器是在編譯時指定的,可以是libc、jemalloc或者tcmalloc。
(i)重啓Redis服務器:如果內存碎片率超過1.5,重啓Redis服務器可以讓額外產生的內存碎片失效並重新作爲新內存來使用,使操作系統恢復高效的內存管理。
在重啓服務器之前,需要在Redis-cli工具上輸入shutdownsave命令,意思是強制讓Redis數據庫執行保存操作並關閉Redis服務,
這樣做能保證在執行Redis關閉時不丟失任何數據。
3.2 stats指標
total_commands_processed #命令處理總數,通過此指標可以瞭解到命令隊列中命令數量,
分析出等待的命令和慢命令(會對Redis進行阻塞,因爲Redis是單線程的)。
這樣的等待就帶來了延遲問題。
比如使用keys * 命令進行慢查詢可能導致應用程序java.net.SocketTimeoutException: Read timed out
優化total_commands_processed幾種途徑:
(i)單命令多參數的形式取代多命令單參數的形式,比如:
舉例來說,循環使用LSET命令去添加1000個元素到list結構中,是性能比較差的一種方式,
更好的做法是在客戶端創建一個1000元素的列表,用單個命令LPUSH或RPUSH,通過多參數構造形式一次性把1000個元素髮送的Redis服務上。
這跟大家通常操作關係型數據庫是一樣的原理,你循環插入數據到數據庫中,和批處理一次性按一定量插入哪個快些?當然批量快些
單參數命令 描述 多參數命令 描述
SET 設置一個key值 MSET 設置多個key多個值
GET 獲取一個key值 MGET 獲取多個key的值
LSET 左端添加一個元素至list中 LPUSH,RPUSH 設置或追加多個元素至list中
LINDEX 從list中獲取某個元素 LRANGE 從list中獲取某個區間的數據
HSET 設置hash中的一個String值 HMSET 設置多個hash字段值
HGET 獲取某個hash字段的值 HMGET 獲取多個hash字段值
(ii)合理使用管道命令:可以減少多命令帶來的網絡開銷,把幾個命令合併一起執行,從而減少因網絡開銷引起的延遲問題。
比如:10個命令單獨發送到服務端會引起10次網絡延遲開銷
(iii)避免大集合的慢命令,如ZINTERSTORE 統計多個有序集合的交集,並存儲結果。(這個要需要權衡,是用Redis,關係型DB,Java那個花費的時間少來決定)
3.3 clients指標,客戶端的連接
Redis默認允許客戶端連接的最大數量是10000。若是看到連接數超過5000以上,那可能會影響Redis的性能。
查看Redis客戶端連接數: redis-cli -a ***** info | grep -w "connected_clients" |awk -F':' '{print $2}'
檢查服務端tcp連接數:netstat -nat|grep -i "6379"|wc -l (部署在Linux上的Redis)
列出所有連接: client list
查看服務端支持的最大連接:CONFIG GET maxclients
查看當前服務端建立的連接:connected_clients
優化方案:
(i)限制客戶端連接數:自Redis2.6以後,允許使用者在配置文件(Redis.conf)maxclients屬性上修改客戶端的最大連接數,
也可以通過在Redis-cli工具上輸入config set maxclients 去設置最大連接數,根據連接數負載的情況,
這個數字應該設置爲預期連接數峯值的110%到150之間,若是連接數超出這個數字後,Redis會拒絕並立刻關閉新來的連接。
(ii)不使用timeout和tcp-keepalive默認值, 推薦tcp-keepalive爲60s
這兩個屬性如果使用默認值0,可能導致連接池中空閒連接被佔用時間過長,導致後面的請求獲取不到連接而拋出異常。
4.wireshark抓包工具,分析redis連接時的tcp數據包。
5.Redis延遲分析,找出慢命令
Redis-cli --latency -h 127.0.0.1 -p 6379
5.1 使用slowlog查出引發延遲的慢命令:Redis中的slowlog命令可以讓我們快速定位到那些超出指定執行時間的慢命令,
默認情況下命令若是執行時間超過10ms就會被記錄到日誌。slowlog只會記錄其命令執行的時間,不包含io往返操作,
也不記錄單由網絡延遲引起的響應慢。
慢命令(慢查詢,慢日誌)在Redis配置文件中配置
slowlog-log-slower-than 10000 #記錄響應時間大於10000微秒(10毫秒)的慢查詢
slowlog-max-len 128 # 最多記錄128條
SLOWLOG RESET #可以清空slow log
6。分片(Sharding)
6.1 分片是把數據分割成合適大小,分別存放在不同的Redis實例上,每一個實例都包含整個數據集的一部分。
通過分片可以把很多服務器聯合起來存儲數據,相當於增加總的物理內存,使其在沒有內存交換和回收key的策略下也能存儲更多的key。
6.2 Redis 的分片承擔着兩個主要目標:
允許使用多節點的內存總和來支持更大的數據庫。沒有分片只能侷限於單機能支持的內存容量。
允許伸縮計算能力到多核或多服務器,伸縮網絡帶寬到多服務器或多網絡適配器。
6.3 分片提高了內存可用量,減少了內存回收率,從而提高性能。Redis實現分片的幾種常用方式,如下: