Redis 第七集Redis服務器調優(Redis)

說明:此爲整理文章。主要是通過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實現分片的幾種常用方式,如下:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章