百億數(shù)據(jù)量下篙悯,掌握這些Redis技巧你就能Hold全場(chǎng)

image

一、Redis封裝架構(gòu)講解

實(shí)際上NewLife.Redis是一個(gè)完整的Redis協(xié)議功能的實(shí)現(xiàn)夕凝,但是Redis的核心功能并沒(méi)有在這里面宝穗,而是在NewLife.Core里面。

這里可以打開(kāi)看一下码秉,NewLife.Core里面有一個(gè)NewLife.Caching的命名空間逮矛,里面有一個(gè)Redis類,里面實(shí)現(xiàn)了Redis的基本功能转砖;另一個(gè)類是RedisClient是Redis的客戶端须鼎。

Redis的核心功能就是有這兩個(gè)類實(shí)現(xiàn)鲸伴,RedisClient代表著Redis客戶端對(duì)服務(wù)器的一個(gè)連接。Redis真正使用的時(shí)候有一個(gè)Redis連接池晋控,里面存放著很多個(gè)RedisClient對(duì)象汞窗。

image

所以我們Redis的封裝有兩層,一層是NewLife.Core里面的Redis以及RedisClient赡译;另一層就是NewLife.Redis仲吏。這里面的FullRedis是對(duì)Redis的實(shí)現(xiàn)了Redis的所有的高級(jí)功能。

這里你也可以認(rèn)為NewLife.Redis是Redis的一個(gè)擴(kuò)展蝌焚。

二裹唆、Test實(shí)例講解Redis的基本使用

1、實(shí)例

打開(kāi)Program.cs看下代碼:

image

這里XTrace.UseConsole();是向控制臺(tái)輸出日志只洒,方便調(diào)試使用查看結(jié)果许帐。

接下來(lái)看第一個(gè)例子Test1,具體的我都在代碼中進(jìn)行了注釋毕谴,大家可以看下:

image

Set的時(shí)候成畦,如果是字符串或者字符數(shù)據(jù)的話,Redis會(huì)直接保存起來(lái)(字符串內(nèi)部機(jī)制也是保存二進(jìn)制)涝开,如果是其他類型羡鸥,會(huì)默認(rèn)進(jìn)行json序列化然后再保存起來(lái)。

Get的時(shí)候忠寻,如果是字符串或者字符數(shù)據(jù)會(huì)直接獲取惧浴,如果是其他類型會(huì)進(jìn)行json反序列化。

Set第三個(gè)參數(shù)過(guò)期時(shí)間單位是秒奕剃。

vs調(diào)試小技巧衷旅,按F5或者直接工具欄“啟動(dòng)”會(huì)編譯整個(gè)解決方案會(huì)很慢(VS默認(rèn)),可以選中項(xiàng)目然后右鍵菜單選擇調(diào)試->啟動(dòng)新實(shí)例纵朋,會(huì)只編譯將會(huì)用到的項(xiàng)目柿顶,這樣對(duì)調(diào)試來(lái)說(shuō)會(huì)快很多。

大家運(yùn)行調(diào)試后可以看到控制臺(tái)輸出的內(nèi)容:向右的箭頭=》是ic.Log=XTrace.Log輸出的日志操软。

image

字典的使用:對(duì)象的話嘁锯,需要把json全部取出來(lái),然后轉(zhuǎn)換成對(duì)象聂薪,而字典的話家乘,就可以直接取某個(gè)字段。

隊(duì)列是List結(jié)構(gòu)實(shí)現(xiàn)的藏澳,上游數(shù)據(jù)太多仁锯,下游處理不過(guò)來(lái)的時(shí)候,就可以使用這個(gè)隊(duì)列翔悠。上游的數(shù)據(jù)發(fā)到隊(duì)列业崖,然后下游慢慢的消費(fèi)野芒。另一個(gè)應(yīng)用,跨語(yǔ)言的協(xié)同工作双炕,比方說(shuō)其他語(yǔ)言實(shí)現(xiàn)的程序往隊(duì)列里面塞數(shù)據(jù)狞悲,然后另一種語(yǔ)言來(lái)進(jìn)行消費(fèi)處理。這種方式類似MQ的概念妇斤,雖然有點(diǎn)low摇锋,但是也很好用。

集合趟济,用的比較多的是用在一個(gè)需要精確判斷的去重功能乱投。像我們每天有三千萬(wàn)訂單咽笼,這三千萬(wàn)訂單可以有重復(fù)顷编。這時(shí)候我想統(tǒng)計(jì)下一共有訂單,這時(shí)候直接數(shù)據(jù)庫(kù)group by是不大可能的剑刑,因?yàn)閿?shù)據(jù)庫(kù)中分了十幾張表媳纬,這里分享個(gè)實(shí)戰(zhàn)經(jīng)驗(yàn):

比方說(shuō)攬收,商家發(fā)貨了施掏,網(wǎng)點(diǎn)要把件收回來(lái)钮惠,但是收回來(lái)之前網(wǎng)點(diǎn)不知道自己有多少貨,這時(shí)候我們做了一個(gè)功能七芭,也就是訂單會(huì)發(fā)送到我們公司來(lái)素挽。我們會(huì)建一個(gè)time_site的key的集合,而且集合本身有去重的功能狸驳,而且我們可以很方便的通過(guò)set.Count功能來(lái)統(tǒng)計(jì)數(shù)量预明,當(dāng)件被攬收以后,我們后臺(tái)把這個(gè)件從集合中Remove掉耙箍。然后這個(gè)Set中存在的就是網(wǎng)點(diǎn)還沒(méi)有攬收的件撰糠,這時(shí)候通過(guò)Count就會(huì)知道這個(gè)網(wǎng)點(diǎn)今天還有多少件沒(méi)有攬收。實(shí)際使用中這個(gè)數(shù)量比較大辩昆,因?yàn)橛袔兹f(wàn)個(gè)網(wǎng)點(diǎn)阅酪。

Redis中布隆過(guò)濾器,去重的汁针,面試的時(shí)候問(wèn)的比較多术辐。

小經(jīng)驗(yàn)分享:

數(shù)據(jù)庫(kù)中不合法的時(shí)間處理:判斷時(shí)間中的年份是否大于2000年,如果小于2000就認(rèn)為不合法施无;習(xí)慣大于小于號(hào)不習(xí)慣用等于號(hào)术吗,這樣可以處理很多意外的數(shù)據(jù);

Set的時(shí)候最好指定過(guò)期時(shí)間帆精,防止有些需要?jiǎng)h除的數(shù)據(jù)我們忘記刪了较屿;

Redis異步盡量不用隧魄,因?yàn)镽edis延遲本身很小,大概在100us-200us隘蝎,再一個(gè)就是Redis本身是單線程的购啄,異步任務(wù)切換的耗時(shí)比網(wǎng)絡(luò)耗時(shí)還要大;

List用法:物聯(lián)網(wǎng)中數(shù)據(jù)上傳嘱么,量比較大時(shí)狮含,我們可以把這些數(shù)據(jù)先放在Redis的List中,比如說(shuō)一秒鐘1萬(wàn)條曼振,然后再批量取出來(lái)然后批量插入數(shù)據(jù)庫(kù)中几迄。這時(shí)候要設(shè)置好key,可以前綴+時(shí)間冰评,對(duì)已處理的List可以進(jìn)行remove移除映胁。

2、壓力測(cè)試

接下來(lái)看第四個(gè)例子甲雅,我們直接做壓力測(cè)試解孙,代碼如下:

image

運(yùn)行的結(jié)果如下圖所示:

image

測(cè)試就是進(jìn)行g(shù)et,set remove,累加等的操作。大家可以看到在我本機(jī)上輕輕松松的到了六十萬(wàn)抛人,多線程的時(shí)候甚至到了一百多萬(wàn)弛姜。

為什么會(huì)達(dá)到這么高的Ops呢?下面給大家說(shuō)一下:

Bench會(huì)分根據(jù)線程數(shù)分多組進(jìn)行添刪改壓力測(cè)試妖枚;

rand參數(shù)廷臼,是否隨機(jī)產(chǎn)生key/value;

batch批大小绝页,分批執(zhí)行讀寫(xiě)操作荠商,借助GetAll/SetAll進(jìn)行優(yōu)化。

3抒寂、Redis中NB的函數(shù)來(lái)提升性能

上面的操作如果大家都掌握了就基本算Redis入門了结啼,接下來(lái)進(jìn)行進(jìn)階。如果能全然吃透屈芜,差不多就會(huì)比別人更勝一籌了郊愧。

GetAll()與SetAll()

GetAll:比方說(shuō)我要取十個(gè)key,這個(gè)時(shí)候可以用getall井佑。這時(shí)候Redis就執(zhí)行了一次命令属铁。比方說(shuō)我要取10個(gè)key那么用get的話要取10次,如果用getall的話要用1次躬翁。1次getall時(shí)間大概是get的一點(diǎn)幾倍焦蘑,但是10次get的話就是10倍的時(shí)間,這個(gè)賬你應(yīng)該會(huì)算吧盒发?強(qiáng)烈推薦大家用getall例嘱。

setall跟getall相似狡逢,批量設(shè)置K-V。

setall與getall性能很恐怖拼卵,官方公布的Ops也就10萬(wàn)左右奢浑,為什么我們的測(cè)試輕輕松松到五十萬(wàn)甚至上百萬(wàn)?因?yàn)槲覀兙陀昧藄etall,getall腋腮。如果get,set兩次以上雀彼,建議用getall,setall。

Redis管道Pipelin

比如執(zhí)行10次命令會(huì)打包成一個(gè)包集體發(fā)過(guò)去執(zhí)行即寡,這里實(shí)現(xiàn)的方式是StartPipeline()開(kāi)始徊哑,StopPipeline()結(jié)束中間的代碼就會(huì)以管道的形式執(zhí)行。

這里推薦使用更強(qiáng)的武器聪富,AutoPipeline自動(dòng)管道屬性莺丑。管道操作到一定數(shù)量時(shí),自動(dòng)提交善涨,默認(rèn)0窒盐。使用了AutoPipeline草则,就不需要StartPipeline钢拧,StopPipeline指定管道的開(kāi)始結(jié)束了。

Add與Replace

Add:Redis中沒(méi)有這個(gè)Key就添加炕横,有了就不要添加源内,返回false;

Replace:有則替換份殿,還會(huì)返回原來(lái)的值膜钓,沒(méi)有則不進(jìn)行操作。

Add跟Replace就是實(shí)現(xiàn)Redis分布式鎖的關(guān)鍵卿嘲。

三颂斜、Redis使用技巧,經(jīng)驗(yàn)分享

在項(xiàng)目的Readme中拾枣,這里摘錄下:

1沃疮、特性

在ZTO大數(shù)據(jù)實(shí)時(shí)計(jì)算廣泛應(yīng)用,200多個(gè)Redis實(shí)例穩(wěn)定工作一年多梅肤,每天處理近1億包裹數(shù)據(jù)司蔬,日均調(diào)用量80億次;

低延遲姨蝴,Get/Set操作平均耗時(shí)200~600us(含往返網(wǎng)絡(luò)通信)俊啼;

大吞吐,自帶連接池左医,最大支持1000并發(fā)授帕;

高性能同木,支持二進(jìn)制序列化(默認(rèn)用的json,json很低效跛十,轉(zhuǎn)成二進(jìn)制性能會(huì)提升很多)泉手。

2、Redis經(jīng)驗(yàn)分享

在Linux上多實(shí)例部署偶器,實(shí)例個(gè)數(shù)等于處理器個(gè)數(shù)斩萌,各實(shí)例最大內(nèi)存直接為本機(jī)物理內(nèi)存,避免單個(gè)實(shí)例內(nèi)存撐爆(比方說(shuō)8核心處理器屏轰,那么就部署8個(gè)實(shí)例)颊郎。

把海量數(shù)據(jù)(10億+)根據(jù)key哈希(Crc16/Crc32)存放在多個(gè)實(shí)例上,讀寫(xiě)性能成倍增長(zhǎng)霎苗。

采用二進(jìn)制序列化姆吭,而非常見(jiàn)的Json序列化。

合理設(shè)計(jì)每一對(duì)Key的Value大小唁盏,包括但不限于使用批量獲取内狸,原則是讓每次網(wǎng)絡(luò)包控制在1.4k字節(jié)附近,減少通信次數(shù)(實(shí)際經(jīng)驗(yàn)幾十k厘擂,幾百k也是沒(méi)問(wèn)題的)昆淡。

Redis客戶端的Get/Set操作平均耗時(shí)200~600us(含往返網(wǎng)絡(luò)通信),以此為參考評(píng)估網(wǎng)絡(luò)環(huán)境和Redis客戶端組件(達(dá)不到就看一下網(wǎng)絡(luò)刽严,序列化方式等等)昂灵。

使用管道Pipeline合并一批命令。

Redis的主要性能瓶頸是序列化舞萄、網(wǎng)絡(luò)帶寬和內(nèi)存大小眨补,濫用時(shí)處理器也會(huì)達(dá)到瓶頸。

在此我向大家推薦一個(gè)架構(gòu)學(xué)習(xí)交流圈:964357187幫助突破Java瓶頸 提升思維能力

其它可查優(yōu)化技巧倒脓。

以上經(jīng)驗(yàn)撑螺,源自于300多個(gè)實(shí)例4T以上空間一年多穩(wěn)定工作的經(jīng)驗(yàn),并按照重要程度排了先后順序崎弃,可根據(jù)場(chǎng)景需要酌情采用甘晤。

3、緩存Redis的兄弟姐妹

Redis實(shí)現(xiàn)ICache接口吊履,它的孿生兄弟MemoryCache安皱,內(nèi)存緩存,千萬(wàn)級(jí)吞吐率艇炎。

各應(yīng)用強(qiáng)烈建議使用ICache接口編碼設(shè)計(jì)酌伊,小數(shù)據(jù)時(shí)使用MemoryCache實(shí)現(xiàn);數(shù)據(jù)增大(10萬(wàn))以后,改用Redis實(shí)現(xiàn)居砖,不需要修改業(yè)務(wù)代碼虹脯。

四、關(guān)于一些疑問(wèn)的回復(fù)

這一Part我們會(huì)來(lái)聊聊大數(shù)據(jù)中Redis使用的經(jīng)驗(yàn):

Q1:一條數(shù)據(jù)多個(gè)key怎么設(shè)置比較合理奏候?

A1:如果對(duì)性能要求不是很高直接用json序列化實(shí)體就好循集,沒(méi)必要使用字典進(jìn)行存儲(chǔ)。

Q2:隊(duì)列跟List有什么區(qū)別蔗草?左進(jìn)右出的話用List還是用隊(duì)列比較好咒彤?

A2:隊(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)棧故觅。

Q3:存放多個(gè)字段的類性能一樣嗎?

A3:大部分場(chǎng)景都不會(huì)有偏差渠啊,可能對(duì)于大公司數(shù)據(jù)量比較大的場(chǎng)景會(huì)有些偏差输吏。

Q4:大數(shù)據(jù)寫(xiě)入到數(shù)據(jù)庫(kù)之后,比如數(shù)據(jù)到億以上的時(shí)候昭抒,統(tǒng)計(jì)分析评也、查詢這塊炼杖,能不能分享些經(jīng)驗(yàn)灭返。

A4:分表分庫(kù),拆分到一千萬(wàn)以內(nèi)坤邪。

Q5:CPU為何暴漲熙含?

A5:程序員終極理念——CPU達(dá)到百分百,然后性能達(dá)到最優(yōu)艇纺,盡量不要浪費(fèi)怎静。最痛恨的是——如果CPU不到百分百,性能沒(méi)法提升了黔衡,說(shuō)明代碼有問(wèn)題蚓聘。

image

雖然Redis大家會(huì)用,但是我們可能平時(shí)不會(huì)有像這樣的大數(shù)據(jù)使用場(chǎng)景盟劫。希望本文能夠給大家一些值得借鑒的經(jīng)驗(yàn)夜牡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市侣签,隨后出現(xiàn)的幾起案子塘装,更是在濱河造成了極大的恐慌急迂,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹦肴,死亡現(xiàn)場(chǎng)離奇詭異僚碎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)阴幌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門勺阐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人矛双,你說(shuō)我怎么就攤上這事皆看。” “怎么了背零?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵腰吟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我徙瓶,道長(zhǎng)毛雇,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任侦镇,我火速辦了婚禮灵疮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壳繁。我一直安慰自己震捣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布闹炉。 她就那樣靜靜地躺著蒿赢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羡棵。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天养篓,我揣著相機(jī)與錄音秃流,去河邊找鬼。 笑死柳弄,一個(gè)胖子當(dāng)著我的面吹牛舶胀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼峻贮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼席怪!你這毒婦竟也來(lái)了挂捻?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤船万,失蹤者是張志新(化名)和其女友劉穎刻撒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體耿导,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡醋火,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了箱吕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芥驳。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茬高,靈堂內(nèi)的尸體忽然破棺而出兆旬,到底是詐尸還是另有隱情,我是刑警寧澤怎栽,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布丽猬,位于F島的核電站,受9級(jí)特大地震影響熏瞄,放射性物質(zhì)發(fā)生泄漏脚祟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一巴刻、第九天 我趴在偏房一處隱蔽的房頂上張望愚铡。 院中可真熱鬧,春花似錦胡陪、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至片橡,卻和暖如春妈经,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工吹泡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留骤星,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓爆哑,卻偏偏與公主長(zhǎng)得像洞难,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揭朝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容