Redis基本使用及百亿数据量中的使用技巧分享
作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/9941208.html
作者:大石頭
時間:2018-11-10 晚上20:00
地點(diǎn):釘釘群(組織代碼BKMV7685)QQ群:1600800
內(nèi)容:Redis基本使用及百億數(shù)據(jù)量中的使用技巧分享
記錄人:依樂祝
熱場準(zhǔn)備
熟悉的開場白,大家晚上好啊,今天給大家分享的是Redis在大數(shù)據(jù)中的使用,可能真正講的是一些redis的使用技巧,Redis基本的一些東西。
首先給大家個地址,源碼以及實(shí)例都在里面,當(dāng)然今天的分享也是按照里面的實(shí)例來進(jìn)行的,大家可以先進(jìn)行下載。
http://git.newlifex.com/NewLife/NewLife.Redis
當(dāng)然這里也附上Redis的下載地址:
windows:https://github.com/MicrosoftArchive/redis/releases
http://x.newlifex.com/Redis-x64-3.2.100.msi
Linux:https://redis.io/download
開始
Redis封裝架構(gòu)講解
實(shí)際上NewLife.Redis是一個完整的Redis協(xié)議的功能的實(shí)現(xiàn),但是redis的核心功能并沒有在這里面,Redis的核心功能的實(shí)現(xiàn)是在NewLife.Core里面。這里可以打開看一下,NewLife.Core里面有一個NewLife.Caching的命名空間,里面有一個Redis類里面實(shí)現(xiàn)了Redis的基本功能,另一個類是RedisClient是Redis的客戶端。Redis的核心功能就是有這兩個類實(shí)現(xiàn)。RedisClient代表著Redis客戶端對服務(wù)器的一個連接。Redis真正使用的時候有一個Redis連接池,里面存放著很多個RedisClient對象。
所以我們Redis的封裝有兩層,一層是NewLife.Core里面的Redis以及RedisClient。另一層就是NewLife.Redis。這里面的FullRedis是對Redis的實(shí)現(xiàn)了Redis的所有的高級功能。這里你也可以認(rèn)為NewLife.Redis是Redis的一個擴(kuò)展。
Test實(shí)例講解Redis的基本使用
實(shí)例
打開Program.cs看下代碼
這里XTrace.UseConsole();是向控制臺輸出日志,方便調(diào)試使用查看結(jié)果。
接下來看第一個例子Test1。具體的我都在代碼中進(jìn)行了注釋,大家可以看下
Set的時候如果是字符串或者字符數(shù)據(jù)的話Redis會直接保存起來(字符串內(nèi)部機(jī)制也是保存二進(jìn)制),如果是其他類型會默認(rèn)進(jìn)行json序列化然后再保存起來
Get的時候如果是字符串或者字符數(shù)據(jù)會直接獲取,如果是其他類型會進(jìn)行json反序列化
Set第三個參數(shù)過期時間單位是秒。
vs調(diào)試小技巧,按F5或者直接工具欄“啟動”會編譯整個解決方案會很慢(VS默認(rèn)),可以選中項(xiàng)目然后右鍵菜單選擇調(diào)試->啟動新實(shí)例。會只編譯將會用到的項(xiàng)目,這樣對調(diào)試來說會快很多。
大家運(yùn)行調(diào)試后可以看到控制臺輸出的內(nèi)容:向右的箭頭=》是ic.Log=XTrace.Log輸出的日志
字典的使用:對象的話需要把json全部取出來然后轉(zhuǎn)換成對象,而字典的話就可以直接取某個字段。
隊(duì)列是List結(jié)構(gòu)實(shí)現(xiàn)的,使用場景可以上游數(shù)據(jù)太多,下游處理不過來的時候,那么就可以使用這個隊(duì)列。上游的數(shù)據(jù)發(fā)到隊(duì)列,然后下游慢慢的消費(fèi)。另一個應(yīng)用,跨語言的協(xié)同工作,比方說其他語言實(shí)現(xiàn)的程序往隊(duì)列里面塞數(shù)據(jù),然后另一種語言來進(jìn)行消費(fèi)處理。哈,這種方式類似mq的概念,雖然有點(diǎn)low,但是也很好用。
集合,用的比較多的是用在一個需要精確判斷的去重功能。像我們每天有三千萬訂單,這三千萬訂單可以有重復(fù),這時候我想統(tǒng)計(jì)下一共有訂單,這時候直接數(shù)據(jù)庫group by是不大可能的,因?yàn)閿?shù)據(jù)庫中分了十幾張表,這里分享個實(shí)戰(zhàn)經(jīng)驗(yàn):比方說攬收,商家發(fā)貨了,網(wǎng)點(diǎn)要把件收回來,但是收回來之前網(wǎng)點(diǎn)不知道自己有多少貨啊,這時候我們做了一個功能,也就是訂單會發(fā)送到我們公司來,我們會建一個time_site的key的集合,而且集合本身有去重的功能,而且我們可以很方便的通過set.Count功能來統(tǒng)計(jì)數(shù)量,當(dāng)件被攬收以后,我們后臺把這個件從集合中Remove掉.然后這個Set中存在的就是網(wǎng)點(diǎn)還沒有攬收的件,這時候通過Count就會知道這個網(wǎng)點(diǎn)今天還有多少件沒有攬收。實(shí)際使用中這個數(shù)量比較大,因?yàn)橛袔兹f個網(wǎng)點(diǎn)。
Redis中布隆過濾器,去重的,面試的時候問的比較多
小經(jīng)驗(yàn)分享:
數(shù)據(jù)庫中不合法的時間處理:判斷時間中的年份,是否大于2000年。如果小于2000就認(rèn)為不合法。習(xí)慣大于小于號不習(xí)慣用等于號,這樣可以處理很多意外的數(shù)據(jù)
Set的時候最好指定過期時間防止有些需要刪除的數(shù)據(jù),我們忘記刪了
Redis異步盡量不用,因?yàn)镽edis延遲本身很小,大概在100us-200us,再一個就是Redis本身是單線程的,異步任務(wù)切換的耗時比網(wǎng)絡(luò)耗時還要大。
List用法:物聯(lián)網(wǎng)中數(shù)據(jù)上傳,量比較大時,我們可以把這些數(shù)據(jù)先放在Redis的List中,比如說一秒鐘1萬條,然后再批量取出來然后批量插入數(shù)據(jù)庫中。這時候要設(shè)置好key,可以前綴+時間,對于已經(jīng)處理的List可以進(jìn)行remove移除。
壓力測試
接下來看第四個例子,我們直接做壓力測試,代碼如下:
運(yùn)行的結(jié)果如下圖所示:
測試就是進(jìn)行g(shù)et,set remove,累加等的操作。大家可以看到在我本機(jī)上輕輕松松的到了六十萬,多線程的時候甚至到了一百多萬。為什么會達(dá)到這么高的ops呢,下面給大家說一下。
Bench 會分根據(jù)線程數(shù)分多組進(jìn)行添刪改壓力測試。
rand 參數(shù),是否隨機(jī)產(chǎn)生key/value。
batch 批大小,分批執(zhí)行讀寫操作,借助GetAll/SetAll進(jìn)行優(yōu)化。
Redis中NB的函數(shù)來提升性能
上面的操作如果大家都掌握的基本算Redis入門了,接下來進(jìn)行進(jìn)階。會了基本比別人更勝一籌了。
GetAll()與SetAll()
GetAll:比方說我要取是個key,這個時候可以用getall。這時候redis就執(zhí)行了一次命令。比方說我要取10個key那么用get的話要取10次,如果用getall的話要用1次。一次getall時間大概是get的一點(diǎn)幾倍,但是10次get的話就是10倍的時間,這個賬你應(yīng)該會算吧。強(qiáng)烈推薦大家用getall。
setall 跟getall相似。批量設(shè)置K-V.
setall與getall性能很恐怖,官方公布的ops也就10萬左右,為什么我們的測試輕輕松松到五十萬甚至上百萬,因?yàn)槲覀兙陀昧藄etall,getall。
如果get,set兩次以上,建議用getall,setall
Redis管道Pipeline
比如執(zhí)行10次命令會打包成一個包集體發(fā)過去執(zhí)行,這里實(shí)現(xiàn)的方式是StartPipeline()開始,StopPipeline()結(jié)束中間的代碼就會以管道的形式執(zhí)行。這里推薦使用我們的更強(qiáng)的武器,AutoPipeline自動管道屬性。管道操作到一定數(shù)量時,自動提交,默認(rèn)0.使用了不需要使用AutoPipeline,就不需要StartPipeline,StopPipeline指定開始結(jié)束了!
Add與Replace
Add:Redis中沒有這個Key就添加,有了就不要添加,返回false
Replace:有則替換,還會返回原來的值,沒有則不進(jìn)行操作
Add跟Replace就是實(shí)現(xiàn)Redis分布式鎖的關(guān)鍵
Redis使用技巧,經(jīng)驗(yàn)分享
在項(xiàng)目的Readme中,這里摘錄下:
特性
在ZTO大數(shù)據(jù)實(shí)時計(jì)算廣泛應(yīng)用,200多個Redis實(shí)例穩(wěn)定工作一年多,每天處理近1億包裹數(shù)據(jù),日均調(diào)用量80億次
低延遲,Get/Set操作平均耗時200~600us(含往返網(wǎng)絡(luò)通信)
大吞吐,自帶連接池,最大支持1000并發(fā)
高性能,支持二進(jìn)制序列化(默認(rèn)用的json,json很低效,轉(zhuǎn)成二進(jìn)制性能會提升很多)
Redis經(jīng)驗(yàn)分享
在Linux上多實(shí)例部署,實(shí)例個數(shù)等于處理器個數(shù),各實(shí)例最大內(nèi)存直接為本機(jī)物理內(nèi)存,避免單個實(shí)例內(nèi)存撐爆(比方說8核心處理器,那么就部署8個實(shí)例)
把海量數(shù)據(jù)(10億+)根據(jù)key哈希(Crc16/Crc32)存放在多個實(shí)例上,讀寫性能成倍增長
采用二進(jìn)制序列化,而非常見的Json序列化
合理設(shè)計(jì)每一對Key的Value大小,包括但不限于使用批量獲取,原則是讓每次網(wǎng)絡(luò)包控制在1.4k字節(jié)附近,減少通信次數(shù)(實(shí)際經(jīng)驗(yàn)幾十k,幾百k也是沒問題的)
Redis客戶端的Get/Set操作平均耗時200~600us(含往返網(wǎng)絡(luò)通信),以此為參考評估網(wǎng)絡(luò)環(huán)境和Redis客戶端組件(達(dá)不到就看一下網(wǎng)絡(luò),序列化方式等等)
使用管道Pipeline合并一批命令
Redis的主要性能瓶頸是序列化、網(wǎng)絡(luò)帶寬和內(nèi)存大小,濫用時處理器也會達(dá)到瓶頸
其它可查優(yōu)化技巧
以上經(jīng)驗(yàn),源自于300多個實(shí)例4T以上空間一年多穩(wěn)定工作的經(jīng)驗(yàn),并按照重要程度排了先后順序,可根據(jù)場景需要酌情采用!
緩存Redis的兄弟姐妹
Redis實(shí)現(xiàn)ICache接口,它的孿生兄弟MemoryCache,內(nèi)存緩存,千萬級吞吐率。
各應(yīng)用強(qiáng)烈建議使用ICache接口編碼設(shè)計(jì),小數(shù)據(jù)時使用MemoryCache實(shí)現(xiàn);
數(shù)據(jù)增大(10萬)以后,改用Redis實(shí)現(xiàn),不需要修改業(yè)務(wù)代碼。
提問環(huán)節(jié)聊聊大數(shù)據(jù)中Redis使用的經(jīng)驗(yàn),問題
一條數(shù)據(jù)多個key怎么設(shè)置比較合理?
如果對性能要求不是很高直接用json序列化實(shí)體就好,沒必要使用字典進(jìn)行存儲。
隊(duì)列跟List有什么區(qū)別?左進(jìn)右出的話用List還是用隊(duì)列比較好?
隊(duì)列其實(shí)就是用List實(shí)現(xiàn)的,也是基于List封裝的。左進(jìn)右出的話直接隊(duì)列就好。Redis的List結(jié)構(gòu)比較有意思,既可以左進(jìn)右出,也能右進(jìn)左出。所以它既可以實(shí)現(xiàn)列表結(jié)構(gòu),也能隊(duì)列,也能實(shí)現(xiàn)棧
存放多個字段的類性能一樣嗎?
大部分場景都不會有偏差,可能對于大公司數(shù)據(jù)量比較大的場景會有些偏差
可否介紹一下使用Redis進(jìn)行數(shù)據(jù)計(jì)算、統(tǒng)計(jì)的場景?
略。自己看視頻吧!o(∩_∩)o 哈哈!(因?yàn)槲覜]聽清!)
大數(shù)據(jù)寫入到數(shù)據(jù)庫之后 比如數(shù)據(jù)到億以上的時候 統(tǒng)計(jì)分析這塊 查詢這塊 能不能分享些經(jīng)驗(yàn)。
分表分庫,拆分到一千萬以內(nèi)。
CPU為何暴漲?
程序員終極理念:CPU達(dá)到百分百,然后性能達(dá)到最優(yōu),盡量不要浪費(fèi)。最痛恨的是:如果cpu不到百分百,性能沒法提升了,說明代碼有問題!
總結(jié)
雖然Redis會用,但是沒有像大石頭這樣的大數(shù)據(jù)使用場景。今天的視頻收獲頗豐,可能大部分人跟我一樣,沒有大石頭的使用場景,但是值得借鑒的經(jīng)驗(yàn)還是很豐富的!期待下一次的精彩分享。同時附上QQ群:1600800。可以共同交流使用經(jīng)驗(yàn)!
原文地址: https://www.cnblogs.com/yilezhu/p/9941208.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的Redis基本使用及百亿数据量中的使用技巧分享的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【.NET Core项目实战-统一认证平
- 下一篇: 一个技术管理者的苦逼【技术管理漫谈】