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