key的一般都是採用字串,而字串的底層資料結構為SDS,SDS 結構中會包含字串長度、分配空間大小等元資料訊息,當key字串的長度增加時,SDS中的元資料也會佔用更多記憶體空間,為了減少key的佔用空間,我們可用根據業務名來使用對應的英文縮寫來表示。例如user用u表示,message 用m來表示。
我們既要注意key的長度,同時也需要關注value的大小,Redis是使用單線程讀寫數據,bigkey 的讀寫操作會阻塞線程,降低Redis的處理效率。
我們可以透過--bigkey的命令來查看Redis中所佔用的bigkey的信息,具體的命令如下:
redis-cli -h 127.0.0.1 -p 6379 -a 'xxx' --bigkeys
從上述圖所示,我們可以查看到Redis中的key佔用了32098個bytes,需要進行相關優化的。
建議:
如果key為string類型,建議value的存放值的大小為10KB左右。
如果key為List/Hash/Set/ZSet類型,建議存放元素的數量控制在1萬以下的。
Redis針對所儲存的資料類型進行了最佳化,同時也對記憶體進行了對應的最佳化。關乎數據結果的相關知識,可以參考先前的文章。
例如:String和set在儲存int資料時,會採用整數編碼儲存。 Hash、ZSet在元素數量比較少時,會採用壓縮列表(ziplist)存儲,在存儲比較多的數據時,才會轉換為哈希表和跳表。
Redis中的字串都是使用二進位安全的位元組陣列來保存的,所以我們可以把業務的序列化成二進位寫入Redis ,但是採用不同的序列化,所佔用的空間大少不一樣。 Protostuff的序列化比Java內建的序列化更有效率,且佔用的空間更少。為了減少空間佔用,我們可以對JSON和XML資料格式進行壓縮存儲,可選的壓縮演算法包括Gzip和Snappy。
我們根據業務的資料量提前預估記憶體大小,從而避免Redis的記憶體持續膨脹,導致佔用過多資源。
關於如何設定淘汰策略,需要集合實際的業務特性來選擇:
#volatile-lru / allkeys-lru: 優先保留最近訪問過的資料
volatile-lfu / allkeys-lfu:優先保留存取次數最頻繁的資料
#volatile-ttl :優先淘汰即將過期的資料
volatile-random / allkeys-random:隨機淘汰資料
Redis單一實例的記憶體大小建議設定在2~6GB之間。由於RDB快照和主從叢集資料同步都能快速完成,因此不會阻塞正常請求的處理。
頻繁的新增修改會導致記憶體碎片的增多,因此需要及時清理記憶體碎片。
Redis提供了Info memory指令可以查看記憶體使用訊息,如下:
##說明:
对于集合类型的来说,在未清楚集合数据大小的情况下,慎用查询集合中的全量数据,例如Hash的HetALL、Set的SMEMBERS命令、LRANGE key 0 -1 或者ZRANGE key 0 -1等命令,因为这些命令会对Hash或者Set类型的底层数据进行全量扫描,当集合数据量比较大时,会阻塞Redis的主线程。
优化建议:
当元素数据量较多时,可以用SSCAN、HSCAN 命令分批返回集合中的数据,减少对主线程的阻塞。
Redis执行复杂度过高的命令,会消耗更多的 CPU 资源,导致主线程中的其它请求只能等待。常见的复杂命令如下:SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE 等聚合类命令。
优化建议:
当需要执行排序、交集、并集操作时,可以在客户端完成,避免让Redis进行过多计算,从而影响Redis性能。
Redis通常用于保存热数据。热数据一般都有使用的时效性。因此,在数据存储的过程中,应根据业务对数据的使用时间合理地设置数据的过期时间。否则写入Redis的数据会一直占用内存,如果数据持续增增长,会达到机器的内存上限,造成内存溢出,导致服务崩溃。
当我们需要一次性操作多个key时,可以使用批量命令来处理,批量命令可以减少客户端与服务端的来回网络IO次数。
String或者Hash类型可以使用 MGET/MSET替代 GET/SET,HMGET/HMSET替代HGET/HSET
其它数据类型使用Pipeline命令,一次性打包发送多个命令到服务端执行。
redisTemplate.executePipelined(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { for (int i = 0; i < 5; i++) { connection.set(("test:" + i).getBytes(), "test".getBytes()); } return null; } });
不同的业务线来部署 Redis 实例,这样当其中一个实例发生故障时,不会影响到其它业务。
业务上根据实际情况采用主从、哨兵、集群方案,避免单点故障,影响业务的正常使用。
针对主从环境,我们需要合理设置相关参数,具体内容如下:
合理的设置repl-backlog参数:如果repl-backlog设置过小,当写流量比较大的场景下,主从复制中断可能会引发全量复制数据的风险。
合理设置slave client-output-buffer-limit:当从库复制发生问题时,过小的 buffer会导致从库缓冲区溢出,从而导致复制中断。
以上是Redis優化實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!