通用技術方面
MVC
1)概念
MVC是一個架構模式,它分離了表現與交互。它被分為三個核心部件:模型-model、視圖-view、控制器-controller
2)工作原理
所有的終端用戶請求被發送到控制器。
控制器依賴請求去選擇加載哪個模型,並把模型附加到對應的視圖。
附加了模型數據的最終視圖做為響應發送給終端用戶。
struts2
1)struts2的基本流程
spring
1)IOC概念
將在編譯階段還不能確定的類的調用關系,放在配置文件中,在執行階段動態調用。
2)AOP概念
默認使用java動態代理實現
3)作用域
- singleton:單實例
- prototype:一個bean可以定義多個實例。
- request:每次HTTP請求都會創建一個新的Bean。
- session:一個HTTP Session定義一個Bean。
- globalSession:同一個全局HTTP Session定義一個Bean。
bean默認的scope屬性是’singleton‘。
4)事務
Spring本身不實現事務,而是為不同的事務API(如JTA, JDBC, Hibernate, JPA, 和JDO)提供了統一的編程模型。
5)Spring 中的設計模式
單例模式:jdbc connectionter
代理模式:AOP
工廠模式:用SpringFactory創建特定的bean
觀察者模式:根據SpringContext的配置方式,決定AOP的模式
hibernate
1)get和load的不同
get:如果緩存中沒有,hibernate將會直接訪問數據庫,並初始化一個持久化對象
load:如果緩存中沒有,hibernate將會創建代理對象,只有真正需要使用這個對象的時候,參會從數據庫中加載數據,即延遲加載。
2)save、persist和saveOrUpdate以及update比較
save:只能insert記錄,返回的是Serializable對象
saveOrUpdate:既能insert,也能update
persist:返回的是void
update()和saveOrUpdate()是用來對跨Session的PO進行狀態管理的。
update()方法操作的對象必須是持久化了的對象。也就是說,如果此對象在數據庫中不存在的話,就不能使用update()方法
saveOrUpdate()方法操作的對象既可以使持久化了的,也可以使沒有持久化的對象。如果是持久化了的對象調用saveOrUpdate()則會 更新數據庫中的對象;如果是未持久化的對象使用此方法,則save到數據庫中。
3)瞬態,游離態,持久態如何轉換
剛new出一個對象,還未保存到數據庫,是瞬態
調用save()保存進數據庫,就成了持久態(即session緩存中的狀態)
當關閉session后,數據庫中有,session中沒有,叫游離態
4)Hibernate並發控制
問題:hibernate中的session是線程非安全的,如果多個線程共享將導資源爭用,進而導致臟讀,幻讀等問題
解決方案:設置JDBC事務隔離級別
Serializable:串行化。隔離級別最高
Repeatable Read:可重復讀
Read Committed:已提交數據讀 (默認)
Read Uncommitted:未提交數據讀。隔離級別最差
設置鎖:樂觀鎖和悲觀鎖。
樂 觀鎖:使用版本號或時間戳來檢測更新丟失
悲觀鎖:Hibernate總是使用數據庫的鎖定機制,從不在內存中鎖定對象
redis/cache
1)虛擬內存
當你的key很小而value很大時,使用VM的效果會比較好
當你的key不小時,可以考慮將key,value組合成一個新的value.
vm-max-threads這個參數,可以設置訪問swap文件的線程數,設置最好不要超過機器的核數,如果設置為0,那么所有對swap文件的操作都是串行的.可能會造成比較長時間的延遲,但是對數據完整性有很好的保證.
2)分布式
a)讀寫分離——主從模式
redis支持主從的模式。原則:Master會將數據同步到slave,而slave不會將數據同步到master。Slave啟動時會連接master來同步數據。
通過增加Slave DB的數量,讀的性能可以線性增長。為了避免Master DB的單點故障,集群一般都會采用兩台Master DB做雙機熱備,所以整個集群的讀和寫的可用性都非常高,但是集群的擴展能力受限於單個節點的存儲能力。
b)數據分片(類似數據庫水平拆分)
分布式總結:結合上面兩種模型,可以將每個master設計成由一個master和多個slave組成的模型。
3)MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略,有以下幾種策略
隨機淘汰
淘汰最少使用的
淘汰過期數據集中最少使用的
淘汰將要過期的
4)redis性能問題
寫內存快照會阻塞主線程,因此master最好不要寫快照
重寫AOF會占用高內存,且AOF文件過大會影響master重啟和恢復速度,因此maste人最好不要做任何持久化工作,包括內存快照和aof,二用slave執行aof
主從最好在同一局域網內提高主從復制的性能
5)redis適用場景
Redis最適合所有數據in-momory的場景而不是持久化,相當於加強版的memcache
A)會話緩存,例如購物車信息,可以持久化
B)全頁緩存
C)做隊列使用
D)排行榜和計數器
E)發布訂閱
6)如果出對列阻塞了怎么辦
redis分片,縮短單個隊列長度
優化consomer,調查處理慢的原因
增加consumer(即分布式的集群服務器)
允許請求超時 /失敗,做好失敗后處理
做好內存報警和配置好內存回收策略
jms,消息隊列
1)特性
異步通信,松耦合的系統集成
websphere MQ是FIFO的,AWS的MQ是random的
並發性能
我們公司面試也經常問這種問題,很多人答很大面的東西,例如JVM調優,負載均衡,但是作為一個程序員,有誰專門在這方面下過功夫,有的人說做過jvm調優,但是一問細節,又說不上來。
做為編碼的程序員,更重要的是應用程序的設計,如何寫出高效的sql,如何占用最小的內存,如何把某些程序在后台異步操作。面試的時候說一說你日常工作的時候這方面的經驗,也能很好的回答這個問題。
1)性能通用解決方案
前端:異步請求+資源靜態化+cdn
后端:請求隊列(如12306)+輪詢分發+F5負載均衡+共享緩存
數據層:redis緩存+數據分表+寫隊列+存儲過程(減少跟客戶端交互的IO)
存儲:raid陣列+熱備
網絡:dns輪詢+DDOS攻擊防護
2)數據庫解決方案
最基本的:建立索引
100萬數據:主從數據庫(讀寫分離,主從復制同步),slave上可以做集群
1000萬數據:數據庫水平拆分,按uid拆分
注意問題
id使用通用算法集中分配
做好數據庫性能監控
不要用長連接,盡量使用連接池。
3)緩存
CND
靜態頁面緩存
動靜分離,圖片,視頻,附件等使用專用服務器
5)前沿解決方案:雲平台——可伸縮擴展,快速熱部署,內存數據,
12306如何解決並發的
並發性能的問題和原因
A.帶寬問題 1.5G的帶寬大約支持1萬PV,
B.服務器集群難以伸縮擴展
C.事務不一致性,12306十分鍾才更新一次余票,期間已經售出很多。2012年處理能力為400-500TPS,有效請求卻高於3000QPS
D.計算量巨大:線路多,車次多,車站多,坐席多,票種多,導致10分鍾才能計算完一次余票
12306雲技術升級
http://www.csdn.net/article/2015-02-10/2823900
http://storage.it168.com/a2012/0217/1313/000001313424_all.shtml
傳統的解決方案
優化架構
1)利用第三方平台登錄來緩解並發壓力,例如新浪,騰訊,阿里等
2)第三方售票平台應該以消息隊列方式,異步地與12306進行集成。 對於登錄的消息隊列,可以在12306批量授權處理(有點類似數據庫存儲過程,減少與客戶端交互的io損耗)
優化軟件
使用線程池和事件驅動處理尖峰請求,可以通過下游負載指標反饋來決定上游處理,對於太老的請求,直接拒絕。
使用KV內存數據庫來緩存余票,只有當數據庫中本車次無票(或者小於n張)才去同步一次緩存
緩存的更新是基於數據庫余票數主動觸發,只有當無票(或者低於n張票)才觸發,而不是根據用戶查詢而觸發,因此可以大幅減少緩存更新頻率
可以基於查詢結果生成靜態頁面緩存起來,設置失效時間,或者由數據庫余票出發頁面失效,完全由CDN或者redis來承擔查詢壓力
增強防作弊機制,在web層對IP做限制,對UID做限制
數據庫層優化
主從數據庫(讀寫分離)
數據庫水平拆分
優化隊列
隊列不能操作鎖
設置隊列等待時間(15分鍾后未處理完的事務直接終止)
設計分布式隊列(因為排隊的人並不一定買的相同車次,沒必要跟着人家一起排隊,而是讓相同車次的人排同一個隊列)
Pivotal Gemfire的解決方案:雲
2012年,業務復雜:路線多,火車站多,坐席多,票等級多,組合就多。使用很多服務器。
2013年,使用Gemfire集群進行余票計算,可以2分鍾刷新一次余票數據
2014年,將訂單生成和訂單查詢分庫處理,將查詢的熱點數據放在Gemfire集群,同時提高了訂單生成和查詢速度
2015年,單獨分出余票查詢服務器群(以前是64台,現在是是幾台雲服務器搭建的上百部虛擬機,節約成本),並與web服務器集群,應用服務器集群一起部署到阿里雲
並發事務
JVM內存結構,GC算法,性能優化
類的生命周期
1)將.class文件加載到內存,生成Class對象——類加載
2)類連接(驗證,准備,解析)
3)初始化:靜態變量賦值
4)使用
5)卸載:垃圾回收
三種類加載器
啟動加載器(jvm),擴展加載器(基礎庫),應用加載器(程序代碼)
加載機制
全盤負責,父類委托,緩存機制
JVM內存結構
三大塊:堆,棧,方法區
堆又分為:年輕代和老年代
年輕代又分為:Eden,from,to
--------
方法區存儲常量,靜態變量,類信息
棧區:存放臨時變量,方法參數
--------
對象引用判斷
引用技術(新增引用時+1,引用釋放時-1,但互相引用的對象則無法計算)
可達性分析
GC算法
標記清除算法
復制算法
分代收集算法
對象分配法則(GC優化法則)
1)優先分配在Eden區,如果Eden區沒有足夠的空間時,執行一次Minor GC,Eden采用復制算法收集內存
2)大對象直接進入老年代,避免在年輕代頻繁進行內存拷貝
3)長期存活的對象進入老年代,因為年輕代的對象隨着年齡增加,最終會進入老年代內存區
4)空間分配擔保。每次進行Minor GC時,JVM會計算Survivor區移至老年區的對象的平均大小,如果這個值大於老年區的剩余值大小則進行一次Full GC
數據庫性能
存儲過程
執行存儲過程是為了1)利用服務器往往具有強大的計算能力和速度,2)避免把大量的數據下載到客戶端,減少網絡上的傳輸量,3)只需要一次編譯,4)方便事務處理
觸發器
1)概念
就是一組由特定條件觸發執行的操作語句。
2)分類
行級:每條記錄都觸發
語句級:指定操作之前或之后觸發
3)應用場景
進行安全檢查(例如數據更新前的權限檢查)
數據同步或者備份(主表更新后, 備份表也更新)
生成自定義ID列:第一步創建一個sequence,用來自定義ID格式,第二步在目標表上面創建觸發器,每當插入數據時,就取sequence的next值
記錄用戶操作(工作流系統中的追蹤,審計)
項目方面
IBE流程
Payment流程
單點登錄
數字證書
communicate service
MPO
重大故障
寫日志導致的故障
故障描述:service頻繁time out, 無法search flight,無法訂票
問題分析:disk io high utilization, terracotta and JVM reject rejoin, was server high CPU, MQ and service error log
分析過程:
懷疑WAS 上的IBE和 WMB 上的MQ通信出故障
MQ connection error and time out, 可能有阻塞,重啟WMB,無效, 2)重啟WAS JVM, 無效,
root cause:
solution
1.限制層數
2.限制表查詢條件
3.緩存結果
