高并發(fā)基礎(chǔ)知識(一)

Netty之所以這么火洪碳,與它的巨大優(yōu)點是密不可分的递览,大致可以總結(jié)如下:

· API使用簡單,開發(fā)門檻低瞳腌〗柿澹· 功能強大,預(yù)置了多種編解碼功能嫂侍,支持多種主流協(xié)議儿捧。

· 定制能力強,可以通過ChannelHandler對通信框架進行靈活擴展挑宠〈棵· 性能高,與其他業(yè)界主流的NIO框架對比痹栖,Netty的綜合性能最優(yōu)。

· 成熟瞭空、穩(wěn)定揪阿,Netty修復(fù)了已經(jīng)發(fā)現(xiàn)的所有JDK NIO中的BUG,業(yè)務(wù)開發(fā)人員不需要再為NIO的BUG而煩惱咆畏。

· 社區(qū)活躍南捂,版本迭代周期短,發(fā)現(xiàn)的BUG可以被及時修復(fù)旧找。



Redis的主要應(yīng)用場景:緩存(數(shù)據(jù)查詢溺健、短連接、新聞內(nèi)容钮蛛、商品內(nèi)容等)鞭缭、分布式會話(Session)剖膳、聊天室的在線好友列表、任務(wù)隊列(秒殺岭辣、搶購吱晒、12306等)、應(yīng)用排行榜沦童、訪問統(tǒng)計仑濒、數(shù)據(jù)過期處理(可以精確到毫秒)。


相對于其他的鍵-值對(Key-Value)內(nèi)存數(shù)據(jù)庫(如Memcached)而言偷遗,Redis具有如下特點:

(1)速度快 不需要等待磁盤的IO墩瞳,在內(nèi)存之間進行的數(shù)據(jù)存儲和查詢,速度非呈贤悖快喉酌。當然,緩存的數(shù)據(jù)總量不能太大箩溃,因為受到物理內(nèi)存空間大小的限制瞭吃。

(2)豐富的數(shù)據(jù)結(jié)構(gòu) 除了string之外,還有l(wèi)ist涣旨、hash歪架、set、sortedset霹陡,一共五種類型和蚪。

(3)單線程,避免了線程切換和鎖機制的性能消耗烹棉。

(4)可持久化 支持RDB與AOF兩種方式攒霹,將內(nèi)存中的數(shù)據(jù)寫入外部的物理存儲設(shè)備。

(5)支持發(fā)布/訂閱浆洗。

(6)支持Lua腳本催束。

(7)支持分布式鎖 在分布式系統(tǒng)中,如果不同的節(jié)點需要訪同到一個資源伏社,往往需要通過互斥機制來防止彼此干擾抠刺,并且保證數(shù)據(jù)的一致性。在這種情況下摘昌,需要使用到分布式鎖速妖。分布式鎖和Java的鎖用于實現(xiàn)不同線程之間的同步訪問,原理上是類似的聪黎。

(8)支持原子操作和事務(wù)Redis事務(wù)是一組命令的集合罕容。一個事務(wù)中的命令要么都執(zhí)行,要么都不執(zhí)行。如果命令在運行期間出現(xiàn)錯誤锦秒,不會自動回滾露泊。

(9)支持主-從(Master-Slave)復(fù)制與高可用(Redis Sentinel)集群(3.0版本以上)

(10)支持管道Redis管道是指客戶端可以將多個命令一次性發(fā)送到服務(wù)器,然后由服務(wù)器一次性返回所有結(jié)果脂崔。管道技術(shù)的優(yōu)點是:在批量執(zhí)行命令的應(yīng)用場景中滤淳,可以大大減少網(wǎng)絡(luò)傳輸?shù)拈_銷,提高性能砌左。



ZooKeeper的核心優(yōu)勢是脖咐,實現(xiàn)了分布式環(huán)境的數(shù)據(jù)一致性,簡單地說:每時每刻我們訪問ZooKeeper的樹結(jié)構(gòu)時汇歹,不同的節(jié)點返回的數(shù)據(jù)都是一致的屁擅。也就是說,對ZooKeeper進行數(shù)據(jù)訪問時产弹,無論是什么時間派歌,都不會引起臟讀、重復(fù)讀痰哨。



read系統(tǒng)調(diào)用胶果,并不是直接從物理設(shè)備把數(shù)據(jù)讀取到內(nèi)存中;write系統(tǒng)調(diào)用斤斧,也不是直接把數(shù)據(jù)寫入到物理設(shè)備早抠。上層應(yīng)用無論是調(diào)用操作系統(tǒng)的read,還是調(diào)用操作系統(tǒng)的write撬讽,都會涉及緩沖區(qū)蕊连。具體來說,調(diào)用操作系統(tǒng)的read游昼,是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到進程緩沖區(qū)甘苍;而write系統(tǒng)調(diào)用,是把數(shù)據(jù)從進程緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū)烘豌。



有了內(nèi)存緩沖區(qū)载庭,上層應(yīng)用使用read系統(tǒng)調(diào)用時,僅僅把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到上層應(yīng)用的緩沖區(qū)(進程緩沖區(qū))廊佩;上層應(yīng)用使用write系統(tǒng)調(diào)用時囚聚,僅僅把數(shù)據(jù)從進程緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū)中。



在Java服務(wù)器端罐寨,完成一次socket請求和響應(yīng),完整的流程如下:

· 客戶端請求:Linux通過網(wǎng)卡讀取客戶端的請求數(shù)據(jù)序矩,將數(shù)據(jù)讀取到內(nèi)核緩沖區(qū)鸯绿。

· 獲取請求數(shù)據(jù):Java服務(wù)器通過read系統(tǒng)調(diào)用,從Linux內(nèi)核緩沖區(qū)讀取數(shù)據(jù),再送入Java進程緩沖區(qū)瓶蝴。

· 服務(wù)器端業(yè)務(wù)處理:Java服務(wù)器在自己的用戶空間中處理客戶端的請求毒返。

· 服務(wù)器端返回數(shù)據(jù):Java服務(wù)器完成處理后,構(gòu)建好的響應(yīng)數(shù)據(jù)舷手,將這些數(shù)據(jù)從用戶緩沖區(qū)寫入內(nèi)核緩沖區(qū)拧簸。這里用到的是write系統(tǒng)調(diào)用。

· 發(fā)送給客戶端:Linux內(nèi)核通過網(wǎng)絡(luò)IO男窟,將內(nèi)核緩沖區(qū)中的數(shù)據(jù)寫入網(wǎng)卡盆赤,網(wǎng)卡通過底層的通信協(xié)議,會將數(shù)據(jù)發(fā)送給目標客戶端歉眷。



阻塞IO牺六,指的是需要內(nèi)核IO操作徹底完成后,才返回到用戶空間執(zhí)行用戶的操作汗捡。阻塞指的是用戶空間程序的執(zhí)行狀態(tài)淑际。傳統(tǒng)的IO模型都是同步阻塞IO。在Java中扇住,默認創(chuàng)建的socket都是阻塞的



在Java應(yīng)用程序進程中春缕,默認情況下,所有的socket連接的IO操作都是同步阻塞IO(BlockingIO)



總之艘蹋,阻塞IO的特點是:在內(nèi)核進行IO執(zhí)行的兩個階段锄贼,用戶線程都被阻塞了。



阻塞IO的缺點是:一般情況下簿训,會為每個連接配備一個獨立的線程咱娶;反過來說,就是一個線程維護一個連接的IO操作强品。在并發(fā)量小的情況下膘侮,這樣做沒有什么問題携栋。但是竿开,當在高并發(fā)的應(yīng)用場景下努酸,需要大量的線程來維護大量的網(wǎng)絡(luò)連接像屋,內(nèi)存乒验、線程切換開銷會非常巨大麻献。因此曙博,基本上阻塞IO模型在高并發(fā)應(yīng)用場景下是不可用的畔塔。



異步IO模型的特點:在內(nèi)核等待數(shù)據(jù)和復(fù)制數(shù)據(jù)的兩個階段晓淀,用戶線程都不是阻塞的所袁。用戶線程需要接收內(nèi)核的IO操作完成的事件,或者用戶線程需要注冊一個IO操作完成的回調(diào)函數(shù)凶掰。正因為如此燥爷,異步IO有的時候也被稱為信號驅(qū)動IO蜈亩。



對于高并發(fā)、高負載的應(yīng)用前翎,就必須要調(diào)整這個系統(tǒng)參數(shù)稚配,以適應(yīng)處理并發(fā)處理大量連接的應(yīng)用場景「刍可以通過ulimit來設(shè)置這兩個參數(shù)道川。方法如下:

ulimit -n? 1000000000

在上面的命令中,n的設(shè)置值越大立宜,可以打開的文件句柄數(shù)量就越大冒萄。建議以root用戶來執(zhí)行此命令。


終極解除Linux系統(tǒng)的最大文件打開數(shù)量的限制赘理,可以通過編輯Linux的極限配置文件/etc/security/limits.conf來解決宦言,修改此文件,加入如下內(nèi)容:

soft? nofile? 1000000

hard nofile 1000000

soft nofile表示軟性極限商模,hard nofile表示硬性極限奠旺。


如果想永久地把設(shè)置值保存下來,可以編輯/etc/rc.local開機啟動文件施流,在文件中添加如下內(nèi)容:

ulimit -SHn? 1000000


Java NIO由以下三個核心組件組成:· Channel(通道)· Buffer(緩沖區(qū))· Selector(選擇器)需要強調(diào)的是:Buffer類是一個非線程安全類响疚。



NIO的Buffer(緩沖區(qū))本質(zhì)上是一個內(nèi)存塊,既可以寫入數(shù)據(jù)瞪醋,也可以從中讀取數(shù)據(jù)忿晕。NIO的Buffer類,是一個抽象類银受,位于java.nio包中践盼,其內(nèi)部是一個內(nèi)存塊(數(shù)組)。







在調(diào)用allocate方法分配內(nèi)存宾巍、返回了實例對象后咕幻,緩沖區(qū)實例對象處于寫模式,可以寫入對象顶霞。要寫入緩沖區(qū)肄程,需要調(diào)用put方法。put方法很簡單选浑,只有一個參數(shù)蓝厌,即為所需要寫入的對象。不過古徒,寫入的數(shù)據(jù)類型要求與緩沖區(qū)的類型保持一致拓提。



對flip()方法的從寫入到讀取轉(zhuǎn)換的規(guī)則,詳細的介紹如下:

首先隧膘,設(shè)置可讀的長度上限limit代态。將寫模式下的緩沖區(qū)中內(nèi)容的最后寫入位置position值狐粱,作為讀模式下的limit上限值。

其次胆数,把讀的起始位置position的值設(shè)為0,表示從頭開始讀互墓。最后必尼,清除之前的mark標記,因為mark保存的是寫模式下的臨時位置篡撵。在讀模式下判莉,如果繼續(xù)使用舊的mark標記,會造成位置混亂育谬。





調(diào)用flip方法券盅,將緩沖區(qū)切換成讀取模式。這時膛檀,可以開始從緩沖區(qū)中進行數(shù)據(jù)讀取了锰镀。讀數(shù)據(jù)很簡單,調(diào)用get方法咖刃,每次從position的位置讀取一個數(shù)據(jù)泳炉,并且進行相應(yīng)的緩沖區(qū)屬性的調(diào)整。



已經(jīng)讀完的數(shù)據(jù)嚎杨,如果需要再讀一遍花鹅,可以調(diào)用rewind()方法。rewind()也叫倒帶枫浙,就像播放磁.



Buffer.mark()方法的作用是將當前position的值保存起來刨肃,放在mark屬性中,讓mark屬性記住這個臨時位置箩帚;之后真友,可以調(diào)用Buffer.reset()方法將mark的值恢復(fù)到position中。



在讀取模式下膏潮,調(diào)用clear()方法將緩沖區(qū)切換為寫入模式锻狗。此方法會將position清零,limit設(shè)置為capacity最大容量值焕参,可以一直寫入轻纪,直到緩沖區(qū)寫滿。



總體來說叠纷,使用Java NIO Buffer類的基本步驟如下:

(1)使用創(chuàng)建子類實例對象的allocate()方法刻帚,創(chuàng)建一個Buffer類的實例對象。

(2)調(diào)用put方法涩嚣,將數(shù)據(jù)寫入到緩沖區(qū)中崇众。

(3)寫入完成后掂僵,在開始讀取數(shù)據(jù)前,調(diào)用Buffer.flip()方法顷歌,將緩沖區(qū)轉(zhuǎn)換為讀模式锰蓬。

(4)調(diào)用get方法,從緩沖區(qū)中讀取數(shù)據(jù)眯漩。

(5)讀取完成后芹扭,調(diào)用Buffer.clear() 或Buffer.compact()方法,將緩沖區(qū)轉(zhuǎn)換為寫入模式赦抖。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舱卡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子队萤,更是在濱河造成了極大的恐慌轮锥,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件要尔,死亡現(xiàn)場離奇詭異舍杜,居然都是意外死亡,警方通過查閱死者的電腦和手機赵辕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門蝴簇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人匆帚,你說我怎么就攤上這事熬词。” “怎么了吸重?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵互拾,是天一觀的道長。 經(jīng)常有香客問我嚎幸,道長颜矿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任嫉晶,我火速辦了婚禮骑疆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘替废。我一直安慰自己箍铭,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布椎镣。 她就那樣靜靜地躺著诈火,像睡著了一般。 火紅的嫁衣襯著肌膚如雪状答。 梳的紋絲不亂的頭發(fā)上冷守,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天刀崖,我揣著相機與錄音,去河邊找鬼拍摇。 笑死亮钦,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的充活。 我是一名探鬼主播或悲,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼堪唐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起翎蹈,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤淮菠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后荤堪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體合陵,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年澄阳,在試婚紗的時候發(fā)現(xiàn)自己被綠了拥知。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡碎赢,死狀恐怖低剔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肮塞,我是刑警寧澤襟齿,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站枕赵,受9級特大地震影響猜欺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拷窜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一开皿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧篮昧,春花似錦赋荆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疚颊,卻和暖如春狈孔,著一層夾襖步出監(jiān)牢的瞬間信认,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工均抽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嫁赏,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓油挥,卻偏偏與公主長得像潦蝇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子深寥,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354