Why Redis 4.0?
摘要:?社區(qū)最新GA版本Redis 4.0推出已近一年,阿里云數(shù)據(jù)庫(kù)Redis 4.0版也上線近半年,之前關(guān)于Redis 4.0的系列文章從源碼實(shí)現(xiàn)來(lái)分析這些新功能,本文旨在從用戶角度出發(fā),讓Redis的用戶能夠快速了解并使用Redis 4.0帶來(lái)的福利。
前言
Redis作為時(shí)下最火爆的NoSQL數(shù)據(jù)庫(kù)以性能強(qiáng)悍、數(shù)據(jù)結(jié)構(gòu)豐富著稱(chēng),同時(shí)其成長(zhǎng)的腳步也從未停止,自誕生伊始已經(jīng)歷多次蛻變不斷推出新功能。
社區(qū)最新GA版本Redis 4.0推出已近一年,阿里云數(shù)據(jù)庫(kù)Redis 4.0版也上線近半年,之前關(guān)于Redis 4.0的系列文章從源碼實(shí)現(xiàn)來(lái)分析這些新功能,本文旨在從用戶角度出發(fā),讓Redis的用戶能夠快速了解并使用Redis 4.0帶來(lái)的福利。
Lazyfree
大key刪除的問(wèn)題想必很多用戶都遇到過(guò),Redis除string外還支持list、set、hash和sorted set等復(fù)雜數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)豐富了Redis的用法,但是如果使用不當(dāng)造成單key體積過(guò)大的話就會(huì)引起一些問(wèn)題。
舉個(gè)簡(jiǎn)單的例子,假如某社交網(wǎng)站有一個(gè)大V,有上百萬(wàn)的粉絲,我們可以用set集合類(lèi)型的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)他的粉絲ID,存儲(chǔ)粉絲集合的key叫做funs好了,我們來(lái)看下粉絲數(shù):
127.0.0.1:6379> SCARD funs (integer) 6320505的確是大V,有600多萬(wàn)的粉絲,但是很不幸的有一天這個(gè)大V注銷(xiāo)了,這時(shí)就要?jiǎng)h除他的信息,我們用DEL命令來(lái)刪除這個(gè)key:
127.0.0.1:6379> DEL funs (integer) 1 (3.11s) 127.0.0.1:6379> slowlog get 1) 1) (integer) 42) (integer) 15281699233) (integer) 31048124) 1) "DEL"2) "funs"5) "127.0.0.1:48398"6) ""- 小插曲:Redis 4.0擴(kuò)展了slowlog的返回結(jié)果,展示了產(chǎn)生慢日志的客戶端IP:PORT以便追本溯源。
可以看到刪除這個(gè)動(dòng)作居然耗時(shí)3秒多,也就意味著這3秒內(nèi)Redis無(wú)法執(zhí)行其他命令,這對(duì)于線上業(yè)務(wù)來(lái)講是有傷害的,那么如何避免刪除大key時(shí)的阻塞問(wèn)題呢?Redis 4.0推出了Lazyfree這一功能,使用UNLINK命令來(lái)刪除大key,主線程只負(fù)責(zé)把key從數(shù)據(jù)庫(kù)中"摘除",真正的釋放動(dòng)作放在了BIO后臺(tái)線程去做,我們來(lái)看下效果:
127.0.0.1:6379> UNLINK funs (integer) 1 (3.11s) 127.0.0.1:6379> slowlog get (empty list or set)可以看到UNLINK執(zhí)行很快沒(méi)有產(chǎn)生slowlog。
Lazyfree一共有3個(gè)命令:
以及4個(gè)配置項(xiàng):
對(duì)于源碼實(shí)現(xiàn)有興趣的讀者可以閱讀《Redis 4.0之Lazyfree》。
Lua腳本支持隨機(jī)操作
Redis內(nèi)嵌了Lua環(huán)境來(lái)支持用戶擴(kuò)展功能,但是出于數(shù)據(jù)一致性考慮,要求腳本必須是純函數(shù)的形式,也就是說(shuō)對(duì)于一段Lua腳本給定相同的參數(shù),重復(fù)執(zhí)行其結(jié)果都是相同的。
為什么要有這個(gè)限制呢?原因是Redis不僅僅是單機(jī)版的內(nèi)存數(shù)據(jù)庫(kù),它還支持主從復(fù)制和持久化,執(zhí)行過(guò)的Lua腳本會(huì)復(fù)制給slave以及持久化到磁盤(pán),如果重復(fù)執(zhí)行得到結(jié)果不同,那么就會(huì)出現(xiàn)內(nèi)存、磁盤(pán)、slave之間的數(shù)據(jù)不一致,在failover或者重啟之后造成數(shù)據(jù)錯(cuò)亂影響業(yè)務(wù)。
還是以具體例子來(lái)看,假設(shè)有這么一段Lua腳本,目的很簡(jiǎn)單就是想記錄下當(dāng)前時(shí)間:
local now = redis.call('time')[1]redis.call('set','now',now)return redis.call('get','now')這里使用了Redis的TIME命令來(lái)獲取時(shí)間戳,然后存儲(chǔ)到名為now的key中,但是其執(zhí)行時(shí)會(huì)報(bào)錯(cuò):
$redis-cli --eval escript (error) ERR Error running script (call to f_cfba5ec6a699dad183456f19d1099d8dabfdb80c): @user_script:3: @user_script: 3: Write commands not allowed after non deterministic commands. Call redis.replicate_commands() at the start of your script in order to switch to single commands replication mode.錯(cuò)誤提示也很明顯,如果執(zhí)行過(guò)非確定性命令(也就是TIME,因?yàn)闀r(shí)間是隨機(jī)的),Redis就不允許執(zhí)行寫(xiě)命令,以此來(lái)保證數(shù)據(jù)一致性。那如何才能實(shí)現(xiàn)隨機(jī)寫(xiě)入呢?剛才的錯(cuò)誤提示也給出了答案,使用redis.replicate_commands(),在執(zhí)行redis.replicate_commands()之后,Redis就不再是把整個(gè)Lua腳本同步給slave和持久化,而是把腳本中調(diào)用Redis的寫(xiě)命令直接去做復(fù)制,那么slave和持久化也可以得到確定的結(jié)果。
腳本修改如下:
redis.replicate_commands()local now = redis.call('time')[1]redis.call('set','now',now)return redis.call('get','now')再執(zhí)行就可以實(shí)現(xiàn)隨機(jī)寫(xiě)入了:
$redis-cli --eval escript "1528191578"$redis-cli --eval escript "1528191804"基于LFU的熱點(diǎn)key發(fā)現(xiàn)機(jī)制
LFU是Redis 4.0新增的一類(lèi)內(nèi)存逐出策略,提供了更精確的內(nèi)存淘汰算法,其本質(zhì)是記錄了一段時(shí)間內(nèi)key的訪問(wèn)頻率,同時(shí)也帶來(lái)了額外的福利就是熱點(diǎn)key的發(fā)現(xiàn)。
LFU簡(jiǎn)單來(lái)講就是用0-255來(lái)表示key的訪問(wèn)頻率,值越大說(shuō)明訪問(wèn)頻率越高,并且這里對(duì)頻率的計(jì)數(shù)采用的是基于對(duì)數(shù)的概率增長(zhǎng),LFU為255可以代表100W次的訪問(wèn),關(guān)于LFU的實(shí)現(xiàn)有興趣的讀者可以參考《Redis 4.0之基于LFU的熱點(diǎn)key發(fā)現(xiàn)機(jī)制》。
使用OBJECT FREQ命令即可獲取指定key的訪問(wèn)頻率,不過(guò)需要首先把內(nèi)存逐出策略設(shè)置為allkeys-lfu或者volatile-lfu:
127.0.0.1:6379> config get maxmemory-policy 1) "maxmemory-policy" 2) "noeviction" 127.0.0.1:6379> object freq counter:000000006889 (error) ERR An LFU maxmemory policy is not selected, access frequency not tracked. Please note that when switching between policies at runtime LRU and LFU data will take some time to adjust.127.0.0.1:6379> config set maxmemory-policy allkeys-lfu OK 127.0.0.1:6379> object freq counter:000000006889 (integer) 3使用scan命令遍歷所有key,再通過(guò)OBJECT FREQ獲取訪問(wèn)頻率并排序,即可得到熱點(diǎn)key。為了方便用戶使用,Redis自帶的客戶端redis-cli也提供了熱點(diǎn)key發(fā)現(xiàn)功能,執(zhí)行redis-cli時(shí)加上--hotkeys選項(xiàng)即可,示例如下:
$./redis-cli --hotkeys# Scanning the entire keyspace to find hot keys as well as # average sizes per key type. You can use -i 0.1 to sleep 0.1 sec # per 100 SCAN commands (not usually needed).[00.00%] Hot key 'counter:000000000002' found so far with counter 87 [00.00%] Hot key 'key:000000000001' found so far with counter 254 [00.00%] Hot key 'mylist' found so far with counter 107 [00.00%] Hot key 'key:000000000000' found so far with counter 254 [45.45%] Hot key 'counter:000000000001' found so far with counter 87 [45.45%] Hot key 'key:000000000002' found so far with counter 254 [45.45%] Hot key 'myset' found so far with counter 64 [45.45%] Hot key 'counter:000000000000' found so far with counter 93-------- summary -------Sampled 22 keys in the keyspace! hot key found with counter: 254 keyname: key:000000000001 hot key found with counter: 254 keyname: key:000000000000 hot key found with counter: 254 keyname: key:000000000002 hot key found with counter: 107 keyname: mylist hot key found with counter: 93 keyname: counter:000000000000 hot key found with counter: 87 keyname: counter:000000000002 hot key found with counter: 87 keyname: counter:000000000001 hot key found with counter: 64 keyname: mysetMEMORY內(nèi)存分析命令
分析內(nèi)存可以?xún)?yōu)化Redis的使用方式,全新的MEMORY命令可以幫助用戶來(lái)實(shí)現(xiàn)這一操作。
MEMORY命令一共有5個(gè)子命令,可以通過(guò)MEMORY HELP來(lái)查看:
127.0.0.1:6379> memory help 1) "MEMORY DOCTOR - Outputs memory problems report" 2) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key" 3) "MEMORY STATS - Show memory usage details" 4) "MEMORY PURGE - Ask the allocator to release memory" 5) "MEMORY MALLOC-STATS - Show allocator internal stats"關(guān)于各個(gè)子命令的詳細(xì)使用方式可以參考《Redis 4.0之MEMORY命令詳解》。
開(kāi)始體驗(yàn)Redis 4.0
- 點(diǎn)擊這里查看Redis 4.0 Release Note
- 體驗(yàn)阿里云數(shù)據(jù)Redis 4.0版請(qǐng)猛擊
作者簡(jiǎn)介
趙釗,花名仲肥,阿里云技術(shù)專(zhuān)家,專(zhuān)注于阿里云數(shù)據(jù)庫(kù)Redis版的開(kāi)發(fā)工作,活躍于Redis開(kāi)源社區(qū),致力讓開(kāi)發(fā)者使用最好的云數(shù)據(jù)庫(kù)服務(wù)。
原文鏈接本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。總結(jié)
以上是生活随笔為你收集整理的Why Redis 4.0?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: iOS Mach异常和signal信号
- 下一篇: 关于CNN图像分类的一份综合设计指南