百億數(shù)據(jù)量下牵舵,掌握這些Redis技巧你就能Hold全場

程序猿DD

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

實際上NewLife.Redis是一個完整的Redis協(xié)議功能的實現(xiàn)宫峦,但是Redis的核心功能并沒有在這里面格带,而是在NewLife.Core里面赎懦。

這里可以打開看一下鞍帝,NewLife.Core里面有一個NewLife.Caching的命名空間,里面有一個Redis類舷暮,里面實現(xiàn)了Redis的基本功能态罪;另一個類是RedisClient是Redis的客戶端。

Redis的核心功能就是有這兩個類實現(xiàn)下面,RedisClient代表著Redis客戶端對服務(wù)器的一個連接复颈。Redis真正使用的時候有一個Redis連接池,里面存放著很多個RedisClient對象沥割。

所以我們Redis的封裝有兩層耗啦,一層是NewLife.Core里面的Redis以及RedisClient凿菩;另一層就是NewLife.Redis。這里面的FullRedis是對Redis的實現(xiàn)了Redis的所有的高級功能帜讲。

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

二、Test實例講解Redis的基本使用

1似将、實例

打開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))想诅,可以選中項目然后右鍵菜單選擇調(diào)試->啟動新實例,會只編譯將會用到的項目岛心,這樣對調(diào)試來說會快很多来破。

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

字典的使用:對象的話忘古,需要把json全部取出來徘禁,然后轉(zhuǎn)換成對象,而字典的話髓堪,就可以直接取某個字段送朱。

隊列是List結(jié)構(gòu)實現(xiàn)的,上游數(shù)據(jù)太多干旁,下游處理不過來的時候驶沼,就可以使用這個隊列。上游的數(shù)據(jù)發(fā)到隊列争群,然后下游慢慢的消費(fèi)回怜。另一個應(yīng)用,跨語言的協(xié)同工作换薄,比方說其他語言實現(xiàn)的程序往隊列里面塞數(shù)據(jù)玉雾,然后另一種語言來進(jìn)行消費(fèi)處理翔试。這種方式類似MQ的概念,雖然有點low抹凳,但是也很好用遏餐。

集合,用的比較多的是用在一個需要精確判斷的去重功能赢底。像我們每天有三千萬訂單失都,這三千萬訂單可以有重復(fù)。這時候我想統(tǒng)計下一共有訂單幸冻,這時候直接數(shù)據(jù)庫group by是不大可能的粹庞,因為數(shù)據(jù)庫中分了十幾張表,這里分享個實戰(zhàn)經(jīng)驗:

比方說攬收洽损,商家發(fā)貨了庞溜,網(wǎng)點要把件收回來,但是收回來之前網(wǎng)點不知道自己有多少貨碑定,這時候我們做了一個功能流码,也就是訂單會發(fā)送到我們公司來。我們會建一個time_site的key的集合延刘,而且集合本身有去重的功能漫试,而且我們可以很方便的通過set.Count功能來統(tǒng)計數(shù)量,當(dāng)件被攬收以后碘赖,我們后臺把這個件從集合中Remove掉驾荣。然后這個Set中存在的就是網(wǎng)點還沒有攬收的件,這時候通過Count就會知道這個網(wǎng)點今天還有多少件沒有攬收普泡。實際使用中這個數(shù)量比較大播掷,因為有幾萬個網(wǎng)點。

Redis中布隆過濾器撼班,去重的歧匈,面試的時候問的比較多。

小經(jīng)驗分享:

數(shù)據(jù)庫中不合法的時間處理:判斷時間中的年份是否大于2000年砰嘁,如果小于2000就認(rèn)為不合法件炉;習(xí)慣大于小于號不習(xí)慣用等于號,這樣可以處理很多意外的數(shù)據(jù)般码;

Set的時候最好指定過期時間妻率,防止有些需要刪除的數(shù)據(jù)我們忘記刪了;

Redis異步盡量不用板祝,因為Redis延遲本身很小宫静,大概在100us-200us,再一個就是Redis本身是單線程的,異步任務(wù)切換的耗時比網(wǎng)絡(luò)耗時還要大孤里;

List用法:物聯(lián)網(wǎng)中數(shù)據(jù)上傳伏伯,量比較大時,我們可以把這些數(shù)據(jù)先放在Redis的List中捌袜,比如說一秒鐘1萬條说搅,然后再批量取出來然后批量插入數(shù)據(jù)庫中。這時候要設(shè)置好key虏等,可以前綴+時間弄唧,對已處理的List可以進(jìn)行remove移除。

2霍衫、壓力測試

接下來看第四個例子候引,我們直接做壓力測試,代碼如下:

運(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)化徐紧。

3静檬、Redis中NB的函數(shù)來提升性能

上面的操作如果大家都掌握了就基本算Redis入門了炭懊,接下來進(jìn)行進(jìn)階并级。如果能全然吃透,差不多就會比別人更勝一籌了侮腹。

GetAll()與SetAll()

GetAll:比方說我要取十個key嘲碧,這個時候可以用getall。這時候Redis就執(zhí)行了一次命令父阻。比方說我要取10個key那么用get的話要取10次愈涩,如果用getall的話要用1次。1次getall時間大概是get的一點幾倍加矛,但是10次get的話就是10倍的時間履婉,這個賬你應(yīng)該會算吧?強(qiáng)烈推薦大家用getall斟览。

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

setall與getall性能很恐怖,官方公布的Ops也就10萬左右已烤,為什么我們的測試輕輕松松到五十萬甚至上百萬鸠窗?因為我們就用了setall,getall。如果get,set兩次以上胯究,建議用getall,setall稍计。

Redis管道Pipelin

比如執(zhí)行10次命令會打包成一個包集體發(fā)過去執(zhí)行,這里實現(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就是實現(xiàn)Redis分布式鎖的關(guān)鍵酷愧。

三、Redis使用技巧缠诅,經(jīng)驗分享

在項目的Readme中溶浴,這里摘錄下:

1、特性

在ZTO大數(shù)據(jù)實時計算廣泛應(yīng)用管引,200多個Redis實例穩(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)制性能會提升很多)。

2猛们、Redis經(jīng)驗分享

在Linux上多實例部署念脯,實例個數(shù)等于處理器個數(shù),各實例最大內(nèi)存直接為本機(jī)物理內(nèi)存弯淘,避免單個實例內(nèi)存撐爆(比方說8核心處理器绿店,那么就部署8個實例)。

把海量數(shù)據(jù)(10億+)根據(jù)key哈希(Crc16/Crc32)存放在多個實例上庐橙,讀寫性能成倍增長假勿。

采用二進(jìn)制序列化,而非常見的Json序列化态鳖。

合理設(shè)計每一對Key的Value大小转培,包括但不限于使用批量獲取,原則是讓每次網(wǎng)絡(luò)包控制在1.4k字節(jié)附近浆竭,減少通信次數(shù)(實際經(jīng)驗幾十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á)到瓶頸特碳。

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

其它可查優(yōu)化技巧诚亚。

以上經(jīng)驗,源自于300多個實例4T以上空間一年多穩(wěn)定工作的經(jīng)驗午乓,并按照重要程度排了先后順序站宗,可根據(jù)場景需要酌情采用。

3硅瞧、緩存Redis的兄弟姐妹

Redis實現(xiàn)ICache接口份乒,它的孿生兄弟MemoryCache恕汇,內(nèi)存緩存腕唧,千萬級吞吐率。

各應(yīng)用強(qiáng)烈建議使用ICache接口編碼設(shè)計瘾英,小數(shù)據(jù)時使用MemoryCache實現(xiàn)枣接;數(shù)據(jù)增大(10萬)以后,改用Redis實現(xiàn)缺谴,不需要修改業(yè)務(wù)代碼但惶。

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

這一Part我們會來聊聊大數(shù)據(jù)中Redis使用的經(jīng)驗:

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

A1:如果對性能要求不是很高直接用json序列化實體就好膀曾,沒必要使用字典進(jìn)行存儲县爬。

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

A2:隊列其實就是用List實現(xiàn)的财喳,也是基于List封裝的。左進(jìn)右出的話直接隊列就好斩狱。Redis的List結(jié)構(gòu)比較有意思耳高,既可以左進(jìn)右出,也能右進(jìn)左出所踊。所以它既可以實現(xiàn)列表結(jié)構(gòu)泌枪,也能隊列,還能實現(xiàn)棧秕岛。

Q3:存放多個字段的類性能一樣嗎碌燕?

A3:大部分場景都不會有偏差,可能對于大公司數(shù)據(jù)量比較大的場景會有些偏差继薛。

Q4:大數(shù)據(jù)寫入到數(shù)據(jù)庫之后陆蟆,比如數(shù)據(jù)到億以上的時候,統(tǒng)計分析惋增、查詢這塊叠殷,能不能分享些經(jīng)驗。

A4:分表分庫诈皿,拆分到一千萬以內(nèi)林束。

Q5:CPU為何暴漲?

A5:程序員終極理念——CPU達(dá)到百分百稽亏,然后性能達(dá)到最優(yōu)壶冒,盡量不要浪費(fèi)。最痛恨的是——如果CPU不到百分百截歉,性能沒法提升了胖腾,說明代碼有問題。

雖然Redis大家會用瘪松,但是我們可能平時不會有像這樣的大數(shù)據(jù)使用場景咸作。希望本文能夠給大家一些值得借鑒的經(jīng)驗。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宵睦,一起剝皮案震驚了整個濱河市记罚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌壳嚎,老刑警劉巖桐智,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件末早,死亡現(xiàn)場離奇詭異,居然都是意外死亡说庭,警方通過查閱死者的電腦和手機(jī)然磷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刊驴,“玉大人样屠,你說我怎么就攤上這事∪甭觯” “怎么了痪欲?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長攻礼。 經(jīng)常有香客問我业踢,道長,這世上最難降的妖魔是什么礁扮? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任知举,我火速辦了婚禮,結(jié)果婚禮上太伊,老公的妹妹穿的比我還像新娘雇锡。我一直安慰自己,他們只是感情好僚焦,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布锰提。 她就那樣靜靜地躺著,像睡著了一般芳悲。 火紅的嫁衣襯著肌膚如雪立肘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天名扛,我揣著相機(jī)與錄音谅年,去河邊找鬼。 笑死肮韧,一個胖子當(dāng)著我的面吹牛融蹂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弄企,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼超燃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了桩蓉?” 一聲冷哼從身側(cè)響起淋纲,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎院究,沒想到半個月后洽瞬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡业汰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年伙窃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片样漆。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡为障,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出放祟,到底是詐尸還是另有隱情鳍怨,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布跪妥,位于F島的核電站鞋喇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏眉撵。R本人自食惡果不足惜侦香,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纽疟。 院中可真熱鬧罐韩,春花似錦、人聲如沸污朽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蟆肆。三九已至错蝴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颓芭,已是汗流浹背顷锰。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留亡问,地道東北人官紫。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像州藕,于是被迫代替她去往敵國和親束世。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

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