1.JVM 堆內(nèi)存和非堆內(nèi)存
堆和非堆內(nèi)存
按照官方的說法:“Java 虛擬機(jī)具有一個堆(Heap)骂澄,堆是運(yùn)行時數(shù)據(jù)區(qū)域想诅,所有類實例和數(shù)組的內(nèi)存均從此處分配。堆是在 Java 虛擬機(jī)啟動時創(chuàng)建的√┘眩”“在JVM中堆之外的內(nèi)存稱為非堆內(nèi)存(Non-heap memory)”。
JVM主要管理兩種類型的內(nèi)存:堆和非堆尘吗。
Heap memory Code Cache
Eden Space
Survivor Space
Tenured Gen
non-heap memory Perm Gen
native heap?(I guess)堆內(nèi)存
Java 虛擬機(jī)具有一個堆逝她,堆是運(yùn)行時數(shù)據(jù)區(qū)域,所有類實例和數(shù)組的內(nèi)存均從此處分配摇予。堆是在 Java 虛擬機(jī)啟動時創(chuàng)建的汽绢。對象的堆內(nèi)存由稱為垃圾回收器的自動內(nèi)存管理系統(tǒng)回收。
堆的大小可以固定侧戴,也可以擴(kuò)大和縮小宁昭。堆的內(nèi)存不需要是連續(xù)空間。非堆內(nèi)存
Java 虛擬機(jī)管理堆之外的內(nèi)存(稱為非堆內(nèi)存)酗宋。
Java 虛擬機(jī)具有一個由所有線程共享的方法區(qū)积仗。方法區(qū)屬于非堆內(nèi)存。它存儲每個類結(jié)構(gòu)蜕猫,如運(yùn)行時常數(shù)池寂曹、字段和方法數(shù)據(jù),以及方法和構(gòu)造方法的代碼回右。它是在 Java 虛擬機(jī)啟動時創(chuàng)建的隆圆。
方法區(qū)在邏輯上屬于堆,但 Java 虛擬機(jī)實現(xiàn)可以選擇不對其進(jìn)行回收或壓縮翔烁。與堆類似渺氧,方法區(qū)的大小可以固定,也可以擴(kuò)大和縮小蹬屹。方法區(qū)的內(nèi)存不需要是連續(xù)空間侣背。
除了方法區(qū)外白华,Java 虛擬機(jī)實現(xiàn)可能需要用于內(nèi)部處理或優(yōu)化的內(nèi)存,這種內(nèi)存也是非堆內(nèi)存贩耐。例如弧腥,JIT 編譯器需要內(nèi)存來存儲從 Java 虛擬機(jī)代碼轉(zhuǎn)換而來的本機(jī)代碼,從而獲得高性能潮太。幾個基本概念
PermGen space:全稱是Permanent Generation space管搪,即永久代。就是說是永久保存的區(qū)域,用于存放Class和Meta信息消别,Class在被Load的時候被放入該區(qū)域抛蚤,GC(Garbage Collection)應(yīng)該不會對PermGen space進(jìn)行清理,所以如果你的APP會LOAD很多CLASS的話寻狂,就很可能出現(xiàn)PermGen space錯誤岁经。
Heap space:存放Instance。
Java Heap分為3個區(qū)蛇券,Young即新生代缀壤,Old即老生代和Permanent。
Young保存剛實例化的對象纠亚。當(dāng)該區(qū)被填滿時塘慕,GC會將對象移到Old區(qū)。Permanent區(qū)則負(fù)責(zé)保存反射對象蒂胞。堆內(nèi)存分配
JVM初始分配的堆內(nèi)存由-Xms指定图呢,默認(rèn)是物理內(nèi)存的1/64;
JVM最大分配的堆內(nèi)存由-Xmx指定骗随,默認(rèn)是物理內(nèi)存的1/4蛤织。
默認(rèn)空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制鸿染;
空余堆內(nèi)存大于70%時指蚜,JVM會減少堆直到-Xms的最小限制。
因此服務(wù)器一般設(shè)置-Xms涨椒、-Xmx 相等以避免在每次GC 后調(diào)整堆的大小摊鸡。
說明:如果-Xmx 不指定或者指定偏小,應(yīng)用可能會導(dǎo)致java.lang.OutOfMemory錯誤蚕冬,此錯誤來自JVM免猾,不是Throwable的,無法用try…catch捕捉囤热。非堆內(nèi)存分配
- JVM使用-XX:PermSize設(shè)置非堆內(nèi)存初始值猎提,默認(rèn)是物理內(nèi)存的1/64;
- 由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小赢乓,默認(rèn)是物理內(nèi)存的1/4忧侧。
還有一說:MaxPermSize缺省值和-server -client選項相關(guān),-server選項下默認(rèn)MaxPermSize為64m牌芋,-client選項下默認(rèn)MaxPermSize為32m蚓炬。這個我沒有實驗。 - XX:MaxPermSize設(shè)置過小會導(dǎo)致java.lang.OutOfMemoryError: PermGen space 就是內(nèi)存益出躺屁。
- 為什么會內(nèi)存益出:
這一部分內(nèi)存用于存放Class和Meta的信息肯夏,Class在被 Load的時候被放入PermGen space區(qū)域,它和存放Instance的Heap區(qū)域不同犀暑。
GC(Garbage Collection)不會在主程序運(yùn)行期對PermGen space進(jìn)行清理驯击,所以如果你的APP會LOAD很多CLASS 的話,就很可能出現(xiàn)PermGen space錯誤。 - 這種錯誤常見在web服務(wù)器對JSP進(jìn)行pre compile的時候耐亏。
2.MySQL大數(shù)據(jù)量分頁查詢方法及其優(yōu)化
---方法1: 直接使用數(shù)據(jù)庫提供的SQL語句
---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 LIMIT M,N
---適應(yīng)場景: 適用于數(shù)據(jù)量較少的情況(元組百/千級)
---原因/缺點: 全表掃描,速度會很慢 且 有的數(shù)據(jù)庫結(jié)果集返回不穩(wěn)定(如某次返回1,2,3,另外的一次返回2,1,3). Limit限制的是從結(jié)果集的M位置處取出N條輸出,其余拋棄.
---方法2: 建立主鍵或唯一索引, 利用索引(假設(shè)每頁10條)**
---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 WHERE id_pk > (pageNum10) LIMIT M
---適應(yīng)場景: 適用于數(shù)據(jù)量多的情況(元組數(shù)上萬)
---原因: 索引掃描,速度會很快. 有朋友提出: 因為數(shù)據(jù)查詢出來并不是按照pk_id排序的徊都,所以會有漏掉數(shù)據(jù)的情況,只能方法3
---方法3: 基于索引再排序
---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 WHERE id_pk > (pageNum10) ORDER BY id_pk ASC LIMIT M
---適應(yīng)場景: 適用于數(shù)據(jù)量多的情況(元組數(shù)上萬). 最好ORDER BY后的列對象是主鍵或唯一所以,使得ORDERBY操作能利用索引被消除但結(jié)果集是穩(wěn)定的(穩(wěn)定的含義,參見方法1)
---原因: 索引掃描,速度會很快. 但MySQL的排序操作,只有ASC沒有DESC(DESC是假的,未來會做真正的DESC,期待...).
---方法4: 基于索引使用prepare(第一個問號表示pageNum广辰,第二個暇矫?表示每頁元組數(shù))**
---語句樣式: MySQL中,可用如下方法: PREPARE stmt_name FROM SELECT * FROM 表名稱 WHERE id_pk > (?* 择吊?) ORDER BY id_pk ASC LIMIT M
---適應(yīng)場景: 大數(shù)據(jù)量
---原因: 索引掃描,速度會很快. prepare語句又比一般的查詢語句快一點李根。
3.ThreadGroup
當(dāng)創(chuàng)建了好幾個線程的時候,很多線程的工作任務(wù)是類似或者一致的几睛,這樣我們就可以使用ThreadGroup來管理他們房轿,ThreadGroup可以隨時的獲取在他里面的線程的運(yùn)行狀態(tài),信息所森,或者一條命令關(guān)閉掉這個group里面的所有線程囱持。
4.SpringMVC與Struts2的區(qū)別及執(zhí)行流程
Struts2是一個基于MVC設(shè)計模式的Web應(yīng)用框架,它本質(zhì)上相當(dāng)于一個servlet必峰,在MVC設(shè)計模式中洪唐,Struts2作為控制器(Controller)來建立模型與視圖的數(shù)據(jù)交互 Struts2=struts1+webwork。
struts2的執(zhí)行流程:
1吼蚁、客戶端瀏覽器發(fā)出HTTP請求凭需。
2、根據(jù)web.xml配置肝匆,該請求被FilterDispatcher接收粒蜈。
3、根據(jù)struts.xml配置旗国,找到需要調(diào)用的Action類和方法枯怖, 并通過IoC方式,將值注入給Aciton能曾。
4度硝、Action調(diào)用業(yè)務(wù)邏輯組件處理業(yè)務(wù)邏輯肿轨,這一步包含表單驗證。
5蕊程、Action執(zhí)行完畢椒袍,根據(jù)struts.xml中的配置找到對應(yīng)的返回結(jié)果result,并跳轉(zhuǎn)到相應(yīng)頁面藻茂。
6驹暑、返回HTTP響應(yīng)到客戶端瀏覽器。
springmvc全稱是spring web mvc辨赐,是spring框架一部分优俘,是一個mvc的框架,和struts2一樣是一個表現(xiàn)層框架掀序。
springMVC的執(zhí)行流程:
1帆焕、 用戶發(fā)送請求至前端控制器DispatcherServlet
2、 DispatcherServlet收到請求調(diào)用HandlerMapping處理器映射器查找Handler不恭。
3视搏、 處理器映射器根據(jù)請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet县袱。
4浑娜、 DispatcherServlet通過HandlerAdapter處理器適配器調(diào)用處理器
5、 HandlerAdapter調(diào)用處理器Handler
6式散、 Handler執(zhí)行完成返回ModelAndView
7筋遭、 HandlerAdapter將Handler執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet
8、 DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器暴拄,ViewReslover根據(jù)邏輯視圖名解析View
9漓滔、 ViewReslover返回View
10、 DispatcherServlet對View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至request域)乖篷。
11响驴、 DispatcherServlet響應(yīng)用戶
Springmvc與struts2的本質(zhì)區(qū)別
1、springmvc入口是一個servlet前端控制器撕蔼,struts2入口是一個filter過濾器豁鲤。
2、struts2通過在action類中定義成員變量接收請求參數(shù)鲸沮,struts2只能使用多例模式管理action琳骡。
springmvc通過在controller方法中定義形參接收請求參數(shù),springmvc可以使用單例模式管理controller讼溺。
3楣号、springmvc是基于方法開發(fā)的,注解開發(fā)中使用requestMapping將url和方法進(jìn)行映射,如果根據(jù)url找到controller類的方法生成一個Handler處理器對象(只包括一個method)炫狱。
struts2是基于類開發(fā)藻懒,每個請求過來創(chuàng)建一個action實例,實例對象中有若干的方法视译。
開發(fā)中建議使用springmvc束析,springmvc方法更類似service業(yè)務(wù)方法。
4憎亚、Struts采用值棧存儲請求和響應(yīng)的數(shù)據(jù),通過OGNL存取數(shù)據(jù)弄慰, springmvc通過參數(shù)綁定器是將request請求內(nèi)容解析第美,并給方法形參賦值。
5陆爽、struts2和springmvc的速度是相當(dāng)?shù)氖餐捎趕truts2的漏洞較多,很多企業(yè)轉(zhuǎn)向使用springmvc了慌闭。
5.談?wù)勀銓truts的理解别威。
- struts是一個按MVC模式設(shè)計的Web層框架,其實它就是一個大大的servlet驴剔,這個Servlet名為ActionServlet省古,或是ActionServlet的子類。我們可以在web.xml文件中將符合某種特征的所有請求交給這個Servlet處理丧失,這個Servlet再參照一個配置文件(通常為/WEB-INF/struts-config.xml)將各個請求分別分配給不同的action去處理豺妓。
一個擴(kuò)展知識點:struts的配置文件可以有多個,可以按模塊配置各自的配置文件布讹,這樣可以防止配置文件的過度膨脹琳拭;
2.ActionServlet把請求交給action去處理之前,會將請求參數(shù)封裝成一個formbean對象(就是一個java類描验,這個類中的每個屬性對應(yīng)一個請求參數(shù))白嘁,封裝成一個什么樣的formbean對象呢?看配置文件膘流。
3.要說明的是絮缅, ActionServlet把formbean對象傳遞給action的execute方法之前,可能會調(diào)用formbean的validate方法進(jìn)行校驗呼股,只有校驗通過后才將這個formbean對象傳遞給action的execute方法盟蚣,否則,它將返回一個錯誤頁面卖怜,這個錯誤頁面由input屬性指定屎开,(看配置文件)作者為什么將這里命名為input屬性,而不是error屬性,我們后面結(jié)合實際的運(yùn)行效果進(jìn)行分析奄抽。
4.action執(zhí)行完后要返回顯示的結(jié)果視圖蔼两,這個結(jié)果視圖是用一個ActionForward對象來表示的,actionforward對象通過struts-config.xml配置文件中的配置關(guān)聯(lián)到某個jsp頁面逞度,因為程序中使用的是在struts-config.xml配置文件為jsp頁面設(shè)置的邏輯名额划,這樣可以實現(xiàn)action程序代碼與返回的jsp頁面名稱的解耦。
6.談?wù)勀銓ibernate的理解档泽。
1.面向?qū)ο笤O(shè)計的軟件內(nèi)部運(yùn)行過程可以理解成就是在不斷創(chuàng)建各種新對象俊戳、建立對象之間的關(guān)系,調(diào)用對象的方法來改變各個對象的狀態(tài)和對象消亡的過程馆匿,不管程序運(yùn)行的過程和操作怎么樣抑胎,本質(zhì)上都是要得到一個結(jié)果,程序上一個時刻和下一個時刻的運(yùn)行結(jié)果的差異就表現(xiàn)在內(nèi)存中的對象狀態(tài)發(fā)生了變化渐北。
2.為了在關(guān)機(jī)和內(nèi)存空間不夠的狀況下阿逃,保持程序的運(yùn)行狀態(tài),需要將內(nèi)存中的對象狀態(tài)保存到持久化設(shè)備和從持久化設(shè)備中恢復(fù)出對象的狀態(tài)赃蛛,通常都是保存到關(guān)系數(shù)據(jù)庫來保存大量對象信息恃锉。從Java程序的運(yùn)行功能上來講,保存對象狀態(tài)的功能相比系統(tǒng)運(yùn)行的其他功能來說呕臂,應(yīng)該是一個很不起眼的附屬功能破托,java采用jdbc來實現(xiàn)這個功能,這個不起眼的功能卻要編寫大量的代碼歧蒋,而做的事情僅僅是保存對象和恢復(fù)對象炼团,并且那些大量的jdbc代碼并沒有什么技術(shù)含量,基本上是采用一套例行公事的標(biāo)準(zhǔn)代碼模板來編寫疏尿,是一種苦活和重復(fù)性的工作瘟芝。
3.通過數(shù)據(jù)庫保存java程序運(yùn)行時產(chǎn)生的對象和恢復(fù)對象,其實就是實現(xiàn)了java對象與關(guān)系數(shù)據(jù)庫記錄的映射關(guān)系褥琐,稱為ORM(即Object Relation Mapping)锌俱,人們可以通過封裝JDBC代碼來實現(xiàn)了這種功能,封裝出來的產(chǎn)品稱之為ORM框架敌呈,Hibernate就是其中的一種流行ORM框架贸宏。使用Hibernate框架,不用寫JDBC代碼磕洪,僅僅是調(diào)用一個save方法吭练,就可以將對象保存到關(guān)系數(shù)據(jù)庫中,僅僅是調(diào)用一個get方法析显,就可以從數(shù)據(jù)庫中加載出一個對象鲫咽。
4.使用Hibernate的基本流程是:配置Configuration對象、產(chǎn)生SessionFactory、創(chuàng)建session對象分尸,啟動事務(wù)锦聊,完成CRUD操作,提交事務(wù)箩绍,關(guān)閉session孔庭。
5.使用Hibernate時,先要配置hibernate.cfg.xml文件材蛛,其中配置數(shù)據(jù)庫連接信息和方言等圆到,還要為每個實體配置相應(yīng)的hbm.xml文件,hibernate.cfg.xml文件中需要登記每個hbm.xml文件卑吭。
6.在應(yīng)用Hibernate時芽淡,重點要了解Session的緩存原理,級聯(lián),延遲加載和hql查詢。
7.Sprig AOP
前段時間寫的java設(shè)計模式--代理模式坎穿,最近在看Spring Aop的時候湘今,覺得于代理模式應(yīng)該有密切的聯(lián)系,于是決定了解下Spring Aop的實現(xiàn)原理唉窃。
說起AOP就不得不說下OOP了耙饰,OOP中引入封裝、繼承和多態(tài)性等概念來建立一種對象層次結(jié)構(gòu)纹份,用以模擬公共行為的一個集合苟跪。但是,如果我們需要為部分對象引入公共部分的時候蔓涧,OOP就會引入大量重復(fù)的代碼件已。例如:日志功能。
AOP技術(shù)利用一種稱為“橫切”的技術(shù)元暴,解剖封裝的對象內(nèi)部篷扩,并將那些影響了多個類的公共行為封裝到一個可重用模塊,這樣就能減少系統(tǒng)的重復(fù)代碼茉盏,降低模塊間的耦合度鉴未,并有利于未來的可操作性和可維護(hù)性。AOP把軟件系統(tǒng)分為兩個部分:核心關(guān)注點和橫切關(guān)注點鸠姨。業(yè)務(wù)處理的主要流程是核心關(guān)注點铜秆,與之關(guān)系不大的部分是橫切關(guān)注點。橫切關(guān)注點的一個特點是讶迁,他們經(jīng)常發(fā)生在核心關(guān)注點的多處连茧,而各處都基本相似。比如權(quán)限認(rèn)證、日志梅屉、事務(wù)處理值纱。
實現(xiàn)AOP的技術(shù),主要分為兩大類:
一是采用動態(tài)代理技術(shù)坯汤,利用截取消息的方式虐唠,對該消息進(jìn)行裝飾,以取代原有對象行為的執(zhí)行惰聂;
二是采用靜態(tài)織入的方式疆偿,引入特定的語法創(chuàng)建“方面”,從而使得編譯器可以在編譯期間織入有關(guān)“方面”的代碼搓幌。
Spring AOP 的實現(xiàn)原理其實很簡單:AOP 框架負(fù)責(zé)動態(tài)地生成 AOP 代理類杆故,這個代理類的方法則由 Advice 和回調(diào)目標(biāo)對象的方法所組成,并將該對象可作為目標(biāo)對象使用。AOP 代理包含了目標(biāo)對象的全部方法溉愁,但 AOP 代理中的方法與目標(biāo)對象的方法存在差異处铛,AOP 方法在特定切入點添加了增強(qiáng)處理,并回調(diào)了目標(biāo)對象的方法拐揭。
Spring AOP使用動態(tài)代理技術(shù)在運(yùn)行期織入增強(qiáng)代碼撤蟆。使用兩種代理機(jī)制:
基于JDK的動態(tài)代理(JDK本身只提供接口的代理);
基于CGlib的動態(tài)代理堂污。
1)JDK的動態(tài)代理主要涉及java.lang.reflect包中的兩個類:Proxy和InvocationHandler家肯。其中InvocationHandler只是一個接口,可以通過實現(xiàn)該接口定義橫切邏輯盟猖,并通過反射機(jī)制調(diào)用目標(biāo)類的代碼讨衣,動態(tài)的將橫切邏輯與業(yè)務(wù)邏輯織在一起。而Proxy利用InvocationHandler動態(tài)創(chuàng)建一個符合某一接口的實例式镐,生成目標(biāo)類的代理對象反镇。 其代理對象必須是某個接口的實現(xiàn),它是通過在運(yùn)行期間創(chuàng)建一個接口的實現(xiàn)類來完成對目標(biāo)對象的代理.只能實現(xiàn)接口的類生成代理,而不能針對類
2)CGLib采用底層的字節(jié)碼技術(shù),為一個類創(chuàng)建子類娘汞,并在子類中采用方法攔截的技術(shù)攔截所有父類的調(diào)用方法愿险,并順勢織入橫切邏輯.它運(yùn)行期間生成的代理對象是目標(biāo)類的擴(kuò)展子類.所以無法通知final的方法,因為它們不能被覆寫.是針對類實現(xiàn)代理,主要是為指定的類生成一個子類,覆蓋其中方法.
在spring中默認(rèn)情況下使用JDK動態(tài)代理實現(xiàn)AOP,如果proxy-target-class設(shè)置為true或者使用了優(yōu)化策略那么會使用CGLIB來創(chuàng)建動態(tài)代理.Spring AOP在這兩種方式的實現(xiàn)上基本一樣.以JDK代理為例,會使用JdkDynamicAopProxy來創(chuàng)建代理价说,在invoke()方法首先需要織入到當(dāng)前類的增強(qiáng)器封裝到攔截器鏈中辆亏,然后遞歸的調(diào)用這些攔截器完成功能的織入.最終返回代理對象.
8.介紹一下Hibernate的二級緩存
(1)緩存就是把以前從數(shù)據(jù)庫中查詢出來和使用過的對象保存在內(nèi)存中(一個數(shù)據(jù)結(jié)構(gòu)中),這個數(shù)據(jù)結(jié)構(gòu)通常是或類似Hashmap鳖目,當(dāng)以后要使用某個對象時扮叨,先查詢緩存中是否有這個對象,如果有則使用緩存中的對象领迈,如果沒有則去查詢數(shù)據(jù)庫彻磁,并將查詢出來的對象保存在緩存中碍沐,以便下次使用。
(2)Hibernate的Session就是一種緩存衷蜓,我們通常將之稱為Hibernate的一級緩存累提,當(dāng)想使用session從數(shù)據(jù)庫中查詢出一個對象時,Session也是先從自己內(nèi)部查看是否存在這個對象磁浇,存在則直接返回斋陪,不存在才去訪問數(shù)據(jù)庫,并將查詢的結(jié)果保存在自己內(nèi)部置吓。由于Session代表一次會話過程无虚,一個Session與一個數(shù)據(jù)庫連接相關(guān)連,所以Session最好不要長時間保持打開衍锚,通常僅用于一個事務(wù)當(dāng)中友题,在事務(wù)結(jié)束時就應(yīng)關(guān)閉。并且Session是線程不安全的戴质,被多個線程共享時容易出現(xiàn)問題度宦。通常只有那種全局意義上的緩存才是真正的緩存應(yīng)用,才有較大的緩存價值告匠,因此戈抄,Hibernate的Session這一級緩存的緩存作用并不明顯,應(yīng)用價值不大凫海。Hibernate的二級緩存就是要為Hibernate配置一種全局緩存呛凶,讓多個線程和多個事務(wù)都可以共享這個緩存男娄。我們希望的是一個人使用過行贪,其他人也可以使用,session沒有這種效果模闲。
(3)二級緩存是獨立于Hibernate的軟件部件建瘫,屬于第三方的產(chǎn)品,多個廠商和組織都提供有緩存產(chǎn)品尸折,例如啰脚,EHCache和OSCache等等。在Hibernate中使用二級緩存实夹,首先就要在hibernate.cfg.xml配置文件中配置使用哪個廠家的緩存產(chǎn)品橄浓,接著需要配置該緩存產(chǎn)品自己的配置文件,最后要配置Hibernate中的哪些實體對象要納入到二級緩存的管理中亮航。明白了二級緩存原理和有了這個思路后荸实,很容易配置起Hibernate的二級緩存。擴(kuò)展知識:一個SessionFactory可以關(guān)聯(lián)一個二級緩存缴淋,也即一個二級緩存只能負(fù)責(zé)緩存一個數(shù)據(jù)庫中的數(shù)據(jù)准给,當(dāng)使用Hibernate 的二級緩存后泄朴,注意不要有其他的應(yīng)用或SessionFactory來更改當(dāng)前數(shù)據(jù)庫中的數(shù)據(jù),這樣緩存的數(shù)據(jù)就會與數(shù)據(jù)庫中的實際數(shù)據(jù)不一致露氮。
9.三大框架各起的作用
struts 在SSH 框架中起控制的作用 , 其核心是(控制器)Controller, 即ActionServlet,而 ActionServlet 的核心就是Struts-config.xml. 主要控制邏輯關(guān)系的處理 . hibernate 是數(shù)據(jù)持久化層 , 是一種新的對象祖灰、關(guān)系的映射工具 , 提供了從 Java 類到數(shù)據(jù)表的映射,也提供了數(shù)據(jù)查詢和恢復(fù)等機(jī)制 , 大大減少數(shù)據(jù)訪問的復(fù)雜度畔规。把對數(shù)據(jù)庫的直接操作 , 轉(zhuǎn)換為對持久對象的操作局扶。
spring 是一個輕量級的控制反轉(zhuǎn) (IoC) 和面向切面 (AOP) 的容器框架, 面向接口的編程 , 由容器控制程序之間的(依賴)關(guān)系,而非傳統(tǒng)實現(xiàn)中油讯,由程序代碼直接操控详民。這也就是所謂“ 控制反轉(zhuǎn)” 的概念所在:(依賴)控制權(quán)由應(yīng)用代碼中轉(zhuǎn)到了外部容器,控制權(quán)的轉(zhuǎn)移陌兑,是所謂反轉(zhuǎn)沈跨。依賴注入,即組件之間的依賴關(guān)系由容器在運(yùn)行期決定兔综,形象的來說饿凛,即由容器動態(tài)的將某種依賴關(guān)系注入到組件之中 起到的主要作用是解耦。
10.spring核心:aop和ioc的解釋软驰?隔離范圍涧窒? 3種注入方法?
(1)aop:Spring提供了對AOP技術(shù)的良好封裝锭亏, AOP稱為面向切面編程纠吴,就是系統(tǒng)中有很多各不相干的類的方法,在這些眾多方法中要加入某種系統(tǒng)功能的代碼;例如慧瘤,加入日志戴已,加入權(quán)限判斷,加入異常處理锅减,這種應(yīng)用稱為AOP糖儡。實現(xiàn)AOP功能采用的是代理技術(shù),客戶端程序不再調(diào)用目標(biāo)怔匣,而調(diào)用代理類握联,代理類與目標(biāo)類對外具有相同的方法聲明,有兩種方式可以實現(xiàn)相同的方法聲明每瞒,一是實現(xiàn)相同的接口金闽,二是作為目標(biāo)的子類在,JDK中采用Proxy類產(chǎn)生動態(tài)代理的方式為某個接口生成實現(xiàn)類剿骨,spring提供了這種支持代芜,只需要在spring配置文件中配置這兩個元素即可實現(xiàn)代理和aop功能;
(2)Ioc:Spring提供了對IOC良好支持,IOC是一種編程思想懦砂,是一種架構(gòu)藝術(shù)蜒犯,利用這種思想可以很好地實現(xiàn)模塊之間的解耦组橄。IOC也稱為DI(Depency Injection);IOC可以理解為‘面向接口編程思想’的一種實現(xiàn)方法,通過IOC實現(xiàn)了強(qiáng)制的‘面向接口編程’罚随。
(3)隔離范圍:Spring支持JDBC規(guī)范定義的四種隔離級別
Default默認(rèn)的事務(wù)隔離級別
READ_UNCOMMITTED讀未提交玉工,一個事務(wù)可以操作另外一個未提交的事務(wù),不能避免臟讀淘菩,不可重復(fù)讀遵班,幻讀,隔離級別最低潮改,并發(fā)性 能最高
READ_COMMITTED讀已提交狭郑,一個事務(wù)不可以操作另外一個未提交的事務(wù), 能防止臟讀汇在,不能避免不可重復(fù)讀翰萨,幻讀。
repeatable_read能夠避免臟讀糕殉,不可重復(fù)讀亩鬼,不能避免幻讀
SERIALIZABLE隔離級別最高,消耗資源最低阿蝶,代價最高雳锋,能夠防止臟讀, 不可重復(fù)讀羡洁,幻讀玷过。
(4)Spring的注入和IoC反轉(zhuǎn)控制是一回事;關(guān)于getter和setter方式的注入;
Autowire=”defualt”;autowire=”byName”;autowire=”byType”;
11.Spring Bean的作用域之間有什么區(qū)別?
Spring容器中的bean可以分為5個范圍筑煮。所有范圍的名稱都是自說明的辛蚊,但是為了避免混淆,還是讓我們來解釋一下:
singleton:這種bean范圍是默認(rèn)的咆瘟,這種范圍確保不管接受到多少個請求嚼隘,每個容器中只有一個bean的實例诽里,單例的模式由bean factory自身來維護(hù)袒餐。
prototype:原形范圍與單例范圍相反,為每一個bean請求提供一個實例谤狡。
request:在請求bean范圍內(nèi)會每一個來自客戶端的網(wǎng)絡(luò)請求創(chuàng)建一個實例灸眼,在請求完成以后,bean會失效并被垃圾回收器回收墓懂。
Session:與請求范圍類似焰宣,確保每個session中有一個bean的實例,在session過期后捕仔,bean會隨之失效匕积。
global-session:global-session和Portlet應(yīng)用相關(guān)盈罐。當(dāng)你的應(yīng)用部署在Portlet容器中工作時,它包含很多portlet闪唆。如果你想要聲明讓所有的portlet共用全局的存儲變量的話盅粪,那么這全局變量需要存儲在global-session中。
12.大型網(wǎng)站在架構(gòu)上應(yīng)當(dāng)考慮哪些問題悄蕾?
1.分層:分層是處理任何復(fù)雜系統(tǒng)最常見的手段之一票顾,將系統(tǒng)橫向切分成若干個層面,每個層面只承擔(dān)單一的職責(zé)帆调,然后通過下層為上層提供的基礎(chǔ)設(shè)施和服務(wù)以及上層對下層的調(diào)用來形成一個完整的復(fù)雜的系統(tǒng)奠骄。計算機(jī)網(wǎng)絡(luò)的開放系統(tǒng)互聯(lián)參考模型(OSI/RM)和Internet的TCP/IP模型都是分層結(jié)構(gòu),大型網(wǎng)站的軟件系統(tǒng)也可以使用分層的理念將其分為持久層(提供數(shù)據(jù)存儲和訪問服務(wù))番刊、業(yè)務(wù)層(處理業(yè)務(wù)邏輯含鳞,系統(tǒng)中最核心的部分)和表示層(系統(tǒng)交互、視圖展示)芹务。需要指出的是:(1)分層是邏輯上的劃分民晒,在物理上可以位于同一設(shè)備上也可以在不同的設(shè)備上部署不同的功能模塊,這樣可以使用更多的計算資源來應(yīng)對用戶的并發(fā)訪問锄禽;(2)層與層之間應(yīng)當(dāng)有清晰的邊界潜必,這樣分層才有意義,才更利于軟件的開發(fā)和維護(hù)沃但。
2.分割:分割是對軟件的縱向切分磁滚。我們可以將大型網(wǎng)站的不同功能和服務(wù)分割開,形成高內(nèi)聚低耦合的功能模塊(單元)宵晚。在設(shè)計初期可以做一個粗粒度的分割垂攘,將網(wǎng)站分割為若干個功能模塊,后期還可以進(jìn)一步對每個模塊進(jìn)行細(xì)粒度的分割淤刃,這樣一方面有助于軟件的開發(fā)和維護(hù)晒他,另一方面有助于分布式的部署,提供網(wǎng)站的并發(fā)處理能力和功能的擴(kuò)展逸贾。
3.分布式:除了上面提到的內(nèi)容陨仅,網(wǎng)站的靜態(tài)資源(JavaScript、CSS铝侵、圖片等)也可以采用獨立分布式部署并采用獨立的域名灼伤,這樣可以減輕應(yīng)用服務(wù)器的負(fù)載壓力,也使得瀏覽器對資源的加載更快咪鲜。數(shù)據(jù)的存取也應(yīng)該是分布式的狐赡,傳統(tǒng)的商業(yè)級關(guān)系型數(shù)據(jù)庫產(chǎn)品基本上都支持分布式部署,而新生的NoSQL產(chǎn)品幾乎都是分布式的疟丙。當(dāng)然颖侄,網(wǎng)站后臺的業(yè)務(wù)處理也要使用分布式技術(shù)鸟雏,例如查詢索引的構(gòu)建、數(shù)據(jù)分析等览祖,這些業(yè)務(wù)計算規(guī)模龐大崔慧,可以使用Hadoop以及MapReduce分布式計算框架來處理。
4.集群:集群使得有更多的服務(wù)器提供相同的服務(wù)穴墅,可以更好的提供對并發(fā)的支持惶室。
5.緩存:所謂緩存就是用空間換取時間的技術(shù),將數(shù)據(jù)盡可能放在距離計算最近的位置玄货。使用緩存是網(wǎng)站優(yōu)化的第一定律皇钞。我們通常說的CDN、反向代理松捉、熱點數(shù)據(jù)都是對緩存技術(shù)的使用夹界。
6.異步:異步是實現(xiàn)軟件實體之間解耦合的又一重要手段。異步架構(gòu)是典型的生產(chǎn)者消費者模式隘世,二者之間沒有直接的調(diào)用關(guān)系可柿,只要保持?jǐn)?shù)據(jù)結(jié)構(gòu)不變,彼此功能實現(xiàn)可以隨意變化而不互相影響丙者,這對網(wǎng)站的擴(kuò)展非常有利复斥。使用異步處理還可以提高系統(tǒng)可用性,加快網(wǎng)站的響應(yīng)速度(用Ajax加載數(shù)據(jù)就是一種異步技術(shù))械媒,同時還可以起到削峰作用(應(yīng)對瞬時高并發(fā))目锭。";能推遲處理的都要推遲處理"是網(wǎng)站優(yōu)化的第二定律纷捞,而異步是踐行網(wǎng)站優(yōu)化第二定律的重要手段痢虹。
7.冗余:各種服務(wù)器都要提供相應(yīng)的冗余服務(wù)器以便在某臺或某些服務(wù)器宕機(jī)時還能保證網(wǎng)站可以正常工作,同時也提供了災(zāi)難恢復(fù)的可能性主儡。冗余是網(wǎng)站高可用性的重要保證奖唯。
13.你用過的網(wǎng)站前端優(yōu)化的技術(shù)有哪些?
①瀏覽器訪問優(yōu)化:
- 減少HTTP請求數(shù)量:合并CSS糜值、合并javascript丰捷、合并圖片(CSS Sprite)
- 使用瀏覽器緩存:通過設(shè)置HTTP響應(yīng)頭中的Cache-Control和Expires屬性,將CSS臀玄、JavaScript瓢阴、圖片等在瀏覽器中緩存畅蹂,當(dāng)這些靜態(tài)資源需要更新時健无,可以更新HTML文件中的引用來讓瀏覽器重新請求新的資源
- 啟用壓縮
- CSS前置,JavaScript后置 -減少Cookie傳輸
② CDN加速:CDN(ContentDistribute Network)的本質(zhì)仍然是緩存液斜,將數(shù)據(jù)緩存在離用戶最近的地方累贤,CDN通常部署在網(wǎng)絡(luò)運(yùn)營商的機(jī)房叠穆,不僅可以提升響應(yīng)速度,還可以減少應(yīng)用服務(wù)器的壓力臼膏。當(dāng)然硼被,CDN緩存的通常都是靜態(tài)資源。
③反向代理:反向代理相當(dāng)于應(yīng)用服務(wù)器的一個門面渗磅,可以保護(hù)網(wǎng)站的安全性嚷硫,也可以實現(xiàn)負(fù)載均衡的功能,當(dāng)然最重要的是它緩存了用戶訪問的熱點資源始鱼,可以直接從反向代理將某些內(nèi)容返回給用戶瀏覽器仔掸。
14.你使用過的應(yīng)用服務(wù)器優(yōu)化技術(shù)有哪些?
①分布式緩存:緩存的本質(zhì)就是內(nèi)存中的哈希表医清,如果設(shè)計一個優(yōu)質(zhì)的哈希函數(shù)起暮,那么理論上哈希表讀寫的漸近時間復(fù)雜度為O(1)。緩存主要用來存放那些讀寫比很高会烙、變化很少的數(shù)據(jù)负懦,這樣應(yīng)用程序讀取數(shù)據(jù)時先到緩存中讀取,如果沒有或者數(shù)據(jù)已經(jīng)失效再去訪問數(shù)據(jù)庫或文件系統(tǒng)柏腻,并根據(jù)擬定的規(guī)則將數(shù)據(jù)寫入緩存纸厉。對網(wǎng)站數(shù)據(jù)的訪問也符合二八定律(Pareto分布,冪律分布)五嫂,即80%的訪問都集中在20%的數(shù)據(jù)上残腌,如果能夠?qū)⑦@20%的數(shù)據(jù)緩存起來,那么系統(tǒng)的性能將得到顯著的改善贫导。當(dāng)然抛猫,使用緩存需要解決以下幾個問題:
- 頻繁修改的數(shù)據(jù);
- 數(shù)據(jù)不一致與臟讀孩灯;
- 緩存雪崩(可以采用分布式緩存服務(wù)器集群加以解決闺金,memcached是廣泛采用的解決方案);
- 緩存預(yù)熱峰档;
- 緩存穿透(惡意持續(xù)請求不存在的數(shù)據(jù))败匹。
②異步操作:可以使用消息隊列將調(diào)用異步化,通過異步處理將短時間高并發(fā)產(chǎn)生的事件消息存儲在消息隊列中讥巡,從而起到削峰作用掀亩。電商網(wǎng)站在進(jìn)行促銷活動時,可以將用戶的訂單請求存入消息隊列欢顷,這樣可以抵御大量的并發(fā)訂單請求對系統(tǒng)和數(shù)據(jù)庫的沖擊槽棍。目前,絕大多數(shù)的電商網(wǎng)站即便不進(jìn)行促銷活動,訂單系統(tǒng)都采用了消息隊列來處理炼七。
③使用集群缆巧。
④代碼優(yōu)化:
-多線程:基于Java的Web開發(fā)基本上都通過多線程的方式響應(yīng)用戶的并發(fā)請求,使用多線程技術(shù)在編程上要解決線程安全問題豌拙,主要可以考慮以下幾個方面:A. 將對象設(shè)計為無狀態(tài)對象(這和面向?qū)ο蟮木幊逃^點是矛盾的陕悬,在面向?qū)ο蟮氖澜缰斜灰暈椴涣荚O(shè)計),這樣就不會存在并發(fā)訪問時對象狀態(tài)不一致的問題按傅。B. 在方法內(nèi)部創(chuàng)建對象捉超,這樣對象由進(jìn)入方法的線程創(chuàng)建,不會出現(xiàn)多個線程訪問同一對象的問題唯绍。使用ThreadLocal將對象與線程綁定也是很好的做法狂秦,這一點在前面已經(jīng)探討過了。C. 對資源進(jìn)行并發(fā)訪問時應(yīng)當(dāng)使用合理的鎖機(jī)制推捐。 - 非阻塞I/O:使用單線程和非阻塞I/O是目前公認(rèn)的比多線程的方式更能充分發(fā)揮服務(wù)器性能的應(yīng)用模式裂问,基于Node.js構(gòu)建的服務(wù)器就采用了這樣的方式。Java在JDK 1.4中就引入了NIO(Non-blockingI/O),在Servlet3規(guī)范中又引入了異步Servlet的概念牛柒,這些都為在服務(wù)器端采用非阻塞I/O提供了必要的基礎(chǔ)堪簿。
- 資源復(fù)用:資源復(fù)用主要有兩種方式,一是單例皮壁,二是對象池椭更,我們使用的數(shù)據(jù)庫連接池、線程池都是對象池化技術(shù)蛾魄,這是典型的用空間換取時間的策略虑瀑,另一方面也實現(xiàn)對資源的復(fù)用,從而避免了不必要的創(chuàng)建和釋放資源所帶來的開銷滴须。
15.Hibernate與Mybatis比較
第一方面:開發(fā)速度的對比
就開發(fā)速度而言舌狗,Hibernate的真正掌握要比Mybatis來得難些。Mybatis框架相對簡單很容易上手扔水,但也相對簡陋些痛侍。個人覺得要用好Mybatis還是首先要先理解好Hibernate。
比起兩者的開發(fā)速度魔市,不僅僅要考慮到兩者的特性及性能主届,更要根據(jù)項目需求去考慮究竟哪一個更適合項目開發(fā),比如:一個項目中用到的復(fù)雜查詢基本沒有待德,就是簡單的增刪改查君丁,這樣選擇hibernate效率就很快了,因為基本的sql語句已經(jīng)被封裝好了将宪,根本不需要你去寫sql語句绘闷,這就節(jié)省了大量的時間橡庞,但是對于一個大型項目,復(fù)雜語句較多簸喂,這樣再去選擇hibernate就不是一個太好的選擇毙死,選擇mybatis就會加快許多燎潮,而且語句的管理也比較方便喻鳄。
第二方面:開發(fā)工作量的對比
Hibernate和MyBatis都有相應(yīng)的代碼生成工具∪贩猓可以生成簡單基本的DAO層方法除呵。針對高級查詢,Mybatis需要手動編寫SQL語句爪喘,以及ResultMap颜曾。而Hibernate有良好的映射機(jī)制,開發(fā)者無需關(guān)心SQL的生成與結(jié)果映射秉剑,可以更專注于業(yè)務(wù)流程泛豪。
第三方面:sql優(yōu)化方面
Hibernate的查詢會將表中的所有字段查詢出來,這一點會有性能消耗侦鹏。Hibernate也可以自己寫SQL來指定需要查詢的字段诡曙,但這樣就破壞了Hibernate開發(fā)的簡潔性。而Mybatis的SQL是手動編寫的略水,所以可以按需求指定查詢的字段价卤。
Hibernate HQL語句的調(diào)優(yōu)需要將SQL打印出來,而Hibernate的SQL被很多人嫌棄因為太丑了渊涝。MyBatis的SQL是自己手動寫的所以調(diào)整方便慎璧。但Hibernate具有自己的日志統(tǒng)計。Mybatis本身不帶日志統(tǒng)計跨释,使用Log4j進(jìn)行日志記錄胸私。
第四方面:對象管理的對比
Hibernate 是完整的對象/關(guān)系映射解決方案,它提供了對象狀態(tài)管理(state management)的功能鳖谈,使開發(fā)者不再需要理會底層數(shù)據(jù)庫系統(tǒng)的細(xì)節(jié)盖文。也就是說,相對于常見的 JDBC/SQL 持久層方案中需要管理 SQL 語句蚯姆,Hibernate采用了更自然的面向?qū)ο蟮囊暯莵沓志没?Java 應(yīng)用中的數(shù)據(jù)五续。
換句話說,使用 Hibernate 的開發(fā)者應(yīng)該總是關(guān)注對象的狀態(tài)(state)龄恋,不必考慮 SQL 語句的執(zhí)行疙驾。這部分細(xì)節(jié)已經(jīng)由 Hibernate 掌管妥當(dāng),只有開發(fā)者在進(jìn)行系統(tǒng)性能調(diào)優(yōu)的時候才需要進(jìn)行了解郭毕。而MyBatis在這一塊沒有文檔說明它碎,用戶需要對對象自己進(jìn)行詳細(xì)的管理。
第五方面:緩存機(jī)制
Hibernate緩存
Hibernate一級緩存是Session緩存,利用好一級緩存就需要對Session的生命周期進(jìn)行管理好扳肛。建議在一個Action操作中使用一個Session傻挂。一級緩存需要對Session進(jìn)行嚴(yán)格管理。
Hibernate二級緩存是SessionFactory級的緩存挖息。 SessionFactory的緩存分為內(nèi)置緩存和外置緩存金拒。內(nèi)置緩存中存放的是SessionFactory對象的一些集合屬性包含的數(shù)據(jù)(映射元素?fù)?jù)及預(yù)定SQL語句等),對于應(yīng)用程序來說,它是只讀的。外置緩存中存放的是數(shù)據(jù)庫數(shù)據(jù)的副本,其作用和一級緩存類似.二級緩存除了以內(nèi)存作為存儲介質(zhì)外,還可以選用硬盤等外部存儲設(shè)備套腹。二級緩存稱為進(jìn)程級緩存或SessionFactory級緩存绪抛,它可以被所有session共享,它的生命周期伴隨著SessionFactory的生命周期存在和消亡电禀。
MyBatis緩存
MyBatis 包含一個非常強(qiáng)大的查詢緩存特性,它可以非常方便地配置和定制幢码。MyBatis 3 中的緩存實現(xiàn)的很多改進(jìn)都已經(jīng)實現(xiàn)了,使得它更加強(qiáng)大而且易于配置。
默認(rèn)情況下是沒有開啟緩存的,除了局部的 session 緩存,可以增強(qiáng)變現(xiàn)而且處理循環(huán) 依賴也是必須的尖飞。要開啟二級緩存,你需要在你的 SQL 映射文件中添加一行: <cache/>
字面上看就是這樣症副。這個簡單語句的效果如下:
- 映射語句文件中的所有 select 語句將會被緩存。
- 映射語句文件中的所有 insert,update 和 delete 語句會刷新緩存政基。
- 緩存會使用 Least Recently Used(LRU,最近最少使用的)算法來收回贞铣。
- 根據(jù)時間表(比如 no Flush Interval,沒有刷新間隔), 緩存不會以任何時間順序 來刷新羔砾。
- 緩存會存儲列表集合或?qū)ο?無論查詢方法返回什么)的 1024 個引用腋寨。
- 緩存會被視為是 read/write(可讀/可寫)的緩存,意味著對象檢索不是共享的,而 且可以安全地被調(diào)用者修改,而不干擾其他調(diào)用者或線程所做的潛在修改。
所有的這些屬性都可以通過緩存元素的屬性來修改奈梳。
比如: <cache eviction=”FIFO” flushInterval=”60000″ size=”512″ readOnly=”true”/>
這個更高級的配置創(chuàng)建了一個 FIFO 緩存,并每隔 60 秒刷新,存數(shù)結(jié)果對象或列表的 512 個引用,而且返回的對象被認(rèn)為是只讀的,因此在不同線程中的調(diào)用者之間修改它們會 導(dǎo)致沖突珊擂∈ダ眨可用的收回策略有, 默認(rèn)的是 LRU:
- LRU – 最近最少使用的:移除最長時間不被使用的對象。
- FIFO – 先進(jìn)先出:按對象進(jìn)入緩存的順序來移除它們摧扇。
- SOFT – 軟引用:移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對象圣贸。
- WEAK – 弱引用:更積極地移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對象。
flushInterval(刷新間隔)可以被設(shè)置為任意的正整數(shù),而且它們代表一個合理的毫秒 形式的時間段扛稽。默認(rèn)情況是不設(shè)置,也就是沒有刷新間隔,緩存僅僅調(diào)用語句時刷新吁峻。
size(引用數(shù)目)可以被設(shè)置為任意正整數(shù),要記住你緩存的對象數(shù)目和你運(yùn)行環(huán)境的 可用內(nèi)存資源數(shù)目。默認(rèn)值是1024在张。
readOnly(只讀)屬性可以被設(shè)置為 true 或 false用含。只讀的緩存會給所有調(diào)用者返回緩 存對象的相同實例。因此這些對象不能被修改帮匾。這提供了很重要的性能優(yōu)勢啄骇。可讀寫的緩存 會返回緩存對象的拷貝(通過序列化) 瘟斜。這會慢一些,但是安全,因此默認(rèn)是 false缸夹。
相同點:Hibernate和Mybatis的二級緩存除了采用系統(tǒng)默認(rèn)的緩存機(jī)制外痪寻,都可以通過實現(xiàn)你自己的緩存或為其他第三方緩存方案,創(chuàng)建適配器來完全覆蓋緩存行為虽惭。
不同點:Hibernate的二級緩存配置在SessionFactory生成的配置文件中進(jìn)行詳細(xì)配置橡类,然后再在具體的表-對象映射中配置是那種緩存。
MyBatis的二級緩存配置都是在每個具體的表-對象映射中進(jìn)行詳細(xì)配置芽唇,這樣針對不同的表可以自定義不同的緩存機(jī)制顾画。并且Mybatis可以在命名空間中共享相同的緩存配置和實例,通過Cache-ref來實現(xiàn)披摄。
兩者比較:因為Hibernate對查詢對象有著良好的管理機(jī)制亲雪,用戶無需關(guān)心SQL勇凭。所以在使用二級緩存時如果出現(xiàn)臟數(shù)據(jù)疚膊,系統(tǒng)會報出錯誤并提示。
而MyBatis在這一方面虾标,使用二級緩存時需要特別小心寓盗。如果不能完全確定數(shù)據(jù)更新操作的波及范圍,避免Cache的盲目使用璧函。否則傀蚌,臟數(shù)據(jù)的出現(xiàn)會給系統(tǒng)的正常運(yùn)行帶來很大的隱患。
第六方面:總結(jié)
對于總結(jié)蘸吓,大家可以到各大java論壇去看一看
相同點:Hibernate與MyBatis都可以是通過SessionFactoryBuider由XML配置文件生成SessionFactory善炫,然后由SessionFactory 生成Session,最后由Session來開啟執(zhí)行事務(wù)和SQL語句库继。其中SessionFactoryBuider箩艺,SessionFactory,Session的生命周期都是差不多的宪萄。
- Hibernate和MyBatis都支持JDBC和JTA事務(wù)處理艺谆。
Mybatis優(yōu)勢
- MyBatis可以進(jìn)行更為細(xì)致的SQL優(yōu)化,可以減少查詢字段拜英。
- MyBatis容易掌握静汤,而Hibernate門檻較高。
Hibernate優(yōu)勢
- Hibernate的DAO層開發(fā)比MyBatis簡單居凶,Mybatis需要維護(hù)SQL和結(jié)果映射虫给。
- Hibernate對對象的維護(hù)和緩存要比MyBatis好,對增刪改查的對象的維護(hù)要方便侠碧。
- Hibernate數(shù)據(jù)庫移植性很好抹估,MyBatis的數(shù)據(jù)庫移植性不好,不同的數(shù)據(jù)庫需要寫不同SQL舆床。
- Hibernate有更好的二級緩存機(jī)制棋蚌,可以使用第三方緩存嫁佳。MyBatis本身提供的緩存機(jī)制不佳。
他人總結(jié)
- Hibernate功能強(qiáng)大谷暮,數(shù)據(jù)庫無關(guān)性好蒿往,O/R映射能力強(qiáng),如果你對Hibernate相當(dāng)精通湿弦,而且對Hibernate進(jìn)行了適當(dāng)?shù)姆庋b瓤漏,那么你的項目整個持久層代碼會相當(dāng)簡單,需要寫的代碼很少颊埃,開發(fā)速度很快蔬充,非常爽。
- Hibernate的缺點就是學(xué)習(xí)門檻不低班利,要精通門檻更高饥漫,而且怎么設(shè)計O/R映射,在性能和對象模型之間如何權(quán)衡取得平衡罗标,以及怎樣用好Hibernate方面需要你的經(jīng)驗和能力都很強(qiáng)才行庸队。
- iBATIS入門簡單,即學(xué)即用闯割,提供了數(shù)據(jù)庫查詢的自動對象綁定功能彻消,而且延續(xù)了很好的SQL使用經(jīng)驗,對于沒有那么高的對象模型要求的項目來說宙拉,相當(dāng)完美宾尚。
- iBATIS的缺點就是框架還是比較簡陋,功能尚有缺失谢澈,雖然簡化了數(shù)據(jù)綁定代碼煌贴,但是整個底層數(shù)據(jù)庫查詢實際還是要自己寫的,工作量也比較大澳化,而且不太容易適應(yīng)快速數(shù)據(jù)庫修改崔步。
16.filter與servlet的比較
一、概念:
1缎谷、servlet:servlet是一種運(yùn)行服務(wù)器端的java應(yīng)用程序井濒,具有獨立于平臺和協(xié)議的特性,并且可以動態(tài)的生成web頁面列林,它工作在客戶端請求與服務(wù)器響應(yīng)的中間層瑞你。
2、filter:filter是一個可以復(fù)用的代碼片段希痴,可以用來轉(zhuǎn)換HTTP請求者甲、響應(yīng)和頭信息。Filter不像Servlet砌创,它不能產(chǎn)生一個請求或者響應(yīng)虏缸,它只是修改對某一資源的請求鲫懒,或者修改從某一的響應(yīng)。
二刽辙、生命周期:
1窥岩、servlet:servlet的生命周期始于它被裝入web服務(wù)器的內(nèi)存時,并在web服務(wù)器終止或重新裝入servlet時結(jié)束宰缤。servlet一旦被裝入web服務(wù)器颂翼,一般不會從web服務(wù)器內(nèi)存中刪除,直至web服務(wù)器關(guān)閉或重新結(jié)束慨灭。
(1)朦乏、裝入:啟動服務(wù)器時加載Servlet的實例;
(2)氧骤、初始化:web服務(wù)器啟動時或web服務(wù)器接收到請求時呻疹,或者兩者之間的某個時刻啟動。初始化工作有init()方法負(fù)責(zé)執(zhí)行完成语淘;
(3)诲宇、調(diào)用:從第一次到以后的多次訪問际歼,都是只調(diào)用doGet()或doPost()方法惶翻;
(4)、銷毀:停止服務(wù)器時調(diào)用destroy()方法鹅心,銷毀實例吕粗。
2、filter:(一定要實現(xiàn)javax.servlet包的Filter接口的三個方法init()旭愧、doFilter()颅筋、destroy(),空實現(xiàn)也行)
(1)输枯、啟動服務(wù)器時加載過濾器的實例议泵,并調(diào)用init()方法來初始化實例;
(2)桃熄、每一次請求時都只調(diào)用方法doFilter()進(jìn)行處理先口;
(3)、停止服務(wù)器時調(diào)用destroy()方法瞳收,銷毀實例碉京。
三、職責(zé)
1螟深、servlet
創(chuàng)建并返回一個包含基于客戶請求性質(zhì)的動態(tài)內(nèi)容的完整的html頁面谐宙;
創(chuàng)建可嵌入到現(xiàn)有的html頁面中的一部分html頁面(html片段);
讀取客戶端發(fā)來的隱藏數(shù)據(jù)界弧;
讀取客戶端發(fā)來的顯示數(shù)據(jù)凡蜻;
與其他服務(wù)器資源(包括數(shù)據(jù)庫和java的應(yīng)用程序)進(jìn)行通信搭综;
通過狀態(tài)代碼和響應(yīng)頭向客戶端發(fā)送隱藏數(shù)據(jù)。
2划栓、filter:
filter能夠在一個請求到達(dá)servlet之前預(yù)處理用戶請求设凹,也可以在離開servlet時處理http響應(yīng):
在執(zhí)行servlet之前,首先執(zhí)行filter程序茅姜,并為之做一些預(yù)處理工作闪朱;
根據(jù)程序需要修改請求和響應(yīng);
在servlet被調(diào)用之后截獲servlet的執(zhí)行
四钻洒、區(qū)別:
1奋姿、servlet 流程是短的,url傳來之后素标,就對其進(jìn)行處理称诗,之后返回或轉(zhuǎn)向到某一自己指定的頁面。它主要用來在 業(yè)務(wù)處理之前進(jìn)行控制.
2头遭、filter 流程是線性的寓免, url傳來之后,檢查之后计维,可保持原來的流程繼續(xù)向下執(zhí)行袜香,被下一個filter, servlet接收等,而servlet 處理之后鲫惶,不會繼續(xù)向下傳遞蜈首。filter功能可用來保持流程繼續(xù)按照原來的方式進(jìn)行下去,或者主導(dǎo)流程欠母,而servlet的功能主要用來主導(dǎo)流程欢策。
filter可用來進(jìn)行字符編碼的過濾,檢測用戶是否登陸的過濾赏淌,禁止頁面緩存等
17.攔截器和過濾器的區(qū)別
①攔截器是基于java的反射機(jī)制的踩寇,而過濾器是基于函數(shù)回調(diào)。
②攔截器不依賴與servlet容器六水,過濾器依賴與servlet容器缩擂。
③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用胯盯。
④攔截器可以訪問action上下文懈费、值棧里的對象憎乙,而過濾器不能訪問票罐。
⑤在action的生命周期中,攔截器可以多次被調(diào)用该押,而過濾器只能在容器初始化時被調(diào)用一次阵谚。
⑥攔截器可以獲取IOC容器中的各個bean梢什,而過濾器就不行,這點很重要囤躁,在攔截器里注入一個service狸演,可以調(diào)用業(yè)務(wù)邏輯宵距。
Spring的攔截器與Servlet的Filter有相似之處中姜,比如二者都是AOP編程思想的體現(xiàn)丢胚,都能實現(xiàn)權(quán)限檢查携龟、日志記錄等勘高。
不同的是:
使用范圍不同:Filter是Servlet規(guī)范規(guī)定的华望,只能用于Web程序中赖舟。而攔截器既可以用于Web程序,也可以用于Application子漩、Swing程序中幢泼。
規(guī)范不同:Filter是在Servlet規(guī)范中定義的缕棵,是Servlet容器支持的招驴。而攔截器是在Spring容器內(nèi)的忽匈,是Spring框架支持的。
使用的資源不同:同其他的代碼塊一樣郭厌,攔截器也是一個Spring的組件折柠,歸Spring管理扇售,配置在Spring文件中承冰,因此能使用Spring里的任何資源困乒、對象娜搂,例如Service對象百宇、數(shù)據(jù)源秘豹、事務(wù)管理等,通過IoC注入到攔截器即可婚苹;而Filter則不能膊升。
深度不同:Filter在只在Servlet前后起作用廓译。而攔截器能夠深入到方法前后非区、異常拋出前后等征绸,因此攔截器的使用具有更大的彈性管怠。所以在Spring構(gòu)架的程序中渤弛,要優(yōu)先使用攔截器她肯。
實際上Filter和Servlet極其相似晴氨,區(qū)別只是Filter不能直接對用戶生成響應(yīng)瑞筐。實際上Filter里doFilter()方法里的代碼就是從多個Servlet的service()方法里抽取的通用代碼,通過使用Filter可以實現(xiàn)更好的復(fù)用闰非。
filter是一個可以復(fù)用的代碼片段财松,可以用來轉(zhuǎn)換HTTP請求辆毡、響應(yīng)和頭信息舶掖。Filter不像Servlet,它不能產(chǎn)生一個請求或者響 應(yīng)主慰,它只是修改對某一資源的請求共螺,或者修改從某一的響應(yīng)藐不。
18.數(shù)據(jù)庫設(shè)計6個注意點+2點總結(jié)
1雏蛮、主鍵與外鍵
一般而言底扳,一個實體不能既無主鍵又無外鍵衷模。沒有主鍵就沒有實體阱冶。
2木蹬、區(qū)別對待不同的表
基本表與統(tǒng)計表镊叁、中間表晦譬、臨時表等不同敛腌,有以下特性
a像樊、原始性生棍∽闵穑基本表中的記錄是原始數(shù)據(jù)(基礎(chǔ)數(shù)據(jù))的記錄氢妈。
b首量、演繹性加缘。由基本按照一定的業(yè)務(wù)原則可以生成統(tǒng)計表和臨時表的數(shù)據(jù)拣宏。
c勋乾、穩(wěn)定性学歧≈Ρ浚基本表的結(jié)構(gòu)是相對穩(wěn)定的横浑,表中的記錄是要長期保存的伪嫁。
所以在設(shè)計數(shù)據(jù)庫的時候,要盡量將基本表和其它中間表似舵、統(tǒng)計表區(qū)別開來砚哗。應(yīng)盡量滿足第三范式蛛芥。其它表可以適當(dāng)?shù)慕档头妒浇鍪纭5遣还茉鯓由南剩瑵M足第三范式的數(shù)據(jù)庫設(shè)計银酬,往往不是最好的設(shè)計揩瞪。為了提高數(shù)據(jù)庫的運(yùn)行效率李破,常常需要降低范式標(biāo)準(zhǔn):適當(dāng)增加冗余喷屋,達(dá)到以空間換時間的目的。
3恶耽、范式理解和冗余的分類
第一范式:1NF是對屬性的原子性約束偷俭,要求屬性具有原子性涌萤,不可再分解负溪;
第二范式:2NF是對記錄的惟一性約束辐真,要求記錄有惟一標(biāo)識侍咱,即實體的惟一性楔脯;
第三范式:3NF是對字段冗余性的約束淤年,即任何字段不能由其他字段派生出來,它要求字段沒有冗余弄诲。
有時為了提高運(yùn)行效率齐遵,就必須降低范式標(biāo)準(zhǔn)梗摇,適當(dāng)保留冗余數(shù)據(jù)伶授。具體做法是:在概念數(shù)據(jù)模型設(shè)計時遵守第三范式糜烹,降低范式標(biāo)準(zhǔn)的工作放到物理數(shù)據(jù)模型設(shè)計時考慮疮蹦。降低范式就是增加字段愕乎,允許冗余慎玖。
但是冗余是有區(qū)別的,主鍵與外鍵在多表中的重復(fù)出現(xiàn), 不屬于數(shù)據(jù)冗余薪前,這個概念必須清楚示括,事實上有許多人還不清楚。
a吼拥、非鍵字段的重復(fù)出現(xiàn), 才是數(shù)據(jù)冗余凿可!而且是一種低級冗余,即重復(fù)性的冗余敛助。
b纳击、高級冗余不是字段的重復(fù)出現(xiàn),而是字段的派生出現(xiàn)百匆。
〖例4〗:商品中的“單價加匈、數(shù)量纵东、金額”三個字段偎球,“金額”就是由“單價”乘以“數(shù)量”派生出來的,它就是冗余猫牡,而且是一種高級冗余。冗余的目的是為了提高處理速度震庭。只有低級冗余才會增加數(shù)據(jù)的不一致性归薛,因為同一數(shù)據(jù),可能從不同時間千元、地點幸海、角色上多次錄入。因此挡篓,我們提倡高級冗余(派生性冗余)秽澳,反對低級冗余(重復(fù)性冗余)担神。
反規(guī)范設(shè)計的數(shù)據(jù)需要額外的工作來維護(hù)數(shù)據(jù)的完整性,一般可以通過以下幾種方式進(jìn)行
a捞挥、應(yīng)用邏輯
在應(yīng)用程序的事務(wù)中對同一數(shù)據(jù)的多處存儲進(jìn)行維護(hù)。這種方式比較難于管理忧吟,一個維護(hù)邏輯很容易出現(xiàn)在多個應(yīng)用程序當(dāng)中,容易遺漏斩披。
b溜族、批處理維護(hù)
由批處理程序批量的處理所有的非規(guī)范化關(guān)系涉及的數(shù)據(jù)。一般定期運(yùn)行垦沉,運(yùn)行間隔根據(jù)業(yè)務(wù)來決定,并且可以利用Job來自動運(yùn)行批處理程序厕倍」炎常可用于對冗余數(shù)據(jù)的實時性要求不高或者有一定規(guī)則的環(huán)境。
c讹弯、觸發(fā)器
在數(shù)據(jù)庫端建立觸發(fā)器况既,對原數(shù)據(jù)的修改會立即觸發(fā)對冗余列的修改∽槊瘢可用于對數(shù)據(jù)實時性要求較高的環(huán)境棒仍,但同時會降低數(shù)據(jù)的插入和更新速度。
4臭胜、重視視圖莫其、物化視圖技術(shù)在數(shù)據(jù)庫的使用
a、簡化查詢
b耸三、隱藏數(shù)據(jù)庫結(jié)構(gòu)乱陡,權(quán)限管理,安全
c仪壮、物化視圖進(jìn)行數(shù)據(jù)預(yù)準(zhǔn)備憨颠,性能
5、數(shù)據(jù)完整性
盡量在表級約束條件(5個=2列級+2表級+1表間)實現(xiàn)睛驳,實現(xiàn)不了的復(fù)雜業(yè)務(wù)約束再進(jìn)行觸發(fā)器和存儲過程實現(xiàn)烙心。
6膜廊、要善于識別與正確處理多對多的關(guān)系
若兩個實體之間存在多對多的關(guān)系,則應(yīng)消除這種關(guān)系淫茵。消除的辦法是爪瓜,在兩者之間增加第三個實體。這樣匙瘪,原來一個多對多的關(guān)系铆铆,現(xiàn)在變?yōu)閮蓚€一對多的關(guān)系。要將原來兩個實體的屬性合理地分配到三個實體中去丹喻。這里的第三個實體薄货,實質(zhì)上是一個較復(fù)雜的關(guān)系,它對應(yīng)一張基本表碍论。一般來講谅猾,數(shù)據(jù)庫設(shè)計工具不能識別多對多的關(guān)系,但能處理多對多的關(guān)系鳍悠。
〖例3〗:在“圖書館信息系統(tǒng)”中税娜,“圖書”是一個實體,“讀者”也是一個實體藏研。這兩個實體之間的關(guān)系敬矩,是一個典型的多對多關(guān)系:一本圖書在不同時間可以被多個讀者借閱,一個讀者又可以借多本圖書蠢挡。為此弧岳,要在二者之間增加第三個實體,該實體取名為“借還書”业踏,它的屬性為:借還時間禽炬、借還標(biāo)志(0表示借書,1表示還書)堡称,另外瞎抛,它還應(yīng)該有兩個外鍵(“圖書”的主鍵,“讀者”的主鍵)却紧,使它能與“圖書”和“讀者”連接桐臊。
===================================================================================
1、 防止數(shù)據(jù)庫設(shè)計打補(bǔ)丁的方法是“三少原則”
(1) 一個數(shù)據(jù)庫中表的個數(shù)越少越好晓殊。只有表的個數(shù)少了断凶,才能說明系統(tǒng)的E--R圖少而精,去掉了重復(fù)的多余的實體巫俺,形成了對客觀世界的高度抽象认烁,進(jìn)行了系統(tǒng)的數(shù)據(jù)集成,防止了打補(bǔ)丁式的設(shè)計;
(2) 一個表中組合主鍵的字段個數(shù)越少越好却嗡。因為主鍵的作用舶沛,一是建主鍵索引,二是做為子表的外鍵窗价,所以組合主鍵的字段個數(shù)少了如庭,不僅節(jié)省了運(yùn)行時間,而且節(jié)省了索引存儲空間撼港;
(3) 一個表中的字段個數(shù)越少越好坪它。只有字段的個數(shù)少了,才能說明在系統(tǒng)中不存在數(shù)據(jù)重復(fù)帝牡,且很少有數(shù)據(jù)冗余往毡,更重要的是督促讀者學(xué)會“列變行”,這樣就防止了將子表中的字段拉入到主表中去靶溜,在主表中留下許多空余的字段开瞭。所謂“列變行”,就是將主表中的一部分內(nèi)容拉出去罩息,另外單獨建一個子表惩阶。這個方法很簡單,有的人就是不習(xí)慣扣汪、不采納、不執(zhí)行锨匆。
數(shù)據(jù)庫設(shè)計的實用原則是:在數(shù)據(jù)冗余和處理速度之間找到合適的平衡點崭别。“三少”是一個整體概念恐锣,綜合觀點茅主,不能孤立某一個原則。該原則是相對的土榴,不是絕對的诀姚。“三多”原則肯定是錯誤的玷禽。試想:若覆蓋系統(tǒng)同樣的功能赫段,一百個實體(共一千個屬性) 的E--R圖,肯定比二百個實體(共二千個屬性) 的E--R圖矢赁,要好得多糯笙。
提倡“三少”原則,是叫讀者學(xué)會利用數(shù)據(jù)庫設(shè)計技術(shù)進(jìn)行系統(tǒng)的數(shù)據(jù)集成撩银。數(shù)據(jù)集成的步驟是將文件系統(tǒng)集成為應(yīng)用數(shù)據(jù)庫给涕,將應(yīng)用數(shù)據(jù)庫集成為主題數(shù)據(jù)庫,將主題數(shù)據(jù)庫集成為全局綜合數(shù)據(jù)庫。集成的程度越高够庙,數(shù)據(jù)共享性就越強(qiáng)恭应,信息孤島現(xiàn)象就越少,整個企業(yè)信息系統(tǒng)的全局E—R圖中實體的個數(shù)耘眨、主鍵的個數(shù)昼榛、屬性的個數(shù)就會越少。
提倡“三少”原則的目的毅桃,是防止讀者利用打補(bǔ)丁技術(shù)褒纲,不斷地對數(shù)據(jù)庫進(jìn)行增刪改,使企業(yè)數(shù)據(jù)庫變成了隨意設(shè)計數(shù)據(jù)庫表的“垃圾堆”钥飞,或數(shù)據(jù)庫表的“大雜院”莺掠,最后造成數(shù)據(jù)庫中的基本表、代碼表读宙、中間表彻秆、臨時表雜亂無章,不計其數(shù)结闸,導(dǎo)致企事業(yè)單位的信息系統(tǒng)無法維護(hù)而癱瘓唇兑。
2、提高數(shù)據(jù)庫運(yùn)行效率的辦法
在給定的系統(tǒng)硬件和系統(tǒng)軟件條件下桦锄,提高數(shù)據(jù)庫系統(tǒng)的運(yùn)行效率的辦法是:
(1) 在數(shù)據(jù)庫物理設(shè)計時扎附,降低范式,增加冗余, 少用觸發(fā)器, 多用存儲過程结耀。
(2) 當(dāng)計算非常復(fù)雜留夜、而且記錄條數(shù)非常巨大時(例如一千萬條),復(fù)雜計算要先在數(shù)據(jù)庫外面图甜,以文件系統(tǒng)方式用C++語言計算處理完成之后碍粥,最后才入庫追加到表中去。這是電信計費系統(tǒng)設(shè)計的經(jīng)驗黑毅。
(3) 發(fā)現(xiàn)某個表的記錄太多嚼摩,例如超過一千萬條,則要對該表進(jìn)行水平分割(oracle的分區(qū)表很強(qiáng)大矿瘦,可代替此操作)枕面。水平分割的做法是,以該表主鍵PK的某個值為界線匪凡,將該表的記錄水平分割為兩個表膊畴。若發(fā)現(xiàn)某個表的字段太多甥桂,例如超過八十個喧笔,則垂直分割該表凹蜂,將原來的一個表分解為兩個表。
(4) 對數(shù)據(jù)庫管理系統(tǒng)DBMS進(jìn)行系統(tǒng)優(yōu)化肌括,即優(yōu)化各種系統(tǒng)參數(shù)裤园,如緩沖區(qū)個數(shù)询筏。
(5) 在使用面向數(shù)據(jù)的SQL語言進(jìn)行程序設(shè)計時破花,盡量采取優(yōu)化算法。
總之玉控,要提高數(shù)據(jù)庫的運(yùn)行效率飞主,必須從數(shù)據(jù)庫系統(tǒng)級優(yōu)化、數(shù)據(jù)庫設(shè)計級優(yōu)化高诺、程序?qū)崿F(xiàn)級優(yōu)化碌识,這三個層次上同時下功夫。
19.mysql ACID與四種隔離級別歸納總結(jié)
A(atomicity)原子性:
即事務(wù)要么全部做完虱而,要么全部不做筏餐,不會出現(xiàn)只做一部分的情形,如A給B轉(zhuǎn)帳牡拇,不會出現(xiàn)A的錢少了魁瞪,B的錢卻沒有增加的情況
C(consistency)一致性:
指的是事務(wù)從一個狀態(tài)到另一個狀態(tài)是一致的,如A減少了100惠呼,B不可能只增加30导俘。
I(isolation)隔離性:
即一個事務(wù)在沒有完成數(shù)據(jù)的提交修改時,對其它事務(wù)是不可見的剔蹋。當(dāng)然這里有個隔離級別的概念旅薄,在不同隔離級別下,這里會有不同的表現(xiàn)形式
D(durability)持久性:
一旦事務(wù)提交泣崩,則所做修改就會被永久保存到數(shù)據(jù)庫中赋秀。
在說隔離級別之前,我們先說如下幾個概念:
臟讀:
一個事務(wù)對數(shù)據(jù)進(jìn)行增刪改律想,但并沒有提交,但另一事務(wù)卻能讀到未提交的數(shù)據(jù)
不可重復(fù)讀:
一事務(wù)對數(shù)據(jù)進(jìn)行了更新或刪除操作绍弟,另一事務(wù)兩次查詢的數(shù)據(jù)不一致
幻讀:
一事務(wù)對數(shù)據(jù)進(jìn)行了新增操作技即,另一事務(wù)兩次查詢結(jié)果不一致。
我們看到不可重復(fù)讀與幻讀好像好類似樟遣,但其實它們是有很大的不同而叼,不可重復(fù)讀主要體現(xiàn)在update與delete,而幻讀主要體現(xiàn)在insert豹悬,從實現(xiàn)層面上講葵陵,要解決不可重復(fù)讀,我們只需要對查詢的數(shù)據(jù)進(jìn)行加鎖就可以實現(xiàn)瞻佛,此時update與delete這些行都會阻塞等待脱篙,但是insert依舊可以娇钱,避免不了幻讀,而要解決幻讀绊困,必須對其行與行之前也加鎖文搂,在mysql中,是通過next key lock(行鎖+gap lock)來實現(xiàn)的秤朗。
隔離級別:
read uncommited未提交讀:
隔離級別為0煤蹭,會有臟讀,不可重復(fù)讀取视,幻讀
read commit提交讀:
隔離級別為1硝皂,不會有臟讀,但有不可重復(fù)讀作谭,幻讀
repeatable read可重復(fù)讀:
隔離級別為2稽物,不會有臟讀,不可重復(fù)讀丢早,但依舊會有幻讀姨裸。但為什么說mysql中的repeatable read解決了幻讀?本來是會有幻讀的怨酝,但是它采用了next key lock加上for update來避免傀缩,InnoDB提供了這樣一種機(jī)制,通過加鎖去查詢可以得到最新的數(shù)據(jù)农猬,如兩個事務(wù)同時開啟赡艰,A事務(wù)插入了一條數(shù)據(jù),并提交斤葱,B事務(wù)去查select * from t慷垮,此時B是不能查詢到A事務(wù)提交的數(shù)據(jù)的,但是加多一個for update揍堕,即select * from t for update料身,就能查找剛剛A事務(wù)插入的數(shù)據(jù)。所以我們才說mysql在repeatable read隔離級別下可以避免幻讀的原因衩茸,記得加for update芹血。
serializable可序列化:
隔離級別為3,不會有臟讀楞慈,不可重復(fù)讀幔烛,幻讀。但效率最低囊蓝,并發(fā)性能最差饿悬,一般情況下不會使用。
20.java虛擬機(jī)類加載機(jī)制
加載:階段主要完成三件事聚霜,即通過一個類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流狡恬,將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時數(shù)據(jù)結(jié)構(gòu)珠叔,在Java堆中生成一個代表此類的Class對象,作為訪問方法區(qū)這些數(shù)據(jù)的入口傲宜。
驗證:確保Class文件的字節(jié)流中包含信息符合當(dāng)前虛擬機(jī)要求运杭,不會危害虛擬機(jī)自身安全。主要包括四種驗證:文件格式驗證函卒、元數(shù)據(jù)驗證辆憔、字節(jié)碼驗證、符號引用驗證报嵌。
準(zhǔn)備:僅僅為類變量(即static修飾的字段變量)分配內(nèi)存并且設(shè)置該類變量的初始值即零值虱咧,這里不包含用final修飾的static,因為final在編 譯的時候就會分配了锚国,同時這里也不會為實例變量分配初始化腕巡。類變量會分配在方法區(qū)中,而實例變量是會隨著對象一起分配到Java堆中血筑。
解析:主要就是將常量池中的符號引用替換為直接引用的過程绘沉。
初始化:階段依舊是初始化類變量和其他資源,這里將執(zhí)行用戶的static字段和靜態(tài)語句塊的賦值操作豺总。這個過程就是執(zhí)行類構(gòu)造器方法的過程车伞。
類加載器的分類:啟動類加載器、擴(kuò)展類類加載器喻喳、應(yīng)用程序類加載器另玖。
21.Lock和synchronized有以下幾點不同
1).Lock是一個接口,而synchronized是Java中的關(guān)鍵字表伦,synchronized是內(nèi)置的語言谦去;
2).synchronized在發(fā)生異常時,會自動釋放線程占有的鎖蹦哼,因此不會導(dǎo)致死鎖現(xiàn)象的發(fā)生鳄哭;而Lock在發(fā)生異常時,如果沒有主動通過unlock()去釋放鎖纲熏,而很可能造成死鎖的現(xiàn)象窃诉,因此使用Lock時需要在finally塊中釋放鎖;
3).Lock可以讓等待鎖的線程響應(yīng)中斷赤套,而synchronized卻不行,使用synchronized時珊膜,等待的線程會一直等待下去容握,不能夠響應(yīng)中斷;
4).通過Lock可以知道有沒有成功獲取鎖车柠,而synchronized卻無法辦到剔氏。
5).Lock可以提高多個線程進(jìn)行讀操作的效率塑猖。
在性能上來說,如果競爭資源不激烈谈跛,兩者的性能是差不多的羊苟,而當(dāng)競爭資源非常激烈時(即有大量線程同時競爭),此時Lock的性能要遠(yuǎn)遠(yuǎn)優(yōu)于synchronized感憾。所以說蜡励,在具體使用時要根據(jù)適當(dāng)情況選擇。
22.緩存穿透阻桅,緩存擊穿凉倚,緩存雪崩解決方案分析
緩存穿透
緩存穿透是指查詢一個一定不存在的數(shù)據(jù),由于緩存是不命中時被動寫的嫂沉,并且出于容錯考慮稽寒,如果從存儲層查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個不存在的數(shù)據(jù)每次請求都要到存儲層去查詢趟章,失去了緩存的意義杏糙。在流量大時,可能DB就掛掉了蚓土,要是有人利用不存在的key頻繁攻擊我們的應(yīng)用宏侍,這就是漏洞。
解決方案
有很多種方法可以有效地解決緩存穿透問題北戏,最常見的則是采用布隆過濾器负芋,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被 這個bitmap攔截掉嗜愈,從而避免了對底層存儲系統(tǒng)的查詢壓力旧蛾。另外也有一個更為簡單粗暴的方法(我們采用的就是這種),如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù) 據(jù)不存在蠕嫁,還是系統(tǒng)故障)锨天,我們?nèi)匀话堰@個空結(jié)果進(jìn)行緩存,但它的過期時間會很短剃毒,最長不超過五分鐘病袄。
緩存雪崩
緩存雪崩是指在我們設(shè)置緩存時采用了相同的過期時間,導(dǎo)致緩存在某一時刻同時失效赘阀,請求全部轉(zhuǎn)發(fā)到DB益缠,DB瞬時壓力過重雪崩。
解決方案
緩存失效時的雪崩效應(yīng)對底層系統(tǒng)的沖擊非郴可怕幅慌。大多數(shù)系統(tǒng)設(shè)計者考慮用加鎖或者隊列的方式保證緩存的單線 程(進(jìn)程)寫,從而避免失效時大量的并發(fā)請求落到底層存儲系統(tǒng)上轰豆。這里分享一個簡單方案就時講緩存失效時間分散開胰伍,比如我們可以在原有的失效時間基礎(chǔ)上增加一個隨機(jī)值齿诞,比如1-5分鐘隨機(jī),這樣每一個緩存的過期時間的重復(fù)率就會降低骂租,就很難引發(fā)集體失效的事件祷杈。