Tomcat
配置:server.xml包括頂級(jí)組件server:1個(gè)Tomcat實(shí)例啤贩;容器組件:service:關(guān)聯(lián)多個(gè)connector和1個(gè)engine咆蒿;engine:通過connector接收請求,處理請求深胳,轉(zhuǎn)發(fā)請求到對(duì)應(yīng)的host或详;host:虛擬主機(jī)艳丛;context:應(yīng)用程序,指定webapp路徑涝登;連接器組件connector:指定端口接收請求雄家;被嵌套類組件:Valve:閥門,發(fā)送到webapp前攔截請求胀滚,實(shí)現(xiàn)如日志趟济、IP控制等;realm:關(guān)聯(lián)一個(gè)用戶認(rèn)證庫蛛淋,實(shí)現(xiàn)認(rèn)證和授權(quán)咙好,包括UserDatabaseRealm使用JNDI自定義、MemoryRealm使用tomcat-users.xml褐荷、JDBCRealm使用JDBC鏈接數(shù)據(jù)庫勾效;
優(yōu)化:安全優(yōu)化:普通用戶啟動(dòng)、SHUTDOWN端口禁telnet、禁用AJP連接层宫、刪除多余的Root目錄避免漏洞杨伙;性能優(yōu)化:禁止DNS查詢(Connector配置enableLookups=false)、JVM調(diào)優(yōu)(catalina.sh增加JAVA_OPTS)萌腿、使用線程池(定義線程池Executor在Connector中使用)限匣、使用NIO(Connector中配置protocol:bio/nio/nio2/apr);
實(shí)現(xiàn)原理:connector通過Socket接收請求毁菱,將Socket請求封裝成HttpRequest請求并傳給Container米死;Container封裝和管理Servlet,處理請求贮庞,并返回HttpResponse給connector峦筒;connector將HttpResponse轉(zhuǎn)換成Socket返回給客戶端;
Connector:通過不同的ProtocolHandler實(shí)現(xiàn)窗慎,每個(gè)ProtocolHandler包括Endpoint(處理Socket連接)物喷、Processor(Socket轉(zhuǎn)HttpRequest)、Adapter(適配Http請求到Servlet容器)遮斥;
Container:包括engine峦失、host站點(diǎn)、context應(yīng)用术吗、wrapper單個(gè)Servlet尉辑;通過Pipeline-Value責(zé)任鏈模式(每1層容器就是1個(gè)Pipeline,每1層有多個(gè)實(shí)現(xiàn)類即Value)實(shí)現(xiàn)不同層容器的調(diào)用藐翎;每一層最后執(zhí)行Base類(StandardXXValue)材蹬,再由BaseValue類調(diào)用下一層;執(zhí)行順序:EnginePipelineValue多個(gè)吝镣、StandardEngineValue堤器、HostPipelineValue多個(gè)、StandardHostValue末贾、ContextPipelineValue多個(gè)闸溃、StandardContextValue、WrapperPipelineValue多個(gè)拱撵、StandardWrapperValue(最后創(chuàng)建FilterChain辉川,包含匹配的所有Filter和Servlet)、Filter.doFilter/Servlet.service多個(gè)拴测;
責(zé)任鏈模式:兩種實(shí)現(xiàn):Pipeline-Valve(Pipeline管道和Valve閥門乓旗,單鏈表實(shí)現(xiàn),invoke)和過濾器鏈(FilterChain和Filter集索,數(shù)組實(shí)現(xiàn)屿愚,doFilter)汇跨;
Servlet容器:容器管理Servlet的生命周期(初始化init、調(diào)用service和銷毀destroy)妆距,Tomcat是一個(gè)Servlet容器穷遂;Web服務(wù)器收到Servlet請求時(shí)會(huì)交給Servlet容器處理;Tomcat也可以做Web服務(wù)器娱据,性能較差蚪黑;
Nginx
作用:Http服務(wù)器、反向代理服務(wù)器中剩、郵件服務(wù)器忌穿、負(fù)載均衡、Web緩存(動(dòng)靜分離咽安,作為靜態(tài)資源的CDN)伴网;
配置:每個(gè)配置項(xiàng)分號(hào)結(jié)束;全局配置:user(用戶用戶組妆棒,默認(rèn)nobody)、worker_processes(進(jìn)程數(shù)沸伏,默認(rèn)1)糕珊、pid(進(jìn)程文件地址)、error_log(日志路徑級(jí)別)毅糟;events配置:accept_mutex(網(wǎng)絡(luò)連接序列化红选,防止驚群)、multi_accept(一個(gè)進(jìn)程同時(shí)接收多個(gè)連接姆另,默認(rèn)off)喇肋、use epoll(事件驅(qū)動(dòng)模型)、worker_connections(每個(gè)進(jìn)程最大連接數(shù))迹辐;http配置:全局參數(shù)(sendfile蝶防、keepalive_timeout、error_page明吩、upstream服務(wù)器配置间学、日志配置)、多個(gè)server配置印荔;server配置:主要配置location低葫;location配置:proxy_pass、deny的IP仍律、allow的IP嘿悬;內(nèi)置參數(shù):$remote_addr、$remote_user水泉、$request等善涨;
驚群現(xiàn)象:一個(gè)網(wǎng)路連接到來窒盐,多個(gè)睡眠的進(jìn)程被同時(shí)叫醒,但只有一個(gè)進(jìn)程能獲得鏈接躯概,這樣會(huì)影響系統(tǒng)性能登钥;通過accept_mutex解決;
負(fù)載均衡策略:內(nèi)置策略:輪詢(默認(rèn))娶靡、加權(quán)輪詢(處理1次連接則權(quán)重減1重新排序牧牢,所有機(jī)器down后重置所有機(jī)器的狀態(tài))、IP hash(經(jīng)過20次hash仍找不到可用的機(jī)器時(shí)退化成輪詢)姿锭、least_conn(把請求轉(zhuǎn)發(fā)給連接數(shù)較少的后端服務(wù)器)塔鳍;擴(kuò)展策略:fair(根據(jù)服務(wù)器響應(yīng)時(shí)間判斷負(fù)載,選出負(fù)載最輕的機(jī)器)呻此、url_hash轮纫、一致性hash;upstream配置參數(shù):ip_hash焚鲜、least_conn掌唾、weight(加權(quán)輪詢的權(quán)重)、backup(標(biāo)記備份服務(wù)器忿磅,主服務(wù)器掛掉才會(huì)處理請求)糯彬、down(標(biāo)記服務(wù)器永久停機(jī))、max_fails/fail_timeout/fail_time(fail_timeout時(shí)間內(nèi)失敗了max_fails次則認(rèn)為服務(wù)器停機(jī)葱她,停機(jī)時(shí)間為fail_time撩扒,默認(rèn)10s);
動(dòng)靜分離:靜態(tài)資源(HTML吨些,JavaScript搓谆,CSS,img等)部署在單獨(dú)的nginx豪墅,動(dòng)態(tài)資源(jsp泉手、do)部署在tomcat,提高用戶訪問靜態(tài)代碼的速度但校,降低對(duì)后臺(tái)應(yīng)用訪問螃诅;通過反向代理nginx轉(zhuǎn)發(fā)到靜態(tài)服務(wù)器nginx和動(dòng)態(tài)服務(wù)器tomcat;
工作原理:Nginx由內(nèi)核和模塊(靜態(tài)編譯状囱,自動(dòng)加載)組成术裸;模塊從結(jié)構(gòu)上分:核心模塊(http、event亭枷、mail)袭艺、基礎(chǔ)模塊(access、proxy叨粘、fastcgi猾编、rewrite)瘤睹、第三方模塊;模塊從功能上分:Handlers答倡、Filters轰传、Proxies;請求響應(yīng)過程:核心模塊接收請求通過配置文件找到location再由location中的指令找到模塊處理瘪撇、根據(jù)配置選擇一個(gè)handler處理請求获茬、多個(gè)Filter處理請求、響應(yīng)客戶端倔既;
進(jìn)程模型:單工作進(jìn)程:master+1個(gè)worker(單線程)恕曲;多工作進(jìn)程:master+多個(gè)worker(1個(gè)主線程);master進(jìn)程:接收CLI信號(hào)渤涌、向worker發(fā)送信號(hào)佩谣、監(jiān)控worker狀態(tài)、實(shí)現(xiàn)重啟实蓬、平滑升級(jí)茸俭、配置加載,不處理網(wǎng)絡(luò)業(yè)務(wù)事件安皱;執(zhí)行reload命令:啟動(dòng)新nginx進(jìn)程向master發(fā)送信號(hào)瓣履、master重新加載配置,啟動(dòng)新的worker练俐,通知老的worker處理完后退出;worker進(jìn)程:獨(dú)立平等冕臭,從master進(jìn)程fork腺晾,通過搶互斥鎖,注冊listenfd讀事件實(shí)現(xiàn)一個(gè)請求只有一個(gè)work處理辜贵;
高性能實(shí)現(xiàn):多進(jìn)程模型中多worker進(jìn)程獨(dú)立不加鎖悯蝉,沒有鎖的開銷;master自動(dòng)啟動(dòng)新的worker代替異常退出的worker托慨;異步非阻塞:每個(gè)worker只有1個(gè)主線程鼻由,通過異步非阻塞可同時(shí)處理大量請求哨查;
事件驅(qū)動(dòng)模型:Nginx響應(yīng)和處理Web請求的過程基于事件驅(qū)動(dòng)模型的西雀,包含事件收集器允坚、事件發(fā)送器和事件處理器欺矫;事件發(fā)送器每傳遞過來一個(gè)請求仙辟,目標(biāo)對(duì)象就將其放入一個(gè)待處理事件的列表涨缚,使用非阻塞I/O方式調(diào)用事件處理器來處理該請求服猪;事件驅(qū)動(dòng)處理庫又被稱為多路IO復(fù)用方法饼拍;select/poll:創(chuàng)建一個(gè)待處理事件列表(一個(gè)進(jìn)程所打開的文件描述符有限)彬犯,然后把這個(gè)列表發(fā)給內(nèi)核向楼,再去輪詢檢查這個(gè)列表查吊,以判斷事件是否發(fā)生,select對(duì)讀湖蜕、寫逻卖、異常創(chuàng)建3個(gè)集合分別輪詢,poll只創(chuàng)建一個(gè)集合昭抒,每個(gè)包含讀评也、寫、異常3個(gè)事件戈鲁,一次輪詢同時(shí)檢查3個(gè)事件仇参,Windows不支持;epoll:把事件列表的管理交給內(nèi)核婆殿,由內(nèi)核主動(dòng)通知進(jìn)程事件的發(fā)生诈乒,進(jìn)程不再輪詢,支持一個(gè)進(jìn)程打開大數(shù)目的socket描述符(FD)婆芦,IO效率不隨FD數(shù)目增加而線性下降(因?yàn)閮?nèi)核只通知活動(dòng)的FD)怕磨;rtsig:實(shí)時(shí)信號(hào)Real-Time Signal,進(jìn)程通過內(nèi)核建立一個(gè)rtsig隊(duì)列用于存放標(biāo)記事件發(fā)生(客戶端請求)的信號(hào)消约,每個(gè)事件發(fā)生時(shí)肠鲫,系統(tǒng)內(nèi)核就會(huì)產(chǎn)生一個(gè)信號(hào)存放到rtsig隊(duì)列中等待工作進(jìn)程的處理;kqueue:BSD平臺(tái)中使用或粮,類似epoll导饲;/dev/poll:主要用于Solaris,通過將要監(jiān)視的文件描述符加入虛擬設(shè)備/dev/poll獲得事件通知氯材;
性能優(yōu)化:worker_processes(同CPU核心數(shù))渣锦、worker_rlimit_nofile(最大打開文件數(shù),同Linux)氢哮、事件處理模型(use epoll袋毙、worker_connections、multi_accept)冗尤、高效文件傳輸(sendfile on听盖、tcp_nopush on)、各種連接超時(shí)時(shí)間裂七、gzip調(diào)優(yōu)皆看、expires緩存調(diào)優(yōu)、防盜鏈(通過校驗(yàn)referer碍讯,防止其他網(wǎng)站盜用占用帶寬)悬蔽、Linux內(nèi)核優(yōu)化、文件描述符(ulimit)捉兴;
Mybatis
概念:半ORM框架(需要自己寫SQL)蝎困,內(nèi)部封裝了JDBC來連接數(shù)據(jù)庫(數(shù)據(jù)庫兼容性較好)录语,可通過XML和注解完成映射和配置;缺點(diǎn):SQL編寫工作量大禾乘,且不能移植澎埠,遷移數(shù)據(jù)庫需要重新寫;
使用:Mapper接口:接口全限定名就是XML的namespace始藕,接口方法就是XML的SQL ID蒲稳,通過接口和方法定位到SQL,所以方法不能重載伍派;每個(gè)select/update等語句被解析成MapperStatement對(duì)象江耀,使用JDK動(dòng)態(tài)代理為Mapper接口生成代理對(duì)象撬讽,調(diào)用對(duì)應(yīng)的MapperStatement執(zhí)行SQL垮刹;分頁實(shí)現(xiàn):通過?RowBounds 對(duì)象進(jìn)行內(nèi)存分頁;物理分頁需要自己寫SQL碳抄;或者通過分頁插件(自定義分頁插件晾腔,攔截SQL舌稀,根據(jù)數(shù)據(jù)庫方言重寫SQL);封裝執(zhí)行結(jié)果:SQL列名和對(duì)象屬性映射灼擂,通過反射創(chuàng)建對(duì)象并賦值壁查;常用標(biāo)簽:select、insert剔应、update睡腿、delete、resultMap峻贮、parameterMap嫉到、sql、include月洛、where、foreach孽锥、if嚼黔、choose、when惜辑、otherwise唬涧;#{}預(yù)編譯,${}替換字符串盛撑;
關(guān)聯(lián)查詢:聯(lián)合查詢碎节,resultMap中通過association(一對(duì)一)/collection(一對(duì)多)配置字段映射;或者嵌套查詢抵卫,resultMap中通過association/collection通過配置select指定查詢ID實(shí)現(xiàn)狮荔;
延遲加載:僅支持 association和collection關(guān)聯(lián)集合對(duì)象的延遲加載胎撇,設(shè)置lazyLoadingEnabled=true,內(nèi)部通過Cglib創(chuàng)建代理對(duì)象殖氏,攔截對(duì)應(yīng)的get方法晚树,如果為空則調(diào)用對(duì)應(yīng)的SQL查詢結(jié)果再set;
緩存:一級(jí)緩存:HashMap實(shí)現(xiàn)雅采,默認(rèn)打開爵憎,作用域?yàn)镾QLSession,緩存失效:Session關(guān)閉婚瓜、使用不同的SQLSession宝鼓、查詢條件不同,使用了修改操作巴刻、手動(dòng)刷新緩存愚铡,分布式時(shí)多個(gè)SQLSession會(huì)導(dǎo)致臟數(shù)據(jù),和Spring集成時(shí)不支持一級(jí)緩存冈涧;二級(jí)緩存:可自定義存儲(chǔ)如Ehcache茂附,默認(rèn)關(guān)閉,作用域?yàn)镸apper NameSpace督弓,不同SQLSession可共享营曼,多表查詢時(shí)容易臟數(shù)據(jù),可在Mapper中配置cache或配置每個(gè)語句的緩存愚隧;查詢順序:二級(jí)緩存蒂阱、一級(jí)緩存、數(shù)據(jù)庫狂塘;分布式時(shí)不能使用录煤,會(huì)有臟數(shù)據(jù),一般使用Redis實(shí)現(xiàn)荞胡;
插件:又稱攔截器妈踊,采用責(zé)任鏈模式,通過JDK動(dòng)態(tài)代理泪漂,攔截指定方法廊营,調(diào)用InvocationHandler實(shí)現(xiàn);支持?jǐn)r截ParameterHandler(SQL參數(shù)處理)萝勤、ResultSetHandler(結(jié)果集處理)露筒、StatementHandler(語句構(gòu)建處理,執(zhí)行SQL敌卓,實(shí)現(xiàn)一級(jí)緩存)慎式、Executor(執(zhí)行器方法,調(diào)用StatementHandler,處理二級(jí)緩存)這4種接口的插件瘪吏;編寫插件:實(shí)現(xiàn)Mybatis的Interceptor接口并復(fù)寫 intercept()方法癣防,然后在給插件編寫注解,指定要攔截哪一個(gè)接口的哪些方法即可肪虎,在配置文件中配置編寫的插件劣砍;
核心類:SqlSession(頂層API,數(shù)據(jù)庫會(huì)話)扇救、Executor(包括SimpleExecutor刑枝、ReuseExecutor重用PrepareStatement、BatchExecutor)迅腔、StatementHandler装畅、ParameterHandler 、ResultSetHandler 沧烈、TypeHandler(Java和Jdbc數(shù)據(jù)類型轉(zhuǎn)換)掠兄、MappedStatement (封裝XML的select等節(jié)點(diǎn))、SqlSource(動(dòng)態(tài)生成SQl) 锌雀、BoundSql(SQL和參數(shù)) 蚂夕、Configuration(配置信息);
Netty
作用:定制編解碼協(xié)議:可使用Netty實(shí)現(xiàn)自己的服務(wù)器(Http服務(wù)器腋逆、Redis婿牍、Ftp等,通過定制編解碼協(xié)議實(shí)現(xiàn))惩歉,理解:傳統(tǒng)Http原理:服務(wù)端創(chuàng)建ServerSocket并監(jiān)聽端口等脂、客戶端請求端口、服務(wù)器accept獲得客戶端Socket撑蚌、服務(wù)器端請求新線程處理(讀Socket上遥、解碼得到HttpRequest、處理并封裝HttpResponse争涌、編碼并寫Socket)粉楚;Http服務(wù)器的編解碼協(xié)議是Http,如果換成其他協(xié)議就成了其他類型的服務(wù)器亮垫;基于Java NIO進(jìn)行封裝:底層使用操作系統(tǒng)的支持(select解幼、epoll),對(duì)外提供一套易用的NIO接口包警,傳統(tǒng)的BIO:Socket的accept、read底靠、write操作都是阻塞的害晦;
粘包拆包:操作系統(tǒng)按字節(jié)流讀取導(dǎo)致Netty發(fā)送的數(shù)據(jù)到接收時(shí)格式不正確,字符串被拆開了;服務(wù)端拆包和客戶端粘包一一對(duì)應(yīng)壹瘟;Netty提供了拆包器可直接使用:基于字符串長度的鲫剿、基于分隔符的、基于行的稻轨,pipline.addLast使用拆包器灵莲;
零拷貝:傳統(tǒng)方式:4次拷貝4次切換,磁盤到內(nèi)核的readbuffer殴俱、內(nèi)核緩沖區(qū)到用戶緩沖區(qū)政冻、用戶緩沖區(qū)到內(nèi)核的socketbuffer、內(nèi)核socketbuffer到網(wǎng)卡接口线欲;Java的FileChannel.transferTo:省去第23步拷貝明场,數(shù)據(jù)從文件由DMA引擎拷貝到內(nèi)核readbuffer、接著DMA從內(nèi)核readbuffer將數(shù)據(jù)拷貝到網(wǎng)卡接口buffer李丰,沒有CPU參與苦锨,實(shí)現(xiàn)零拷貝;Netty實(shí)現(xiàn):bytebuffer使用直接內(nèi)存通過DMA發(fā)送到網(wǎng)卡趴泌,避免堆內(nèi)存的拷貝舟舒;使用組合bytebuffer通過保存引用避免多個(gè)bytebuffer的拷貝,使用了FileChannel的transferTo方法嗜憔;
Reactor線程模型:所有線程都是NIO線程秃励,單線程模型:1個(gè)Reactor線程(完成所有IO操作包括接收、分發(fā)和處理)痹筛,實(shí)現(xiàn):ServerBootstrap().group(NioEventLoopGroup)莺治;多線程模型:1個(gè)Reactor線程(負(fù)責(zé)接收)+多個(gè)Acceptor線程(線程池,負(fù)責(zé)處理)帚稠,實(shí)現(xiàn):ServerBootstrap().group(NioEventLoopGroup(1),NioEventLoopGroup)谣旁;主從模型:1個(gè)主Reactor線程(負(fù)責(zé)接收,只負(fù)責(zé)接入認(rèn)證滋早、握手等榄审,然后重新注冊到從Reactor)+多個(gè)從Reactor線程(線程池)+多個(gè)Acceptor線程(線程池,負(fù)責(zé)處理)杆麸,實(shí)現(xiàn):ServerBootstrap().group(NioEventLoopGroup,NioEventLoopGroup)搁进;
執(zhí)行流程:服務(wù)端:創(chuàng)建ServerBootStrap、綁定Reactor線程池NioEventLoopGroup昔头、綁定NioServerScoketChannel饼问、創(chuàng)建ChannelPipeline和handler、綁定并啟動(dòng)監(jiān)聽端口揭斧、當(dāng)輪訓(xùn)到準(zhǔn)備就緒的channel后由Reactor線程N(yùn)ioEventLoop執(zhí)行pipline中的方法最終調(diào)度并執(zhí)行channelHandler莱革;客戶端:創(chuàng)建BootStrap、綁定Reactor線程池EventLoopGroup、綁定NioSocketChannel盅视、創(chuàng)建ChannelPipeline和handler捐名、發(fā)起連接connect;
Redis
數(shù)據(jù)結(jié)構(gòu):String:key-value闹击,命令:get/set镶蹋、mset/mget(同時(shí)操作多個(gè))、setex(設(shè)置過期時(shí)間)赏半、setnx(不存在才設(shè)置)贺归;Hash:類似Map,key-filed-value除破,命令:hset/hget牧氮、hexists(判斷field是否存在)、hmset/hmget瑰枫、hkeys踱葛、hvals、hgetall光坝、hdel尸诽、hsetnx(field不存在才設(shè)置);list:列表List盯另,可重復(fù)性含,命令:lpush、lindex(獲取指定序號(hào)的值)鸳惯、lrange商蕴、lset(設(shè)置指定序號(hào)的值)、lpop(刪除第一個(gè))芝发、rpop(刪除最后一個(gè))绪商;set:集合,類似list辅鲸,無序可去重格郁,使用hash實(shí)現(xiàn),命令:sadd独悴、scard求長度例书、sdiff求2個(gè)集合的差集、sinter求交集刻炒、sunion求并集决采、srem刪除指定元素、spop隨機(jī)移除元素坟奥;zset:有序集合树瞭,分?jǐn)?shù)可重復(fù)暂幼,元素不可重復(fù),使用hash實(shí)現(xiàn)移迫,命令:zadd、zrange管行、zcount厨埋;
常用命令:save(同步保存磁盤)、bgsave(異步保存磁盤)捐顷、shundown(異步保存磁盤再關(guān)閉)荡陷、info(顯示服務(wù)器信息)、config(運(yùn)行時(shí)配置)迅涮、exists(判斷key存在)废赞、keys(正則查詢所有key)、del(刪除key)叮姑、type(key類型)唉地、ttl(Key的剩余時(shí)間)、expire(設(shè)置過期)传透、flushdb(刪除當(dāng)前庫的所有key)耘沼、flushall(刪除所有庫的所有key);
持久化:RDB:快照保存朱盐,默認(rèn)方式群嗤,將內(nèi)存數(shù)據(jù)保存到磁盤dump.rdb文件;保存時(shí)機(jī):根據(jù)規(guī)則定期保存(save設(shè)置兵琳,xx時(shí)間內(nèi)超過xx個(gè)Key被修改則保存)狂秘,手動(dòng)保存(執(zhí)行save或bgsave命令);原理:fork子進(jìn)程躯肌,由子進(jìn)程保存數(shù)據(jù)到臨時(shí)rdb文件者春,再替換原rdb文件;適合做備份但不能實(shí)時(shí)保存羡榴;AOF(Append Only File):追加寫碧查,每個(gè)修改命令追加到appendonly.aof文件中;保存時(shí)機(jī):執(zhí)行修改命令時(shí)或每秒一次可配置校仑;可實(shí)時(shí)保存忠售,寫較多時(shí)會(huì)降低性能;支持同時(shí)開啟RDB和AOF迄沫,系統(tǒng)重啟后會(huì)優(yōu)先使用AOF來恢復(fù)數(shù)據(jù)稻扬,這樣丟失的數(shù)據(jù)會(huì)最少;
通信協(xié)議:RESP是Redis序列化協(xié)議羊瘩,文本協(xié)議泰佳,實(shí)現(xiàn)簡單盼砍,性能極好,協(xié)議將傳輸?shù)慕Y(jié)構(gòu)數(shù)據(jù)分為5種最小單元類型逝她,單元結(jié)束時(shí)統(tǒng)一加上回車換行符號(hào)\r\n浇坐;單行字符串(+開頭)、多行字符串($開頭跟上字符串長度)黔宛、整數(shù)值(:開頭近刘,后跟整數(shù)的字符串形式)、錯(cuò)誤消息(-開頭)臀晃、數(shù)組(*開頭跟上數(shù)組長度)觉渴;
部署方式:單機(jī)模式,單節(jié)點(diǎn)讀寫使用徽惋;主從復(fù)制:1個(gè)master+n個(gè)slave案淋,master負(fù)責(zé)讀寫,slave從master復(fù)制數(shù)據(jù)险绘,只負(fù)責(zé)讀踢京,master/slave數(shù)據(jù)相同,slave降低master讀的壓力隆圆,無法保證高可用漱挚,沒有解決寫的壓力;哨兵模式:基于主從復(fù)制模式增加了n個(gè)哨兵服務(wù)器(單獨(dú)進(jìn)程渺氧,定時(shí)和主從服務(wù)器心跳獲取信息)旨涝,用于監(jiān)控主從服務(wù)器間的連接、通知管理員故障侣背、主服務(wù)器故障時(shí)轉(zhuǎn)移故障白华,實(shí)現(xiàn)了高可用,但切換要丟數(shù)據(jù)贩耐,沒有解決寫的壓力弧腥;集群代理模式:n個(gè)master+n個(gè)salve+n個(gè)哨兵,master層前使用第三方代理工具Twemproxy進(jìn)行代理潮太,維護(hù)成本高管搪,擴(kuò)展性差;集群模式:數(shù)據(jù)按Slot分段分別存儲(chǔ)在所有機(jī)器上铡买,每個(gè)Node分配一段Slot(0-16384)更鲁,Node退出或加入會(huì)已Slot為單位遷移數(shù)據(jù),分?jǐn)偭藢懖僮髌娉?jié)點(diǎn)間互相監(jiān)聽澡为、讀和寫,任務(wù)繁重景埃;
線程模型:單線程媒至,基于Reactor模式的文件事件處理器顶别;文件事件處理器監(jiān)聽多個(gè)客戶端的socket,并根據(jù)socket產(chǎn)生的事件選擇不同的事件處理器處理客戶端連接請求拒啰、命令請求和響應(yīng)請求驯绎;文件事件處理器包括多個(gè)客戶端連接的Socket、IO多路復(fù)用程序(監(jiān)聽Socket并放入隊(duì)列)谋旦、文件事件分派器(處理隊(duì)列中的Socket分派到處理器)条篷、事件處理器(應(yīng)答/命令請求/命令回復(fù)/主從復(fù)制處理器);高并發(fā)的原因:純內(nèi)存操作蛤织、非阻塞IO多路復(fù)用程序、單線程避免上下文切換帶來的CPU消耗鸿染;?
內(nèi)存策略:刪除策略:定期刪除(每隔100ms隨機(jī)抽取一部分設(shè)置了過期時(shí)間的key指蚜,若過期則刪除)、惰性刪除(獲取key時(shí)檢查涨椒,過期則刪除)摊鸡;淘汰策略:內(nèi)存滿時(shí)的策略,noeviction(默認(rèn)蚕冬,不淘汰免猾,寫時(shí)返回錯(cuò)誤)、allkeys-lru/volatile-lru(從所有key/設(shè)置了過期時(shí)間的key淘汰最近最少使用的)囤热、allkeys-random/volatile-random(隨機(jī)淘汰)猎提、allkeys-lfu/volatile-lfu(淘汰最近最少訪問的)、volatile-ttl(淘汰越早過期的)旁蔼;設(shè)置:maxmemory(最大使用內(nèi)存锨苏,不設(shè)或0則不限制)、maxmemory-policy(內(nèi)存淘汰策略)棺聊;Redis實(shí)現(xiàn)LRU:采用隨機(jī)采樣法伞租,每次抽取5個(gè)key淘汰最近最少使用的,每個(gè)key內(nèi)部增加最近訪問時(shí)間字段限佩;
事務(wù):執(zhí)行事務(wù):MULTI(開始事務(wù))葵诈、輸入N個(gè)命令(命令如FIFO隊(duì)列,不會(huì)馬上執(zhí)行)祟同、EXEC(執(zhí)行事務(wù)作喘,串行執(zhí)行隊(duì)列的多個(gè)命令);WATCH:樂觀鎖耐亏,執(zhí)行事務(wù)前設(shè)置需要觀察的多個(gè)key徊都,執(zhí)行事務(wù)時(shí)判斷若觀察的key被修改則事務(wù)失敗广辰;通過watched_keys字典實(shí)現(xiàn)暇矫,修改每個(gè)客戶端的REDIS_DIRTY_CAS字段主之,執(zhí)行事務(wù)時(shí)判斷該字段來決定是否執(zhí)行;Redis事務(wù)滿足ACID:A(執(zhí)行過程中不被中斷)李根、C(不支持回滾槽奕,入隊(duì)失敗則事務(wù)失敗,單條命令執(zhí)行錯(cuò)誤不影響事務(wù))房轿、I(單線程串行執(zhí)行)粤攒、D(RDB/AOF實(shí)現(xiàn));
緩存問題:緩存穿透:查詢的數(shù)據(jù)不存在囱持,會(huì)直接請求到數(shù)據(jù)庫夯接,解決:緩存空值,布隆過濾器纷妆;緩存擊穿:大量請求查詢的key正好失效如系統(tǒng)配置钻蔑,解決:互斥鎖(先取緩存再查庫再更新緩存)嵌莉、緩存標(biāo)識(shí)(提前識(shí)別過期key更新緩存)宛瞄;緩存雪崩:大量緩存key同時(shí)失效或宕機(jī)導(dǎo)致請求到數(shù)據(jù)庫寞忿,解決:redis集群、ehcache本地緩存际邻、分散key過期時(shí)間芯丧;
分布式鎖:通過setnx、expire加鎖世曾,get缨恒、del解鎖,通過lua腳本實(shí)現(xiàn)轮听;Spring提供RedisLockRegistry可操作分布式鎖API肿轨;
Redis槽位:Redis采用CRC16(key) mod 16384進(jìn)行Hash定位槽位,CRC16算法產(chǎn)生的hash值有16bit蕊程,該算法可以產(chǎn)生2^16-=65536個(gè)值椒袍,由于節(jié)點(diǎn)間通信定時(shí)發(fā)送心跳消息Ping Pong,消息中會(huì)帶有槽位信息藻茂,如果槽位太多就會(huì)導(dǎo)致心跳消息太大產(chǎn)生網(wǎng)絡(luò)擁塞驹暑,處于性能考慮槽位數(shù)沒有選擇65536二而是16384,Redis集群節(jié)點(diǎn)數(shù)也建議不超過1000辨赐;
Redis管道:管道用于一次打包多個(gè)命令發(fā)送給Redis執(zhí)行處理优俘,Redis之前完前會(huì)緩存命令結(jié)果再一次發(fā)送給客戶端;所以管道命令不能太多掀序,會(huì)耗內(nèi)存帆焕、增加客戶端等待時(shí)間、造成網(wǎng)絡(luò)擁塞不恭;原生的批處理命令mget等是原子的叶雹,管道非原子财饥;
Redis底層數(shù)據(jù)結(jié)構(gòu):簡單動(dòng)態(tài)字符串SDS(定義了長度、空閑長度折晦、數(shù)組钥星,比C原生字符串性能高)、鏈表(C沒提供满着,自己實(shí)現(xiàn)雙端鏈表谦炒,定義了長度等屬性方法)、字典(C沒提供风喇,哈希表底層實(shí)現(xiàn)宁改,采用拉鏈法解決哈希沖突,采用漸進(jìn)式Hash魂莫,分多次完成透且,并非一次對(duì)所有Hash)、跳躍表豁鲤;整數(shù)集合intset、壓縮列表鲸沮;
Redis使用Lua腳本:減少網(wǎng)絡(luò)開銷(將多個(gè)請求通過腳本的形式一次發(fā)送減少網(wǎng)絡(luò)時(shí)延)琳骡、原子操作(Redis會(huì)將整個(gè)腳本作為一個(gè)整體執(zhí)行,中間不會(huì)被其他命令插入)讼溺、復(fù)用(客戶端發(fā)送的腳步會(huì)永久存在redis中)楣号、實(shí)現(xiàn)事務(wù)(Redis中的腳本本身就是一種事務(wù),所以任何在事務(wù)里可以完成的事在腳本里面也能完成)怒坯;使用3個(gè)命令實(shí)現(xiàn):eval炫狱、evalsha、script load剔猿;
Kafka
高可用:通過副本實(shí)現(xiàn)视译,1個(gè)主題多個(gè)分區(qū),1個(gè)分區(qū)多個(gè)副本归敬,不同副本保存在不同broker酷含;副本同步ISR:每個(gè)分區(qū)維護(hù)自己的ISR(與leader保持同步的副本列表,定期消息同步汪茧,不同步則剔除)椅亚,寫入消息時(shí)先給leader,leader再同步的把消息同步給ISR內(nèi)的多個(gè)副本舱污,再提交呀舔,再異步的把消息同步給ISR外的副本;選舉leader:ZK創(chuàng)建臨時(shí)節(jié)點(diǎn)成功的為leader扩灯,先到先得媚赖,所有副本都不工作時(shí)等待ISR中第一個(gè)恢復(fù)的為leader或者所有副本中第一個(gè)答復(fù)的為leader霜瘪;
高性能:partiton機(jī)制:1個(gè)Topic有多個(gè)partiton,partiton分布在不同節(jié)點(diǎn)且存儲(chǔ)在本地文件夾且可在不同磁盤省古,1個(gè)partiton有多個(gè)segment粥庄,1個(gè)segment有1個(gè)數(shù)據(jù)和索引文件,從節(jié)點(diǎn)豺妓、磁盤惜互、文件上都可并發(fā),同時(shí)1個(gè)partiton只有1個(gè)消費(fèi)者線程琳拭,避免競爭训堆;ISR機(jī)制:可用性和一致性的動(dòng)態(tài)平衡,動(dòng)態(tài)復(fù)制白嘁,避免慢節(jié)點(diǎn)拖慢整體性能坑鱼;順序?qū)懘疟P:新消息順序?qū)懭胛募x消息通過offset順序讀絮缅,刪消息刪整個(gè)segment文件鲁沥,避免磁盤隨機(jī)寫;支持多磁盤:broker數(shù)據(jù)存儲(chǔ)支持配置多個(gè)磁盤路徑耕魄,不同分區(qū)數(shù)據(jù)盡量寫到不同路徑画恰;零拷貝:transferTo和transferFrom使用零拷貝讀寫文件;批處理:同一主題和分區(qū)的多條消息合并傳輸吸奴,并支持?jǐn)?shù)據(jù)壓縮允扇;高效的序列化:可自定義使用更高效的序列化方式;
持久化:1個(gè)分區(qū)1個(gè)目錄(topic名稱+分區(qū)序號(hào))包含多個(gè)segment文件则奥,segment文件包含1個(gè)index索引文件和1個(gè)log數(shù)據(jù)文件考润,offset命名;
選舉機(jī)制:Broker選舉Leader:創(chuàng)建ZK臨時(shí)節(jié)點(diǎn)读处,第一個(gè)創(chuàng)建成功則為leader糊治,后續(xù)節(jié)點(diǎn)注冊watch事件;broker退出會(huì)判斷是否存在副本leader罚舱,有則重新選舉并更新ISR俊戳;broker加入會(huì)判斷是否存在分區(qū)副本,有則同步馆匿;分區(qū)副本選舉Leader:創(chuàng)建時(shí)指定的或第一個(gè)副本為Leader抑胎;消費(fèi)者組選Leader:第一個(gè)為Leader;
其他:特點(diǎn):持久化渐北、高吞吐阿逃、低延遲、分布式、可容錯(cuò)恃锉、高擴(kuò)展搀菩;發(fā)送消息:確認(rèn)成功:0(不等broker確認(rèn))、1(leader確認(rèn)破托,異步同步)肪跋、-1(leader和ISR所有副本都確認(rèn));分區(qū)機(jī)制:順序輪詢分區(qū)(默認(rèn))土砂、隨機(jī)輪詢分區(qū)州既、按Key分區(qū);offset存儲(chǔ):老版默認(rèn)存儲(chǔ)在ZK萝映,新版默認(rèn)存儲(chǔ)在__consumer_offsets主題中吴叶,可配置;消費(fèi)者:1個(gè)分區(qū)只能被同1個(gè)消費(fèi)者組的1個(gè)線程消費(fèi)序臂,1個(gè)消費(fèi)者線程可同時(shí)消費(fèi)多個(gè)分區(qū)蚌卤;節(jié)點(diǎn):leader負(fù)責(zé)全部的讀寫,follower只負(fù)責(zé)備份不負(fù)責(zé)讀(區(qū)別于ZK的follower負(fù)責(zé)讀)奥秆;
Kafka事務(wù):場景包括:生產(chǎn)者發(fā)送多條消息可以封裝在一個(gè)事務(wù)中逊彭,形成一個(gè)原子操作;read-process-write模式:將消息消費(fèi)和生產(chǎn)封裝在一個(gè)事務(wù)中构订,形成一個(gè)原子操作侮叮;事務(wù)方法包括:init/begin/commit/abortTransactions;事務(wù)配置:Producer設(shè)置transactional.id鲫咽,Consumer設(shè)置isolation.level=read_committed和enable.auto.commit=false;事務(wù)實(shí)現(xiàn):使用2PC谷异,引入Tranaction Corordinator節(jié)點(diǎn)分尸;事務(wù)本質(zhì):將一組寫操作(如果有)對(duì)應(yīng)的消息與一組讀操作(如果有)對(duì)應(yīng)的Offset的更新進(jìn)行同樣的標(biāo)記(Transaction Marker)來實(shí)現(xiàn)事務(wù)中涉及的所有讀寫操作同時(shí)對(duì)外可見或同時(shí)對(duì)外不可見,只提供對(duì)Kafka本身的讀寫操作的事務(wù)性歹嘹,不提供包含外部系統(tǒng)的事務(wù)性箩绍;
MongoDb
特點(diǎn):C++編寫,無數(shù)據(jù)結(jié)構(gòu)限制(沒有表結(jié)構(gòu)概念尺上,每條記錄可以有不同結(jié)構(gòu))材蛛、完全的索引支持(支持單鍵/數(shù)據(jù)/全文索引等)、方便的冗余和擴(kuò)展(復(fù)制集怎抛、分片擴(kuò)展)卑吭、支持動(dòng)態(tài)查詢、自動(dòng)分片马绝、支持JS豆赏、支持故障恢復(fù);適用場景:持久化緩存、文檔化存儲(chǔ)和查詢掷邦、實(shí)時(shí)插入查詢白胀、大尺寸低價(jià)值的數(shù)據(jù)、高伸縮性的場景抚岗;不適合:高度事務(wù)性系統(tǒng)或杠、復(fù)雜的表級(jí)聯(lián)查詢;
概念:和關(guān)系數(shù)據(jù)庫概念映射:數(shù)據(jù)庫(同數(shù)據(jù)庫)宣蔚、集合(同表)向抢、文檔(同行,JSON格式)件已、字段(同列)笋额、索引(同索引)、主鍵(同主鍵篷扩,默認(rèn)_id為主鍵字段)兄猩;Journal:類似redo日志,用于數(shù)據(jù)故障恢復(fù)和持久化數(shù)據(jù)的鉴未,可通過批量提交提高寫入性能枢冤;32位系統(tǒng)默認(rèn)關(guān)閉;實(shí)現(xiàn)涉及磁盤文件:data file和journal file铜秆,內(nèi)存映射shared view和private view淹真;分析器:類似執(zhí)行計(jì)劃和慢查詢記錄;分析器級(jí)別:0-沒打開连茧;1-記錄超過閾值的查詢核蘸;2-記錄所有查詢;db.system.profile.find()查詢執(zhí)行信息啸驯;find().explain分析特定查詢客扎;BSON:Binary JSON,比JSON多支持一些數(shù)據(jù)類型罚斗,用于存儲(chǔ)文檔和數(shù)據(jù)傳輸徙鱼;namespace:數(shù)據(jù)庫名.集合名稱即為命名空間;更新操作不會(huì)立刻fsync到磁盤针姿,而是定時(shí)批量寫袱吆;MongoDb沒有使用鎖和回滾,類似MySQL MylSAM的自動(dòng)提交模式距淫;支持存儲(chǔ)過程绞绒,使用JS寫;GridFS:將大型文件存儲(chǔ)在MongoDB數(shù)據(jù)庫中的文件規(guī)范榕暇,可以將一個(gè)大文件分割成為多個(gè)較小的文檔处铛;MapReduce:相當(dāng)于Mysql中的"group by"饲趋,統(tǒng)計(jì)比較容易;
使用:啟動(dòng):手動(dòng)創(chuàng)建data/log/conf目錄撤蟆,創(chuàng)建mongodb.conf配置文件配置奕塑,啟動(dòng)時(shí)可指定配置文件路徑:mongod -f conf/mongodb.conf;通過客戶端連接:mongo ip:port家肯;自帶工具:mongo(客戶端程序龄砰,連接MongoDB)、mongod(服務(wù)端程序讨衣,啟動(dòng)管理MongoDB)换棚、mongodump/mongorestore(數(shù)據(jù)庫二進(jìn)制導(dǎo)入導(dǎo)出用于備份還原)、mongoimport/mongoexport(數(shù)據(jù)庫數(shù)據(jù)導(dǎo)入導(dǎo)出)反镇、mongostat(用于查看數(shù)據(jù)庫狀態(tài))固蚤、mongooplog(用于數(shù)據(jù)庫的操作記錄)、mongos(數(shù)據(jù)分片程序歹茶,支持?jǐn)?shù)據(jù)的橫向擴(kuò)展)夕玩、mongofiles(GridFS工具,內(nèi)建的分布式文件系統(tǒng))惊豺;常用命令:show dbs查看所有數(shù)據(jù)庫燎孟、use xx使用xx數(shù)據(jù)庫,不存在則創(chuàng)建尸昧、db.dropDatabase刪除數(shù)據(jù)庫揩页、show collections查看所有集合、db.集合名.insert/find/update/remove/drop/getIndexes/ensureIndex({json})插入/查詢/更新/刪除局/刪集合/查看索引/創(chuàng)建索引烹俗,集合不存在會(huì)自動(dòng)創(chuàng)建爆侣、find().count/skip/limit/sort對(duì)查詢結(jié)果統(tǒng)計(jì)總數(shù)/跳過前x項(xiàng)/返回指定條目/排序、db.createUser(創(chuàng)建用戶)幢妄、xx.explain(查看指令詳情)兔仰;
索引類型:_id索引(自動(dòng)創(chuàng)建)、單鍵索引(單一值的單字段創(chuàng)建索引)磁浇、多鍵索引(多值的單字段創(chuàng)建索引如數(shù)組字段)斋陪、復(fù)合索引(多字段創(chuàng)建索引)朽褪、過期索引(一段時(shí)間后會(huì)過期的索引置吓,時(shí)間字段才能創(chuàng)建,索引過期后相應(yīng)的數(shù)據(jù)會(huì)被刪除)缔赠、全文索引(對(duì)字符串與字符串?dāng)?shù)組創(chuàng)建全文可搜索的索引)衍锚、地理索引;索引屬性:name嗤堰、unique唯一性戴质、sparse稀疏性(沒有該字段則不對(duì)該行創(chuàng)建索引)度宦;
部署方案:主從(一主一從一主多從):主節(jié)點(diǎn)可讀可寫,記錄所有操作oplog告匠,從節(jié)點(diǎn)可讀不寫戈抄,定期從主節(jié)點(diǎn)同步數(shù)據(jù),主節(jié)點(diǎn)掛掉需要人工重新指定后专;副本集(支持自動(dòng)故障轉(zhuǎn)移的主從):主節(jié)點(diǎn)可讀可寫划鸽,掛掉后通過仲裁節(jié)點(diǎn)選舉一個(gè)副本節(jié)點(diǎn)作為主節(jié)點(diǎn),副本節(jié)點(diǎn)可讀不寫戚哎,同步數(shù)據(jù)裸诽,參與選主,仲裁節(jié)點(diǎn)無數(shù)據(jù)型凳,不參與選主丈冬,只投票,副本節(jié)點(diǎn)需為奇數(shù)甘畅;分片:將數(shù)據(jù)拆分并分散存放在不同機(jī)器上埂蕊,每個(gè)分片維護(hù)著一個(gè)數(shù)據(jù)集合的子集,支持自動(dòng)分片橄浓,包括分片服務(wù)器(mongod實(shí)例粒梦,可由副本集承擔(dān))、配置服務(wù)器(mongod 實(shí)例荸实,保存集群和分片源數(shù)據(jù))和路由服務(wù)器(客戶端連接入口匀们,路由客戶請求到對(duì)應(yīng)的分片服務(wù)器);