2020最新java面試題庫(杭州)
目 錄
1.常見的集合有哪些?都有什麼區別: 1
2.HashMap的底層原理: 1
3.sleep和wait的區別 1
4.run方法和start方法的區別: 1
5.Threadlocad的作用: 2
6.solr查詢出的資料放在哪: 本地 磁碟中 2
7.為什麼用solr和其他的區別在哪:https://blog.csdn.net/jokeylin/article/details/80562148 2
8.支付寶的支付流程: 2
9.資料庫有幾種索引: 3
10redis五種資料型別和應用場景 3
11執行緒池工作原理: 4
12Gc(垃圾回收機制)的四種演算法 4
13Spring ioc和aop 原理 4
14設計模式; 5
15.Redis持久化: 5
16.悲觀鎖和樂觀鎖 5
17.springmvc的工作原理: 5
18.索引過多會引發什麼: 6
19.手寫冒泡: 6
20.在開發中於遇到的困難,怎麼解決的,有什麼收穫 6
21.談談集合? 6
22.Hashmap的底層原理? 7
23.有對hashmap初始容量進行修改過嗎?修改原理初始容量? 7
24.多執行緒中使用的集合有哪些是執行緒安全的? 7
25.專案中有涉及多執行緒嗎?採用什麼方法建立執行緒?(建立執行緒的集中方式) 8
26.資料庫用的什麼連線的? 8
27.在哪種場景下使用的多執行緒?(回答訂單)用在訂單的使用者量很大為什麼使用建立執行緒沒有使用建立執行緒池? 8
28.執行緒的生命週期? 8
29.說下Ioc Aop 和專案中用到的地方? 10
31.公司專案部署都是手工部署,說一下Linux的常用命令? 10
32.==和equals的區別? 11
33.專案有沒有上線的?做了幾個專案? 11
34.專案登入功能實現過程?token怎麼生成的?登入是用的框架還是自己直接寫的? 11
35.登入驗證有幾步驗證?寫個指令碼一直請求怎麼處理的? 11
36.訂單模組怎麼實現的? 11
37.Tcp、http協議 11
38.mysql資料庫儲存結構?資料庫鎖? 12
39.實現執行緒的方式? 12
40.Nginx的作用? 12
40微服使用者資訊如何獲取? 12
41Sprongboot常用註解? 12
42手寫單例 13
43springmvc工作流程 13
44sleep和wait區別 14
45mysql圖形計劃 14
46sql優化 15
47spring注入方式 15
48redis優點 15
49spring事務管理有幾種 15
51.Spring單例執行緒是否安全 16
52. JDK、JRE、JVM是什麼 16
53.Hashmap執行原理 16
54. IO與NIO的區別 17
55. 如何實現多執行緒 17
3.使用ExecutorService、Callable、Future實現有返回結果的多執行緒 17
應用場景: 需要讓非同步執行的執行緒在執行完成後返回一個值給當前的執行緒,當前的執行緒需要依賴這個值做一些其他的業務操作,這個時候就需要實現有返回結果的多執行緒 17
56.如何防止死鎖 17
57. 訊息佇列 18
58. 記憶體溢位 20
59. ioc與aop 21
60. Redis持久化 22
61設計模式以及原理? 22
62、分散式? 22
63微服框架? 23
64、反射機制? 23
65、Mvc? 23
66、Jdk 1.8新出了什麼功能? 23
67、垃圾回收機制? 23
68、內連線和左外連線的區別? 23
69、Zookeeper原理、作用? 23
70、Dubbo特點和springcloud區別? 24
71.如何保證執行緒安全 24
72. 記憶體溢位的原因和解決方法 24
73. 單例模式的作用 25
74. 資料庫優化的方法 25
75. hashMap原理 26
76. finally final finaize的區別 26
77. 連線池的作用是什麼? 26
78. 什麼是 JAVA 事務? 26
79. 主鍵索引和普通索引的區別 26
80. springmvc工作流程 27
81.wait與sleep的區別 27
82.mysql執行計劃 27
83.sql優化 28
84.spring注入方式 29
85.redis優點 29
86.spring事務管理有幾種 30
87.spring單例執行緒是否安全 30
88.除了SSM還用過什麼框架 31
89.spring核心庫,功能 31
90.springIOC和AOP原理 31
91自己寫會怎麼寫IOC,AOP 32
92spring怎麼注入 32
93在二班的課程大於3個的學生 33
94在開發過程中遇到過對框架技術問題怎麼解決 33
95對未來3年規則 33
96對產品是否瞭解 33
97加班出差怎麼看 33
98有沒有需要問我們 33
99解碼格式 33
100介面 33
101. 資料型別不匹配 34
102. spring整個請求流程 34
103. servlet的生命週期 34
104. 別人呼叫介面時中文亂碼解決方式 35
105. web.xml的作用 35
106. double和float的區別 35
107. ArrayList使用時有什麼注意事項 35
108. ArrayList和LinkedList區別 35
109. 多型怎麼實現 36
110. 重寫注意點,怎麼看呼叫的是父類還是子類,許可權要求 36
111過載的返回值要求 36
112對redis的理解 36
113使用spring的好處 37
114資料庫呼叫 37
115mybatis中的#和
的
區
別
,
的區別,
的區別,的應用場景 38
116介面和抽象類的區別和各自的應用場景 38
117solr怎麼建立索引 38
1.常見的集合有哪些?都有什麼區別:
List集合:
ArrayList:陣列結構,執行緒不安全,執行查詢效率塊,增刪改慢
LinkList:連結串列結構,對元素執行增刪改效率高
Set集合:
HashSet:要保證元素唯一性,需要覆蓋掉Object中的equals和hashCode方法
(因為底層是通過這兩個方法來判斷兩個元素是否是同一個)
TreeSet:以二叉樹的結構對元素進行儲存,可以對元素進行排序
Map集合:元素是成對出現的,以健值對的方式體現,健保證唯一性
HashMap:執行緒不安全,允許存放null鍵null值
HashTable:執行緒安全,不允許存放null鍵null值
TreeMap:可以對鍵進行排序,
2.HashMap的底層原理:
是以陣列和連結串列的形式儲存元素
3.sleep和wait的區別
1.wait來自Object類,sleep來之Thread類
2.呼叫sleep方法,執行緒不會釋放物件鎖,而呼叫wait方法執行緒會釋放物件鎖
3.slee睡眠後不出讓系統資源,wait讓其他執行緒可以佔用cup
4.sleep需要一個指定睡眠時間,時間一到會自動喚醒,而wait需要配合notify方法或者notifyAll方法使用
4.run方法和start方法的區別:
run方法:當前普通方法的方式呼叫,程式還是順序執行,還是要等待run方法體執行完畢後才會繼續執行下面的程式碼
start方法:用來啟動執行緒,真正實現了多執行緒執行,無序等待run方法體執行完畢後才執行下面的程式碼
5.Threadlocad的作用:
提供執行緒內部的區域性變數,並且這些變數依靠執行緒獨立存在,可以在多個執行緒中互不干擾的進行儲存資料和修改資料,通過set,get和remove方法。每個執行緒都是獨立操作
原理:在不同的執行緒中訪問一個物件,獲取的值是不一樣的,因為內部會從各個執行緒取出一個陣列,
通多對應的下標,查詢對應的值
6.solr查詢出的資料放在哪: 本地 磁碟中
7.為什麼用solr和其他的區別在哪:https://blog.csdn.net/jokeylin/article/details/80562148
solr是一款高效能的搜尋引擎,同時對其進行的擴充套件,提供了比Lucene更為豐富的查 詢語言,實現了高配置,可擴充套件對查詢效能進行了優化,並且提供了一個完善的功能管理介面,是一款非常豐富的全文搜尋引擎。
8.支付寶的支付流程:
先是生成商戶系統一筆未支付的訂單,獲得商戶訂單ID(商戶系統生成)和訂單的一些其他資訊,然後再呼叫支付寶的SDK提供的數字簽名方法,將需要傳給支付寶的資訊進行加簽,然後把加簽後的字串返回給APP。APP拉起支付寶APP,再把這個加簽的字串傳給支付寶,完成支付。APP接收到同步通知後,還需要再次呼叫商戶後臺的介面(雖然同步通知也有付款情況,但需要以後臺通知為準),校驗訂單最終的付款情況。按照支付寶API上所說,當完成支付後,支付寶會做2個操作,一個是同步返回資訊給APP,一個是非同步通知商戶後臺返回支付狀態等資訊,並且最終的支付結果是以非同步通知為準。所以我們還需要考慮到一點,就是當使用者支付成功之後,商戶系統暫時沒有接收到支付寶的非同步通知時。我們需要拿著這個商戶訂單ID主動呼叫SDK支付寶的查詢介面,去獲取該訂單的支付情況,並最終返回給APP
當點選支付的時候將一筆未支付的訂單資訊(包含商家,商品以及使用者的資訊)給支付寶,當輸入支付密碼支付寶呼叫SDK加簽再給支付寶,當支付完成後,支付寶會做2個操作,一個是同步返回資訊給APP,一個是非同步通知商戶後臺返回支付狀態等資訊,並且最終的支付結果是以非同步通知為準。
9.資料庫有幾種索引:
主鍵索引:最常見的索引,確保資料記錄的唯一性,確定特定資料在資料庫的位置
唯一索引:避免同一個表中某資料列中的值重複
常規索引:快速定位特定資料
全文索引:快速定位特定資料
10redis五種資料型別和應用場景
①String(字串):
string 是 redis 最基本的型別,你可以理解成與 Memcached(分散式快取) 一模一樣的型別,一個 key 對應一個 value。
string 型別是二進位制安全的。意思是 redis 的 string 可以包含任何資料。比如jpg圖片或者序列化的物件。
string 型別是 Redis 最基本的資料型別,string 型別的值最大能儲存 512MB。
②Hash(雜湊表):
Redis hash 是一個鍵值(key=>value)對集合。
Redis hash 是一個 string 型別的 field 和 value 的對映表,hash 特別適合用於儲存物件。
③List(集合):
Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素到列表的頭部(左邊)或者尾部(右邊
④Set(集合):
Redis 的 Set 是 string 型別的無序集合。
集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)
⑤zset(sorted set:有序集合):
Redis zset 和 set 一樣也是string型別元素的集合,且不允許重複的成員。
不同的是每個元素都會關聯一個double型別的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。zset的成員是唯一的,但分數(score)卻可以重複
11執行緒池工作原理:
先啟動若干數量的執行緒,並讓這些執行緒都處於睡眠狀態,當客戶端有一個新請求時,就會喚醒執行緒池中的某一個睡眠執行緒,讓它來處理客戶端的這個請求,當處理完這個請求後,執行緒又處於睡眠狀態
12Gc(垃圾回收機制)的四種演算法
及時清除不再使用的物件,將記憶體清理出來,
①引用計數法:
②標記清除法:
為每個物件儲存一個標記位,記錄物件的狀態(活著或者死亡),死亡則進行清除
③標記壓縮法:
是標記清楚法的改進版,該演算法不會對死亡的物件直接清理,而是將所有存活的對 象整理一下,放到另一個空間,然後把剩下的物件全部清除
優點: 該演算法不會產生大量的碎片空間
缺點: 如果存活物件過多,整理階段將會執行過多的複製操作,導致演算法效率
④複製演算法:
將記憶體評分分成兩部分,然後每次只使用其中一部分,當這部分記憶體滿的時候,將 記憶體中存活的物件複製到另一個記憶體中,然後將之前的記憶體清空,只使用這部分內 存,迴圈下去。
13.Spring ioc和aop 原理
ioc(控制反轉):是工廠模式
其包含兩個內容,一是控制,二是反轉,在程式中,被呼叫類的選擇控制權從呼叫 它的類中移除,轉交給第三方裁決。第三方指的就是spring的容器,IOC另解,依 賴注入,呼叫類對被呼叫類的依賴關係由第三方注入,以移除呼叫類對被呼叫類的 使用。
aop(面向切面程式設計):是代理模式
是目前軟體開發中的一個熱點,也是spring框架中的重要內容,利用AOP可以對 業務邏輯的各個本分進行隔離,從而使得業務邏輯的各個部分減低耦合度,提供程 序的可重用性,提高了開發效率
14設計模式;
工廠模式:spring的IOC容器就是一個大的Bean實列的工廠,複製Bean的週期管理
單列模式:和spring的IOC 是一起的,既然IOC是一個大工程,那麼Bean物件為了 減少記憶體開銷就需要提供單列特徵。
代理模式:為其他物件提供一種代理訪問的機制
觀察者模式:當物件發生變化時,則會通知他的依賴物件,屬於行為型模式
15.Redis持久化:
ROB:在指定的時間間隔能對你的資料進行快照儲存
AOF:記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料
用一句話可以將持久化概括為:將資料(如記憶體中的物件)儲存到可永久儲存的儲存設 備中。持久化的主要應用是將記憶體中的物件儲存在資料庫中,或者儲存在磁碟檔案 中、 XML 資料檔案中等等
為什麼要做持久化:因為redis的資料是快取在記憶體中的,當你重啟或者關閉系統後, 快取在記憶體中的資料就會消失殆盡,再也找不回來,所以,為了能讓資料長期儲存, 就一號將Redis快取在記憶體中的資料做持久化成操作。
怎麼實現持久化:
1、RDB持久化方式能夠在指定的時間間隔能對你的資料進行快照儲存。
2、AOF持久化方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料,AOF命令以redis協議追加儲存每次寫的操作到檔案末尾.Redis還能對AOF檔案進行後臺重寫,使得AOF檔案的體積不至於過大。
3、如果你只希望你的資料在伺服器執行的時候存在,你也可以不使用任何持久化方式。
4、你也可以同時開啟兩種持久化方式, 在這種情況下, 當redis重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整。
。
16.悲觀鎖和樂觀鎖
悲觀鎖:總是假設最壞的情況發生,因此每次在取資料的時候就會加鎖,操作完成後才 釋放鎖。Java中典型的悲觀鎖就是
樂觀鎖:假設大資料情況下不會發生資料衝突,因此在取資料的時候不加鎖,只有在更 新的時候判斷該資料在此期間釋放被修改過
17.springmvc的工作原理:
1.使用者傳送請求給點的控制器DispatcherServlet
2.DispatcherServlet接收到使用者請求後,通過HandlerMapping處理器對映器尋找合理的 處理器進行處理
3.處理器對映器找到具體的處理器後,生成處理器物件以及處理器攔截器,並返回給前 端控制器
4.前端控制器呼叫處理器介面卡,將請求交給處理器處理
5.處理器介面卡呼叫具體的處理器對請求進行處理
6.處理器處理完成後放回ModelAndView
7.處理器介面卡將放回的ModelAndView返回給前端控制器
8.前端控制器將ModelAndView交給檢視解析器進行解析
9.檢視解析器解析之後返回具體的View
10.前端控制器根據具體的View進行渲染
11.前端控制器響應使用者請求
18.索引過多會引發什麼:
增加儲存開銷,對於插入,刪除,更新操作也會增加處理上的開銷,過多的複合索引, 在有單欄位索引情況下,一般都是沒有價值的,還有降低效能,特表是對頻繁更新的 表來說,負面影響更大
19.手寫冒泡:
public static void main(Sring[] args){
//使用氣泡排序實現升序降序
ing[] array={5,25,42,9,36,50,28};
for(int i=0;i<array.length-1;i++){
for(int j=0;j<array.length-1;j++){
if(array[j] > array[j+1]){
int temp;
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp
}
}
System.out.println(“排序後”)
for(int i=o;i<array.length;i++){
System.out.print (array[i]
}
}
}
20.在開發中於遇到的困難,怎麼解決的,有什麼收穫
力求自己解決,可以百度或者進入CSDN之類的學習平臺。實在不行找身邊的同事
與身邊的同事相處好更有利於以後的開發
21.談談集合?
集合多個個體擁有同種特性聚集在一起,Java集合是java提供的一個工具包,全部繼承自java.util.*。
主要包括兩大介面Collection介面和Map介面以及相關的工具類
(Iterator迭代器介面、Enumeration列舉類、Arrays和Colletions)
22.Hashmap的底層原理?
HashMap底層是通過陣列加連結串列的結構來實現的HashMap 的例項有兩個引數影響其效能
:“初始容量” 和 “載入因子”HashMap 根據鍵的 hashCode 值儲存資料,大多數情況
下可以直接定位到它的值,因而具有很快的訪問速度,但遍歷順序卻是不確定的。
HashMap 最多隻允許一條記錄的鍵為 null ,允許多條記錄的值為 null 。
HashMap 非執行緒安全,即任一時刻可以有多個執行緒同時寫 HashMap,可能會
導致資料的不一致。如果需要滿足執行緒安全,可以用 Collections的
synchronizedMap 方法使 HashMap 具有執行緒安全的能力,或者使用ConcurrentHashMap。
在JDK1.8之前,它的底層結構是陣列+連結串列,而在JDK1.8之後,為了查詢效率的優化
(主要是當雜湊碰撞較多的時候),它的底層結構變成了陣列+連結串列+紅黑樹
23.有對hashmap初始容量進行修改過嗎?修改原理初始容量?
當我們設定了初始化容量,HashMap就會按照我們設定的容量進行設定嗎?
答案是不一定。當你設定的初始化容量是2的n次方時,就會按照你設定的容量設定
;當你設定的初始化容量不是2的n次方時,就會按照大於你設定的那個值但是最接近
你設定的那個值的2的n次方進行設定其中size是HashMap中新增鍵值對的數量,
而threshold是容量載入因子(capacity * load factor)得出的值,
也是就當我們的容量是16,載入因子是0.75時,當鍵值對的數量大於160.75=12時
,HashMap會進行擴容操作
24.多執行緒中使用的集合有哪些是執行緒安全的?
ConcurrentHashMap是Java5中新增加的一個執行緒安全的Map集合
ConcurrentSkipListSet是執行緒安全的有序的集合,適用於高併發的場景
LinkedBlockingQueue是一個執行緒安全的阻塞佇列,它實現了BlockingQueue介面
,BlockingQueue介面繼承自java.util.Queue介面,並在這個介面的基礎上增加了
take和put方法,這兩個方法正是佇列操作的阻塞版本。
CopyOnWriteArrayList是ArrayList 的一個執行緒安全的變體,
其中所有可變操作(add、set等等)都是通過對底層陣列進行一次新的複製來實現的
Vector和HashTable實現了執行緒安全的陣列和雜湊表;在java1.2版本中他們就已經不再使用了
,取而代之是ArrayList和HashMap這些集合類不是執行緒安全但是他們可以通過集合庫中提供的
同步包裝器使其變成執行緒安全的;
25.專案中有涉及多執行緒嗎?採用什麼方法建立執行緒?(建立執行緒的集中方式)
繼承therad,實現runnable
26.資料庫用的什麼連線的?
navicat
27.在哪種場景下使用的多執行緒?(回答訂單)用在訂單的使用者量很大為什麼使用建立執行緒沒有使用建立執行緒池?
場景一:一個業務邏輯有很多次的迴圈,每次迴圈之間沒有影響,比如驗證1萬條url路徑是否存在,正常情況要迴圈1萬次,逐個去驗證每一條URL,這樣效率會很低,假設驗證一條需要1分鐘,總共就需要1萬分鍾,有點恐怖。這時可以用多執行緒,將1萬條URL分成50等份,開50個執行緒,沒個執行緒只需驗證200條,這樣所有的執行緒執行完是遠小於1萬分鐘的。
場景二:需要知道一個任務的執行進度,比如我們常看到的進度條,實現方式可以是在任務中加入一個整型屬性變數(這樣不同方法可以共享),任務執行一定程度就給變數值加1,另外開一個執行緒按時間間隔不斷去訪問這個變數,並反饋給使用者。
我知道執行緒池是一件好事,因為它可以重用執行緒,從而節省建立新執行緒的成本
如果在其上執行的任務通過阻塞佇列交換資訊,則有限大小的執行緒池是危險的,
這可能導致執行緒飢餓
28.執行緒的生命週期?
New(初始化狀態)
Runnable(可執行/執行狀態)
Blocked(阻塞狀態)
Waiting(無時間限制的等待狀態)
Timed_Waiting(有時間限制的等待狀態)
Terminated(終止狀態)
1.New(初始化狀態):指的是在高階語言,比如Java。在Java層面的執行緒被建立了,而在作業系統中的
執行緒其實是還沒被建立的,所以這個時候是不可能分配CPU執行這個執行緒的!所以這個狀態是高階語言獨
有的,作業系統的執行緒沒這個狀態。我們New了一個執行緒,那時候它就是這個狀態。
2.Runnable(可執行/執行狀態):這個狀態下是可以分配CPU執行的,在New狀態時候我們呼叫start()方法後執行緒就處於這個狀態。
3.Blocked(阻塞狀態):這個狀態下是不能分配CPU執行的,只有一種情況會導致執行緒阻塞,就是synchronized
!我們知道被synchronized修飾的方法或者程式碼塊同一時刻只能有一個執行緒執行,而其他競爭鎖的執行緒就從
Runnable到了Blocked狀態!當某個執行緒競爭到鎖了它就變成了Runnable狀態。注意併發包中的Lock,是
會讓執行緒屬於等待狀態而不是阻塞,只有synchronized是阻塞。(感覺是歷史遺留問題,沒必要多一個阻塞狀態和等待沒差啊)。
4.Waiting(無時間限制的等待狀態):這個狀態下也是不能分配CPU執行的。有三種情況會使得Runnable狀態到waiting狀態
呼叫無參的Object.wait()方法。等到notifyAll()或者notify()喚醒就會回到Runnable狀態。
呼叫無參的Thread.join()方法。也就是比如你在主執行緒裡面建立了一個執行緒A,呼叫A.join(),那麼你的主執行緒是得等A執行完了才會繼續執行,這是你的主執行緒就是等待狀態。
呼叫LockSupport.park()方法。LockSupport是Java6引入的一個工具類Java併發包中的鎖都是基於它實現的,再呼叫LocakSupport.unpark(Thread thread),就會回到Runnable狀態。
5.Timed_Waiting(有時間限制的等待狀態):其實這個狀態和Waiting就是有沒有超時時間的差別,這個狀態下也是不能分配CPU執行的。有五種情況會使得Runnable狀態到waiting狀態
Object.wait(long timeout)。
Thread.join(long millis)。
Thread.sleep(long millis)。注意 Thread.sleep(long millis, int nanos) 內部呼叫的其實也是Thread.sleep(long millis)。
LockSupport.parkNanos(Object blocked,long deadline)。
LockSupport.parkUntil(long deadline)。
6.Terminated(終止狀態):在我們的執行緒正常run結束之後或者run一半異常了就是終止狀態!
注意有個方法Thread.stop()是讓執行緒終止的,但是這個方法已經被廢棄了,不推薦使用,因為比如你這個執行緒得到了鎖,你stop了之後這個鎖也隨著沒了,其它執行緒就都拿不到這個鎖了!這不玩完了麼!所以推薦使用interrupt()方法。
interrupt()會使得執行緒Waiting和Timed_Waiting狀態的執行緒丟擲 interruptedException異常,使得Runnabled狀態的執行緒如果是在I/O操作會丟擲其它異常。
如果Runnabled狀態的執行緒沒有阻塞在I/O狀態的話,那隻能主動檢測自己是不是被中斷了,使用isInterrupted()。
29.說下Ioc Aop 和專案中用到的地方?
ioc,控制反轉,這個指的就是我們獲取物件的方式進行反轉了,改變了。在使用spring之前是需要手
動new出來的,是我們主動獲取的。使用spring之後,是將這個獲取的過程交給spring來管理,我們只需
要告訴spring你需要什麼就行了,它就會把東西給你。比如:在沒有電商的時候,我們去上街買東西,需
要考慮到這東西有沒有,價錢多少,怎麼搬回來,去有多遠……等等無數個和主要的業務邏輯(買東西)無
關的問題。這樣就會擾亂主業務邏輯。當我們有了電商平臺後,買東西時只需要兩步。註冊賬號(裝載bean)
,告訴電商你要的東西名字(通過名字獲取Bean),然後就可以在門口收到東西了。這就是ioc。
aop,面向切面。在談這個之前需要了解幾個詞:切面,切入點,織入,目標物件,通知。
我先解釋下名字的意思,再講故事。
切面:就是你要準備增強的那些方法。
切入點:就是具體織入的方法,定義了地點
織入:動詞,就是將切面織入的過層
目標物件:被增強的類
通知:就是什麼時候增強,定義了時間
好了,瞭解清楚上面的幾個詞的意思後,再聽故事就容易多了。
aop的功能就是用來增強,在執行主業務的通知也順帶執行其他業務。如:老李上街辦點事兒,走啊走,走到了老王家門前(切入點),老王看見老李問:去哪啊!
老李:上街辦點事兒(目標類)
老王:那幫我順便把這封信投到郵筒裡吧。(切面),等到10點的時候郵局開門了去櫃檯投。(通知)
老李:好嘞。然後老李接過信。(織入)
老李繼續走啊走,繼續上街辦事(增強後的目標類)。辦完事後老李回家了。
以上就是aop。aop一般用來處理許可權控制,日誌記錄,載入事務等非主要業務邏輯的事情。底層是採用cglib和jdk的動態代理實現的。
31.公司專案部署都是手工部署,說一下Linux的常用命令?
shutdown -h now 關閉系統,cd 進入個人的主目錄,ls檢視當前目錄下檔案,命令有很多,使用時可以檢視文件。
32.==和equals的區別?
==是指對記憶體地址進行比較 , equals()是對字串的內容進行比較
33.專案有沒有上線的?做了幾個專案?
上線了/沒上線,做過兩個專案/三個專案,按自己情況說。
34.專案登入功能實現過程?token怎麼生成的?登入是用的框架還是自己直接寫的?
獲取前端登入的資料(驗證碼,使用者名稱,密碼等),先驗證驗證碼是否正確,再驗證使用者名稱和密碼(加不加密隨意)是否正確,正確與否都要做出提示,然後再設定一個Cookie機制用來儲存使用者登入的資訊,如果勾選了儲存密碼,就可以對Cookie設定有效期之類的。也可以生成token。 token(分為三部分,header密文,payload密文,簽名),將荷載payload,以及Header資訊進行Base64加密,形成密文payload密文,header密文,將形成的密文用句號連結起來,用服務端祕鑰進行HS256加密,生成簽名,將前面的兩個密文後面用句號連結簽名形成最終的token返回給服務端。 登入用了框架/自己寫(視自己的情況說)。
35.登入驗證有幾步驗證?寫個指令碼一直請求怎麼處理的?
同上步驟 Ajax請求外面套一層迴圈或者遞迴函式
36.訂單模組怎麼實現的?
首先訂單模組有訂單的增刪改查等功能,使用者選好商品後提交,生成訂單詳情,然後使用者可以對這個訂單進行一些操作比如支付、取消等。在生成訂單時可能會有併發的情況,這裡我使用了訊息佇列解決併發問題。
37.Tcp、http協議
HTTP協議即超文字傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用, HTTP連線最顯著的特點是客戶端傳送的每次請求都需要伺服器回送響應,過程稱為“一次連線” 。。。 TCP/IP是一個協議簇,是由許多協議組成的,TCP/IP按照層次從上至下分為四層,建立起一個TCP連線需要經過“三次握手”
38.mysql資料庫儲存結構?資料庫鎖?
儲存結構是儲存在連續的記憶體中,所以採用的是B-樹索引 。資料庫儲存引擎有Inoodb,MyISAM,Memory,mysql預設採用的是inoodb。 資料庫鎖:表級鎖(表共享讀鎖和表獨佔寫鎖),行級鎖(共享鎖,排他鎖,意向共享鎖和意向排他鎖,間隙鎖),頁級鎖
39.實現執行緒的方式?
實現Runnable介面,以及繼承Thread類
40.Nginx的作用?
一、靜態http伺服器,Nginx是一個HTTP伺服器,可以將伺服器上的靜態檔案(如HTML、圖片)通過HTTP協議展現給客戶端。二、反向代理伺服器,客戶端本來可以直接通過HTTP協議訪問某網站應用伺服器,網站管理員可以在中間加上一個Nginx,客戶端請求Nginx,Nginx請求應用伺服器,然後將結果返回給客戶端。三、負載均衡,Nginx可以通過反向代理來實現負載均衡。四、虛擬主機,有的網站,由於訪問量太小,需要節省成本,將多個網站部署在同一臺伺服器上。
40微服使用者資訊如何獲取?
用dubbox搭建的微服各模組註冊資訊從zookeeper註冊中心獲取,用springcloud搭建的微服各模組註冊資訊從eureka註冊中心獲取。
41Sprongboot常用註解?
@Service: 註解在類上,表示這是一個業務層bean
@Controller:註解在類上,表示這是一個控制層bean
@Repository: 註解在類上,表示這是一個資料訪問層bean
@Component: 註解在類上,表示通用bean ,value不寫預設就是類名首字母小寫
@Autowired:按型別注入
@Resource: 按名稱裝配
@Configuration:註解在類上,表示這是一個IOC容器,
@Bean: 註解在方法上,宣告當前方法返回一個Bean
@Scope:註解在類上,描述spring容器如何建立Bean例項。
@Value:註解在變數上,從配置檔案中讀取。
@ConfigurationProperties: 賦值,將註解轉換成物件。
@EnableAutoConfiguration啟用 Spring 應用程式上下文的自動配置,試圖猜測和配置您可能需要的bean。
@SpringBootApplication=@ComponentScan+@Configuration+@EnableAutoConfiguration:約定優於配置
@ComponentScan:註解在類上,掃描標註了@Controller等註解的類,註冊為bean 。
@RestController @RestController 是一個結合了 @ResponseBody 和 @Controller 的註解
@Responsebody:表示該方法的返回的結果直接寫入 HTTP 響應正文(ResponseBody)中,一般在非同步獲取資料時使用,通常是在使用 @RequestMapping後,返回值通常解析為跳轉路徑,加上@Responsebody 後返回結果不會被解析為跳轉路徑,而是直接寫入HTTP 響應正文中。
@PathVariable、@RequestParam:兩者的作用都是將request裡的引數的值繫結到contorl裡的方法引數裡的,區別在於,URL寫法不同。
@EnablCaching:pring framework中的註解驅動的快取管理功能。
@suppresswarnings: 抑制警告
@Modifying :增,改,刪加註解
42手寫單例
public class Singleton {
private static Singleton = new Singleton();
private Singleton() {}
public static getSignleton(){
return singleton;
}
}
43springmvc工作流程
1、使用者向服務端傳送一次請求,這個請求會先到前端控制器DispatcherServlet(也叫中央控制器)。
2、DispatcherServlet接收到請求後會呼叫HandlerMapping處理器對映器。由此得知,該請求該由哪個Controller來處理(並未呼叫Controller,只是得知)
3、DispatcherServlet呼叫HandlerAdapter處理器介面卡,告訴處理器介面卡應該要去執行哪個Controller
4、HandlerAdapter處理器介面卡去執行Controller並得到ModelAndView(資料和檢視),並層層返回給DispatcherServlet
5、DispatcherServlet將ModelAndView交給ViewReslover檢視解析器解析,然後返回真正的檢視。
6、DispatcherServlet將模型資料填充到檢視中
7、DispatcherServlet將結果響應給使用者
44sleep和wait區別
原理不同
sleep是Thread類的靜態方法,是執行緒用來控制自身流程的,它會使此執行緒暫停執行指定的時間,而把執行機會讓給其他的執行緒,等到計時時間到,此執行緒會自動甦醒.
wait是Object類的方法,用於執行緒間的通訊,這個方法會使當前擁有該物件鎖的程式等待,直到其他執行緒呼叫notify方法才醒來,也可以指定時間自己醒來.
對鎖的處理機制不同
由於sleep方法的主要作用是讓執行緒休眠指定一段時間,在時間到時自動恢復,不涉及執行緒間的通訊,因此,呼叫sleep方法並不會釋放掉鎖.
但是呼叫wait方法的時候,執行緒會釋放掉它所佔用的鎖,從而使執行緒所在物件中的其他synchronized資料可以被其他執行緒使用.
使用的區域不同
由於wait方法的特殊含義,所以它必須放在同步控制方法或者同步語句塊中使用,而sleep方法則可以放在任何地方使用.
異常的捕獲
sleep方法必須捕獲異常,而wait,notify以及notifyall不需要捕獲異常,在sleep的過程中,有可能別其他物件呼叫其interrupt(),產生InterruptedException異常.
sleep不會釋放鎖標誌,容易導致死鎖的發生,所以一般情況下,不推薦使用sleep方法,而是使用wait方法.
45mysql圖形計劃
執行計劃,簡單的來說,是SQL在資料庫中執行時的表現情況,通常用於SQL效能分析,優化等場景。在MySQL中使用 explain 關鍵字來檢視。explain sql語句
table:顯示這一行的資料是關於哪張表的
type:顯示連線使用了何種型別。
possible_keys:顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。
key:實際使用的索引。
key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows:MYSQL認為必須檢查的用來返回請求資料的行數
Extra:關於MYSQL如何解析查詢的額外資訊。
46sql優化
1、在表中建立索引,優先考慮where、group by使用到的欄位。
2、儘量避免使用select *,返回無用的欄位會降低查詢效率。
3、儘量避免使用in 和not in,會導致資料庫引擎放棄索引進行全表掃描。
4、儘量避免使用or,會導致資料庫引擎放棄索引進行全表掃描。
5、儘量避免在欄位開頭模糊查詢,會導致資料庫引擎放棄索引進行全表掃描。
6、儘量避免進行null值的判斷,會導致資料庫引擎放棄索引進行全表掃描。
7、儘量避免在where條件中等號的左側進行表示式、函式操作,會導致資料庫引擎放棄索引進行全表掃描。
8、當資料量大時,避免使用where 1=1的條件。通常為了方便拼裝查詢條件,我們會預設使用該條件,資料庫引擎會放棄索引進行全表掃描。
47spring注入方式
一、構造器注入
構造器注入依賴於構造方法的實現,構造方法可以是有引數的,也可以是無引數的 。
二、setter注入
setter注入利用JAVA Bean規範所定 首先將構造方法設定為無參的構造方法,然後利用setter注入為其設定新的值,這是通過java的反射技術得以實現的
三、介面注入
有時候資源並非來自於自身的系統,而是來自於外界,比如說資料庫連線資源完全可以在Tomcat下配置,然後通過JNDI的方式去獲取它,這樣的資料庫連線資源就屬於開發工程外的資源。
48redis優點
效能極高: Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
豐富的資料型別: Redis支援二進位制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 資料型別操作。
原子性: Redis的所有操作都是原子性的,同時Redis還支援對幾個操作合併後的原子性執行。(事務)
豐富的特性:Redis還支援 publish/subscribe, 通知, key 過期等等特性。
49spring事務管理有幾種
(1)程式設計式事務管理對基於 POJO 的應用來說是唯一選擇。我們需要在程式碼中呼叫beginTransaction()、commit()、rollback()等事務管理相關的方法,這就是程式設計式事務管理。
(2)基於 TransactionProxyFactoryBean的宣告式事務管理
(3)基於 @Transactional 的宣告式事務管理
(4)基於Aspectj AOP配置事務
51.Spring單例執行緒是否安全
spring框架裡的bean獲取例項的時候都是預設單例模式,所以在多執行緒開發裡就有可能會出現執行緒不安全的問題。
當多個使用者同時請求一個伺服器時,容器(tomcat)會給每一個請求分配一個執行緒,這時多個執行緒會併發執行該請求所對應的業務邏輯(controller裡的方法),此時就要注意啦,如果controller(是單例物件)裡有全域性變數並且又是可以修改的,那麼就需要考慮執行緒安全的問題。解決方案有很多,比如設定@scope(“prototype”)為多例模式,為每個執行緒建立一個controller,還可以使用ThreadLocal
52. JDK、JRE、JVM是什麼
JDK:Java開發工具包,是整個JAVA開發的核心,包括了JRE,JAVA基本類庫和一堆JAVA工具(比如說編譯器等等)
JRE:Java執行時環境,包含了JVM和JAVA執行時基本類庫
JVM:Java虛擬機器,它是Java實現跨平臺最核心的部分,所有的java檔案被編譯成.class檔案後,通過JVM進行識別執行
53.Hashmap執行原理
同上(2題)
54. IO與NIO的區別
IO是面向流的,NIO是面向緩衝區的:IO面向流意味著每次從流中讀一個或多個位元組,直至讀取所有位元組,它們沒有被快取在任何地方
IO是阻塞的,NIO是不阻塞的:如果在一次讀寫資料呼叫時資料還沒有準備好,或者目前不可寫,那麼讀寫操作就會被阻塞直到資料準備好或目標可寫為止。Java NIO則是非阻塞的,每一次資料讀寫呼叫都會立即返回,並將目前可讀(或可寫)的內容寫入緩衝區或者從緩衝區中輸出,即使當前沒有可用資料,呼叫仍然會立即返回並且不對緩衝區做任何操作。這就好像去超市買東西,如果超市中沒有需要的商品或者數量還不夠,那麼Java IO會一直等直到超市中需要的商品數量足夠了就將所有需要的商品帶回來,Java NIO則不同,不論超市中有多少需要的商品,它都會立即買下可以買到的所有需要的商品並返回,甚至是沒有需要的商品也會立即返回。
55. 如何實現多執行緒
1.繼承Thread類,重寫run()方法
2.實現Runnable介面並例項化一個執行緒
3.使用ExecutorService、Callable、Future實現有返回結果的多執行緒
應用場景: 需要讓非同步執行的執行緒在執行完成後返回一個值給當前的執行緒,當前的執行緒需要依賴這個值做一些其他的業務操作,這個時候就需要實現有返回結果的多執行緒
56.如何防止死鎖
1.設定加鎖順序
如果一個執行緒需要鎖,那麼就需要按照鎖的順序來獲得鎖
比如說,執行緒1佔據著鎖A,,執行緒2和執行緒3只有在獲取鎖A後才能獲取到鎖B(鎖A是鎖B的必要條件),所以執行緒2或3需要等待執行緒A釋放鎖之後才可以進行加鎖操作
缺點:按照順序加鎖是一個很有效的死鎖預防機制,但是按序加鎖也就意味著需要清楚所有可能用到的鎖以及鎖之間的先後順序
2.設定加鎖時長
若一個執行緒在給定的時間內沒有成功的獲取到所需要的鎖,則會進行回退並釋放其所佔用的的鎖,然後等待一段隨機的時間後在進行嘗試
缺點:有些執行緒可能需要花很長時間去執行任務而導致了鎖的超時,所以並不能確定一定發生了死鎖
3.設定死鎖檢測
當一個執行緒獲取鎖後,會對其進行記錄,記錄在資料結構中,如果有執行緒對某鎖進行請求,也會進行記錄。當一個執行緒請求鎖失敗後,這個執行緒會去遍歷鎖的關係圖,如果發現發生了死鎖,執行緒則會進行回退和等待,當然,也有可能發生回退後大量執行緒搶佔同一批鎖的情況,繼而又發生了死鎖,這裡可以對執行緒設定優先順序,讓部分執行緒先進行回退操作
57. 訊息佇列
1.為什麼要用訊息佇列?
解耦:A系統呼叫B系統、C系統,傳統的呼叫是直接呼叫,但是當B系統說我不需要你提供資料了,這時候A需要改程式碼,C系統說我不需要某個欄位了,這時候A也要改程式碼,如果又多了一個D系統,A又要寫程式碼。為了實現解耦,引入訊息佇列,A將產生的資料丟到訊息佇列中,哪個系統需要,哪個系統就去取;
非同步:A系統呼叫B系統,B系統由於某個需要呼叫第三方介面超時,導致A系統響應速度慢,而B系統的好壞又不會影響業務邏輯,所以可以改為A非同步呼叫B,A將訊息丟到訊息佇列中,B系統訂閱訊息,實現A的快速響應;
削峰:當大量流量請求到系統A時,由於資料庫的處理能力有限,造成資料庫連線異常。使用訊息佇列,大量請求先丟到訊息佇列中,系統A使用按批拉資料的方式,批量處理資料,生產中,高峰期短暫的訊息積壓是允許的。
2.使用訊息佇列有什麼缺點
系統複雜性增加:需要考慮訊息的處理,包括訊息冪等性(重複消費問題),訊息保序性(一個訂單多條訊息問題),以及訊息中介軟體本身的持久化和穩定性可靠性
系統的可用性降低:解耦後,多個系統通過訊息中介軟體互動,訊息中介軟體掛了整個系統就掛了
3.各種MQ的比較
ActiveMQ:
優點: 技術成熟,功能齊全,歷史悠久,有大量公司在使用
缺點: 偶爾會有較低概率丟失資料,而且社群已經不怎麼維護5.15.X版本
適用場景: 主要用於系統解耦和非同步處理,不適用與大資料量吞吐情況。網際網路公司很少適用
rabitMQ:
優點: 吞吐量高,功能齊全,管理介面易用,社群活躍,效能極好
缺點: 吞吐量只是萬級,erlang難以二次開發和掌控;叢集動態擴充套件非常麻煩
適用場景: 吞吐量不高而要求低延遲,並且不會頻繁調整和擴充套件的場景。非常適合國內中小型網際網路公司適用,因為管理介面非常友好,可以在介面進行配置和優化/叢集監控
rocketMQ
優點: 支援百千級大規模topic。吞吐量高(十萬級,日處理上百億)。介面易用。,分散式易擴充套件,阿里支援。java開發易於掌控
缺點: 與阿里(社群)存在繫結。不相容JMS規範
適用場景: 高吞吐量
Kafka
優點: 超高吞吐量,超高可用性和可靠性,分散式易擴充套件
缺點: topic支援少,MQ功能簡單,訊息可能會重複消費影響資料精確度
適用場景: 超高吞吐量場景而資料精確度沒那麼高,天然適合大資料實時計算和日誌採集場景
58. 記憶體溢位
記憶體溢位的情形:
1.java堆記憶體溢位: 當出現java.lang.OutOfMemoryError:Java heap space異常時,就是堆記憶體溢位了
發生場景:1.設定的jvm記憶體太小,物件所需記憶體太大,建立物件時分配空間,就會丟擲這個異常。2.流量/資料峰值,應用程式自身的處理存在一定的限額,比如一定數量的使用者或一定數量的資料。而當使用者數量或資料量突然激增並超過預期的閾值時,那麼就會峰值停止前正常執行的操作將停止並觸發java . lang.OutOfMemoryError:Java堆空間錯誤
解決方法:首先,如果程式碼沒有什麼問題的情況下,可以適當調整-Xms和-Xmx兩個jvm引數,使用壓力測試來調整這兩個引數達到最優值。其次,儘量避免大的物件的申請,像檔案上傳,大批量從資料庫中獲取,這是需要避免的,儘量分塊或者分批處理,有助於系統的正常穩定的執行。最後,儘量提高一次請求的執行速度,垃圾回收越早越好,否則,大量的併發來了的時候,再來新的請求就無法分配記憶體了,就容易造成系統的雪崩
2. 垃圾回收超時記憶體溢位:
發生場景: 當應用程式耗盡所有可用記憶體時,GC開銷限制超過了錯誤,而GC多次未能清除它,這時便會引發java.lang.OutOfMemoryError。當JVM花費大量的時間執行GC,而收效甚微,而一旦整個GC的過程超過限制便會觸發錯誤(預設的jvm配置GC的時間超過98%,回收堆記憶體低於2%)
解決方法:減少物件生命週期,儘量能快速的進行垃圾回收
59. ioc與aop
同上(14題)
60. Redis持久化
同上(16題)
61設計模式以及原理?
1、工廠模式:建立型模式,它提供了一種建立物件的最佳方式。在工廠模式中,我們在建立物件時不會對客戶端暴露建立邏輯,並且是通過使用一個共同的介面來指向新建立的物件。應用例項: 1、您需要一輛汽車,可以直接從工廠裡面提貨,而不用去管這輛汽車是怎麼做出來的,以及這個汽車裡面的具體實現。使用場景: 1、日誌記錄器:記錄可能記錄到本地硬碟、系統事件、遠端伺服器等,使用者可以選擇記錄日誌到什麼地方。 2、資料庫訪問,當使用者不知道最後系統採用哪一類資料庫,以及資料庫可能有變化時。 3、設計一個連線伺服器的框架,需要三個協議,“POP3”、“IMAP”、“HTTP”,可以把這三個作為產品類,共同實現一個介面。
2、單例模式:建立型模式,這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。應用例項:一個班級只有一個班主任。使用場景:1、要求生產唯一序列號。2、WEB 中的計數器,不用每次重新整理都在資料庫里加一次,用單例先快取起來。3、建立的一個物件需要消耗的資源過多,比如 I/O 與資料庫的連線等
3、代理模式:結構型模式,在代理模式中,我們建立具有現有物件的物件,以便向外界提供功能介面。應用例項:Windows 裡面的快捷方式。使用場景:按職責來劃分,通常有以下使用場景: 1、遠端代理。 2、虛擬代理。 3、Copy-on-Write 代理。 4、保護(Protect or Access)代理。
4、MVC模式:Model-View-Controller(模型-檢視-控制器)模式,這種模式用於應用程式的分層開發,Model(模型) - 模型代表一個存取資料的物件或 JAVA POJO。它也可以帶有邏輯,在資料變化時更新控制器;View(檢視) - 檢視代表模型包含的資料的視覺化;Controller(控制器) - 控制器作用於模型和檢視上。它控制資料流向模型物件,並在資料變化時更新檢視。它使檢視與模型分離開。
62、分散式?
多臺伺服器合起來跑的才是一套完整程式碼,這就叫分散式;多臺伺服器跑的都是一套完整的程式碼,這就叫叢集
63微服框架?
微服務架構是一種架構模式或者說是一種架構風格,它將單一應用程式劃分一組小的服務,每個服務執行在其獨立的自己的程式中,服務之間按照一定的方式進行通訊。
64、反射機制?
動態獲取物件資訊和呼叫物件方法的功能稱之為反射機制。
65、Mvc?
MVC 是一種使用 MVC(Model View Controller 模型-檢視-控制器)設計建立 Web 應用程式的模式,是用一種業務邏輯、資料、介面顯示分離的方法組織程式碼,將業務邏輯聚集到一個部件裡面,在改進和個性化定製介面及使用者互動的同時,不需要重新編寫業務邏輯。
66、Jdk 1.8新出了什麼功能?
1、default關鍵字
2、Lambda 表示式
3、函式式介面
4、方法與建構函式引用
5、區域性變數限制
6、Date Api更新;
7、流
67、垃圾回收機制?
垃圾回收機制是由垃圾收集器Garbage Collection GC來實現的,GC是後臺的守護程式。它的特別之處是它是一個低優先順序程式,但是可以根據記憶體的使用情況動態的調整他的優先順序。因此,它是在記憶體中低到一定限度時才會自動執行,從而實現對記憶體的回收。
68、內連線和左外連線的區別?
內連線:顯示兩個表中有聯絡的所有資料;左連結:以左表為參照,顯示所有資料,右邊表資料資料少了補NULL值,資料多了不顯示。
69、Zookeeper原理、作用?
ZooKeeper是一個分散式的,開放原始碼的分散式應用程式協調服務。 功能:主要是用來解決分散式應用中經常遇到的一些資料管理問題,如:統一命名服務、狀態同步服務、叢集管理、分散式應用配置項的管理等。 原理:Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啟動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。
70、Dubbo特點和springcloud區別?
SpringCloud和Dubbo都是現在主流的微服務架構,
區別:1、Dubbo是阿里系的分散式服務框架;SpringCloud是Apache旗下的Spring體系下的微服務解決方案;
2、服務的呼叫方式:Dubbo使用的是RPC遠端呼叫,而SpringCloud使用的是 Rest API; 3、服務的註冊中心:Dubbo使用了第三方的ZooKeeper作為其底層的註冊中心,SpringCloud使用Eureka實現註冊中心
4、服務閘道器:Dubbo並沒有本身的實現,只能通過其他第三方技術的整合,而SpringCloud有Zuul路由閘道器,作為路由伺服器,進行消費者的請求分發;
5、SpringCloud還支援斷路器,與git完美整合分散式配置檔案支援版本控制,事務匯流排實現配置檔案的更新與服務自動裝配等等一系列的微服務架構要素
71.如何保證執行緒安全
1、使用執行緒安全的類;
2、使用synchronized同步程式碼塊,或者用Lock鎖;
3、多執行緒併發情況下,執行緒共享的變數改為方法區域性級變數;
-
記憶體溢位的原因和解決方法
原因:
1.記憶體中載入的資料量過於龐大,如一次從資料庫取出過多資料;
2.集合類中有對物件的引用,使用完後未清空,使得JVM不能回收;
3.程式碼中存在死迴圈或迴圈產生過多重複的物件實體;
4.使用的第三方軟體中的BUG;
5.啟動引數記憶體值設定的過小;
解決方法:
第一步,修改JVM啟動引數,直接增加記憶體。(-Xms,-Xmx引數一定不要忘記加。)
第二步,檢查錯誤日誌,檢視“OutOfMemory”錯誤前是否有其它異常或錯誤。
第三步,對程式碼進行走查和分析,找出可能發生記憶體溢位的位置。 -
單例模式的作用
1、控制資源的使用,通過執行緒同步來控制資源的併發訪問;
2、控制例項產生的數量,達到節約資源的目的。
3、作為通訊媒介使用,也就是資料共享,它可以在不建立直接關聯的條件下,讓多個不相關的兩個執行緒或者程式之間實現通訊。 -
資料庫優化的方法
1、選取最適用的欄位屬性
2、使用連線(JOIN)來代替子查詢(Sub-Queries)
3、使用聯合(UNION)來代替手動建立的臨時表
4、事務
5、鎖定表
6、使用外來鍵
7、使用索引
8、優化的查詢語句 -
hashMap原理
HashMap是一個雜湊桶(陣列和連結串列),它儲存的內容是鍵值對(key-value)對映HashMap採用了陣列和連結串列的資料結構,能在查詢和修改方便繼承了陣列的線性查詢和連結串列的定址修改 -
finally final finaize的區別
final是修飾符,修飾類、方法和變數,意為不可修改的。當修飾類的時候不可以派生出新的子類,因此一個類的修飾符不可以既是final和abstract;修飾方法的時候該方法不可以被過載;修飾變數的時候需要給變數賦初值,在接下來只能對其讀取不可以重新賦值。
finally是在異常處理時提供finally塊來執行任何清除操作的,如果try語句中發生了catch塊中的異常,則跳轉到catch中進行異常處理,而finally中的內容則是無論異常是否發生都要執行的。如果finally中有return,則會先執行finally再執行return,如果此時try中也有return,則try中的return不會執行,但是,如果只有try中有return也是先執行finally中的語句再執行return;
finalize是方法名,在垃圾回收器將物件從記憶體中清理出去之前做的必要工作。是由垃圾回收器在確定這個物件沒有被引用的時候呼叫的,它是在Object中定義的,子類重寫finalize方法整理系統資源或其他清理工作finalize方法是在垃圾收集器刪除物件之前呼叫的。
-
連線池的作用是什麼?
連線池是將已經建立好的連線儲存在池中,當有請求來時,直接使用已經建立好的連線對資料庫進行訪問。這樣省略了建立連線和銷燬連線的過程。這樣效能上得到了提高。 -
什麼是 JAVA 事務?
事務是作為一個邏輯單元執行的一系列操作,一個邏輯工作單元必須有四個屬性,稱為 ACID(原子性、一致性、隔離性和永續性)屬性,只有這樣才能成為一個事務。 -
主鍵索引和普通索引的區別
普通索引是最基本的索引型別,沒有任何限制,值可以為空,僅加速查詢。普通索引是可以重複的,一個表中可以有多個普通索引。
主鍵索引是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值;索引列的所有值都只能出現一次,即必須唯一。簡單來說:主鍵索引是加速查詢 + 列值唯一(不可以有null)+ 表中只有一個。 -
springmvc工作流程
使用者傳送url請求 ,前端通過action 裡面的對映地址 實現跳轉到後端控制器Controller ,執行完成後返回modelandview 傳入檢視解析器中,返回view ,把view進行渲染,相應給使用者
81.wait與sleep的區別
1、wait()方法屬於Object類,sleep()屬於Thread類;
2、wait()方法釋放cpu給其他執行緒,自己讓出資源進入等待池等待;sleep佔用cpu,不讓出資源;
3、sleep()必須指定時間,wait()可以指定時間也可以不指定;sleep()時間到,執行緒處於臨時阻塞或執行狀態;
4、wait()方法會釋放持有的鎖,不然其他執行緒不能進入同步方法或同步塊,從而不能呼叫notify(),notifyAll()方法來喚醒執行緒,產生死鎖,所以釋放鎖,可以執行其他執行緒,也可以喚醒自己,只是設定停止自己的時間時不確定的;sleep方法不會釋放持有的鎖,設定sleep的時間是確定的會按時執行的;
5、wait()方法只能在同步方法或同步程式碼塊中呼叫,否則會報illegalMonitorStateException異常,如果沒有設定時間,使用notify()來喚醒;而sleep()能在任何地方呼叫;
82.mysql執行計劃
執行計劃,簡單的來說,是SQL在資料庫中執行時的表現情況,通常用於SQL效能分析,優化等場景。在MySQL中使用 explain 關鍵字來檢視。如下所示:
explain select*fromtablewheretable.id =1
執行上面的sql語句後你會看到,下面的表頭資訊:
table | type | possible_keys | key | key_len | ref | rows | Extra
解釋下表頭各列的意義。
Table:顯示這一行的資料是關於哪張表的
Type:這是重要的列,顯示連線使用了何種型別。從最好到最差的連線型別為const、eq_reg、ref、range、index和ALL
不同連線型別的解釋(按照效率高低的順序排序):
system:表只有一行:system表。這是const連線型別的特殊情況。
const :表中的一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或惟一索引)。因為只有一行,這個值實際就是常數,因為MYSQL先讀這個值然後把它當做常數來對待。
eq_ref:在連線中,MYSQL在查詢時,從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用。
ref:這個連線型別只有在查詢使用了不是惟一或主鍵的鍵或者是這些型別的部分(比如,利用最左邊字首)時發生。對於之前的表的每一個行聯合,全部記錄都將從表中讀出。這個型別嚴重依賴於根據索引匹配的記錄多少—越少越好。
range:這個連線型別使用索引返回一個範圍中的行,比如使用>或<查詢東西時發生的情況。
index:這個連線型別對前面的表中的每一個記錄聯合進行完全掃描(比ALL更好,因為索引一般小於表資料)。
ALL:這個連線型別對於前面的每一個記錄聯合進行完全掃描,這一般比較糟糕,應該儘量避免。
possible_keys:顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句
key:實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows:MYSQL認為必須檢查的用來返回請求資料的行數
Extra:關於MYSQL如何解析查詢的額外資訊。舉例返回值如:Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢
以下為extra列返回的一些值和其意義:
Distinct :一旦mysql找到了與行相聯合匹配的行,就不再搜尋了。
Notexists :mysql優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜尋了。
RangecheckedforeachRecord(index map:#) :沒有找到理想的索引,因此對從前面表中來的每一個行組合,mysql檢查使用哪個索引,並用它來從表中返回行。這是使用索引的最慢的連線之一。
Usingfilesort:看到這個的時候,查詢就需要優化了。mysql需要進行額外的步驟來發現如何對返回的行排序。它根據連線型別以及儲存排序鍵值和匹配條件的全部行的行指標來排序全部行。
Usingindex :列資料是從僅僅使用了索引中的資訊而沒有讀取實際的行動的表返回的,這發生在對錶的全部的請求列都是同一個索引的部分的時候。
Usingtemporary :看到這個的時候,查詢需要優化了。這裡,mysql需要建立一個臨時表來儲存結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上。
Whereused :使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給使用者。如果不想返回表中的全部行,並且連線型別ALL或index,這就會發生,或者是查詢有問題。
83.sql優化
1、注意萬用字元中Like的使用,以下寫法會造成全表的掃描
2、避免在where子句中對欄位進行函式操作
3、在子查詢當中,儘量用exists代替in
4、where子句中儘量不要使用is null 或 is not null對欄位進行判斷,儘量在資料庫欄位中不出現null,如果查詢的時候條件為 is null ,索引將不會被使用,造成查詢效率低,因此資料庫在設計的時候,儘可能將某個欄位可能為空的時候設定預設值,那麼查詢的時候可以根據預設值進行查詢,比如空欄位設定為0
5、避免在where子句使用or作為連結條件
6、避免在 where 子句中使用 != 或 <> 操作符。
7、少用in 或 not in,對於連續的數值範圍查詢儘量使用BETWEEN AND
84.spring注入方式
1.構造器注入
2.setter注入
3.介面注入
構造器注入和setter注入是依賴注入的兩種主要方式,介面注入是指從別的地方注入的方式。(通過在xml中描述,實現注入)
85.redis優點
Redis的特點:
• 記憶體資料庫,速度快,也支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。
• Redis不僅僅支援簡單的key-value型別的資料,同時還提供list,set,zset,hash等資料結構的儲存。
• Redis支援資料的備份,即master-slave模式的資料備份。
• 支援事務
Redis的優勢:
• 效能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
• 豐富的資料型別 – Redis支援二進位制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 資料型別操作。
• 原子 – Redis的所有操作都是原子性的,同時Redis還支援對幾個操作合併後的原子性執行。(事務)
• 豐富的特性 – Redis還支援 publish/subscribe, 通知, key 過期等等特性。
86.spring事務管理有幾種
spring支援程式設計式事務管理和宣告式事務管理兩種方式:
①程式設計式事務管理使用TransactionTemplate。
②宣告式事務管理建立在AOP之上的。其本質是通過AOP功能,對方法前後進行攔截,將事務處理的功能編織到攔截的方法中,也就是在目標方法開始之前加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。
宣告式事務最大的優點就是不需要在業務邏輯程式碼中摻雜事務管理的程式碼,只需在配置檔案中做相關的事務規則宣告或通過@Transactional註解的方式,便可以將事務規則應用到業務邏輯中。
宣告式事務管理要優於程式設計式事務管理,這正是spring倡導的非侵入式的開發方式,使業務程式碼不受汙染,只要加上註解就可以獲得完全的事務支援。唯一不足地方是,最細粒度只能作用到方法級別,無法做到像程式設計式事務那樣可以作用到程式碼塊級別。
87.spring單例執行緒是否安全
在Spring中單例bean是在beanfactory中用反射機制動態建立的,被快取到ioc容器中相對於new了一個物件。而這些建立的物件class,則是自己建立的。
所以是不是執行緒安全和Spring本身無關,和自己建立的類有關。
自己建立的是安全的那就是安全的,自己建立的不是安全的那就不是安全的。
88.除了SSM還用過什麼框架
十大常用框架:一、SpringMVC。二、Spring三、Mybatis。四、Dubbo。五、Maven。六、RabbitMQ。七、Log4j。八、Ehcache。九、Redis。十、Shiro。
什麼會說什麼,不會不要說
89.spring核心庫,功能
Spring三大核心功能
1、IOC(DI) IOC:Inversion of Control,DI:Dependency Injection
2、AOP:Aspect Oriented Programming
3、宣告式事務
90.springIOC和AOP原理
IoC(Inversion of Control)
(1). IoC(Inversion of Control)是指容器控制程式物件之間的關係,而不是傳統實現中,由程式程式碼直接操控。控制權由應用程式碼中轉到了外部容器,控制權的轉移是所謂反轉。 對於Spring而言,就是由Spring來控制物件的生命週期和物件之間的關係;IoC還有另外一個名字——“依賴注入(Dependency Injection)”。從名字上理解,所謂依賴注入,即元件之間的依賴關係由容器在執行期決定,即由容器動態地將某種依賴關係注入到元件之中。
(2). 在Spring的工作方式中,所有的類都會在spring容器中登記,告訴spring這是個什麼東西,你需要什麼東西,然後spring會在系統執行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的建立、銷燬都由 spring來控制,也就是說控制物件生存週期的不再是引用它的物件,而是spring。對於某個具體的物件而言,以前是它控制其他物件,現在是所有物件都被spring控制,所以這叫控制反轉。
(3). 在系統執行中,動態的向某個物件提供它所需要的其他物件。
(4). 依賴注入的思想是通過反射機制實現的,在例項化一個類時,它通過反射呼叫類中set方法將事先儲存在HashMap中的類屬性注入到類中。 總而言之,在傳統的物件建立方式中,通常由呼叫者來建立被呼叫者的例項,而在Spring中建立被呼叫者的工作由Spring來完成,然後注入呼叫者,即所謂的依賴注入or控制反轉。 注入方式有兩種:依賴注入和設定注入; IoC的優點:降低了元件之間的耦合,降低了業務物件之間替換的複雜性,使之能夠靈活的管理物件。
AOP(Aspect Oriented Programming)
(1). AOP面向方面程式設計基於IoC,是對OOP的有益補充;
(2). AOP利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了 多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的 邏輯或責任封裝起來,比如日誌記錄,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。
(3). AOP代表的是一個橫向的關 系,將“物件”比作一個空心的圓柱體,其中封裝的是物件的屬性和行為;則面向方面程式設計的方法,就是將這個圓柱體以切面形式剖開,選擇性的提供業務邏輯。而 剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡,但完成了效果。
(4). 實現AOP的技術,主要分為兩大類:一是採用動態代理技術,利用擷取訊息的方式,對該訊息進行裝飾,以取代原有物件行為的執行;二是採用靜態織入的方式,引入特定的語法建立“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的程式碼。
(5). Spring實現AOP:JDK動態代理和CGLIB代理 JDK動態代理:其代理物件必須是某個介面的實現,它是通過在執行期間建立一個介面的實現類來完成對目標物件的代理;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現原理類似於JDK動態代理,只是它在執行期間生成的代理物件是針對目標類擴充套件的子類。CGLIB是高效的程式碼生成包,底層是依靠ASM(開源的java位元組碼編輯類庫)操作位元組碼實現的,效能比JDK強;需要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ註解驅動的切面實際上底層也是通過動態代理實現的
91自己寫會怎麼寫IOC,AOP
IOC:準備配置檔案、由IOC容器進行解析後設資料、例項化IOC容器
AOP:一是採用動態代理技術,二是採用靜態織入的方式
92spring怎麼注入
常用的有構造方法注入、setter注入、基於註解的注入
93在二班的課程大於3個的學生
SELECT name from student WHERE class=2 GROUP BY name HAVING count(lesson)>3
94在開發過程中遇到過對框架技術問題怎麼解決
百度、論壇、翻牆谷歌
95對未來3年規則
未來三年主要以積累開發經驗為主,後期會考慮往管理或架構師方向發展;
96對產品是否瞭解
?????
97加班出差怎麼看
儘量優先滿足公司的需求
98有沒有需要問我們
從公司目前的專案,使用的技術方面切入
99解碼格式
GBK、UTF-8
100介面
是一個抽象型別,是抽象方法的集合,通常以interface來宣告。一個類通過整合介面的方式,從而來繼承介面的抽象方法。
-
資料型別不匹配
能強轉的強轉,不能強轉的改成匹配的, -
引用型別: 返回二進位制名稱。(java.lang.string,java.lang.Integer)
-
基本型別或void: 返回對應Java關鍵字相同的String。(int,void)
-
陣列型別:返回’[‘字元加元素型別名,多維陣列則多個’['字元;元素型別名對應如下;([B,[Ljava.lang.String)
Element Type Encoding
boolean Z
byte B
char C
class or interface Lclassname;
double D
float F
int I
long J
short S -
spring整個請求流程
-
servlet的生命週期
(1)init()方法:伺服器初始化servlet。
(2)service()方法:初始化完畢,servlet物件呼叫該方法響應客戶的請求。
(3)destroy()方法:呼叫該方法消滅servlet物件。
其中,init()方法只在servlet第一次被請求載入的時候被呼叫一次,當有客戶再請求servlet服務時,web伺服器將啟動一個新的執行緒,在該執行緒中,呼叫service方法響應客戶的請求。 -
別人呼叫介面時中文亂碼解決方式
瞭解雙方的字元編碼格式,然後字串打散,按照新的編碼格式重新組合
比如A的介面編碼格式是UTF-8,B應用的編碼格式是ISO-8859-1,B呼叫A的介面,先將字串按UTF-8格式打散,再按ISO-8859-1格式重新組合,這樣就b接收到的資料就不會亂碼了 -
web.xml的作用
web.xml檔案是用來初始化配置資訊, 一個web中可以沒有web.xml檔案,也就是說,web.xml檔案並不是web工程必須的。
web.xml常用的一些標籤元素及其功能:
1、 指定歡迎頁面
2、 命名與定製URL。
3、 定製初始化引數:可以定製servlet、JSP、Context的初始化引數,然後可以再servlet、JSP、Context中獲取這些引數值。
4、 指定錯誤處理頁面,可以通過“異常型別”或“錯誤碼”來指定錯誤處理頁面
5、 設定過濾器:比如設定一個編碼過濾器,過濾所有資源
6、 設定監聽器
7、 設定會話(Session)過期時間,其中時間以分鐘為單位 -
double和float的區別
這兩種都是浮點型別資料,double 和 float 的區別是double精度高,有效數字 16位,float精度7位。float資料佔用32bit,double資料佔用64bit,double消耗記憶體是float的兩倍,double的運算速度比float慢得多 -
ArrayList使用時有什麼注意事項
集合的元素的型別不能是基本資料型別,只能是引用資料型別。 -
ArrayList和LinkedList區別
ArrayList:
0.ArrayList預設的初始緩衝空間是10個
1.ArrayList的底層的資料結構採用的陣列結構。(結構)
2.儲存資料的順序和取出資料的順序是一致的。(讀寫性質)
3.ArrayList在處理讀取和新增資料的效率非常高。(強項)
4.ArrayList在執行插入和刪除的操作時效率比較低,因為底層實現採用的 (弱項)是陣列結構,所有每刪除個元素n 則n元素之後的元素的下標都會向前移動一次。
使用注意事項:
集合的元素的型別不能是基本資料型別,只能是引用資料型別。
LinkedList:
0.LinkedList預設的初始緩衝空間是0個
1.LinkedList的底層的資料結構採用的是連結串列結構。
2.LinkedList插入和刪除效率比較高,因為刪除元素值,只需要修改當前刪除元素的前一個指標指向當前刪除元素的下一個元素。
3.讀取的效率相對於ArrayList比較低。
- 多型怎麼實現
實現多型的步驟:子類繼承父類或實現某介面,父類引用指向子類物件。 - 重寫注意點,怎麼看呼叫的是父類還是子類,許可權要求
重寫是在子類中出現和父類同名的方法。
1.子類重寫父類方法的方法範圍必須大於等於父類型別,但是不能是private型別。
2.父類私有的方法是不能被子類重寫。
3.子類中的同名方法除了範圍修飾符不同,其他的都必須相同。
111過載的返回值要求 - 過載與返回值無關;2.只有返回值型別不同的方法,不構成過載
112對redis的理解
簡單來說 redis 就是一個資料庫,不過與傳統資料庫不同的是 redis 的資料是存在記憶體中的,所以存寫速度非常快,因此 redis 被廣泛應用於快取方向。另外,redis 也經常用來做分散式鎖。redis 提供了多種資料型別來支援不同的業務場景。除此之外,redis 支援事務 、持久化、LUA指令碼、LRU驅動事件、多種叢集方案。
優勢:
1.速度快:因為資料存在記憶體中,類似於HashMap,HashMap的優勢就是查詢和操作的時間複雜度都是O(1),每秒可以處理超過 10萬次讀寫操作,是已知效能最快的Key-Value DB。
2.支援豐富資料型別:支援string,list,set,sorted set,hash
3.單個value的最大限制是1GB,不像 memcached只能儲存1MB的資料
4.支援事務:操作不是原子性的,即使某些操作失敗,也不會影響別的操作的執行
5.豐富的特性:可用於快取,按key設定過期時間,過期後將會自動刪除
113使用spring的好處
-
輕量級框架
Spring是輕量級框架,基本的版本大約2M
-
控制反轉
Spring通過控制反轉實現鬆散耦合,物件們給它們的依賴,而不是建立或者查詢依賴的物件們 方便解耦,簡化開發
-
面相切面的程式設計 AOP
Spring支援面相切面的程式設計,並且把應用業務邏輯和系統分開
-
容器
Spring 包含並管理應用中物件的生命週期和配置
-
MVC框架
Spring的WEB框架是個精心設計的框架,是WEB框架的一個很好的替代品
-
事務管理
Spring 提供一個持續的事務管理介面,可以擴充套件到上至本地事務下至全域性事務(JTA)
-
異常處理
Spring 提供方便的API把具體技術的相關異常(比如由JDBC Hibernate or JDO 丟擲的) 轉化為一致的 unchecked異常
114資料庫呼叫
1.載入(註冊)資料庫
2.建立連結
3.執行SQL語句
4.處理結果集
5.關閉資料庫
115mybatis中的#和
的
區
別
,
的區別,
的區別,的應用場景
應用場景:
#{ } :#代表佔位符,用來傳遞引數;
:
{ } :
:用來拼接sql 語句的;
區別:
1、#是預編譯的方式,KaTeX parse error: Expected 'EOF', got '#' at position 10: 是直接拼接; 2、#̲不需要關注資料型別,mybat…不做資料型別轉換,需要自行判斷資料型別;
3、#可以防止sql注入;KaTeX parse error: Expected 'EOF', got '#' at position 44: …e 只有一個引數,預設情況下,#̲{ }中可以寫任意的名字;{ }中只能用value來接收。
116介面和抽象類的區別和各自的應用場景
相同點:1.都不能被例項化2.都可以定義抽象方法
不同點:1.抽象類是一種類只能單繼承 介面可以多實現抽象;2.介面只能有抽象方法,抽象類可以有非抽象方法;
3.抽象類中可以有普通變數 介面中的變數都是由final修飾的
4.抽象類可以有構造器和主方法(抽象類中的構造器主要是在子類的構造方法中呼叫 負責初始化抽象類中的引數) 介面中不可以有構造器和主方法
5.抽象類中的方法普通可以由public private protected 和預設修飾 抽象方法可以由 public protected(或者不加修飾符)修飾 抽象方法必須由abstract修飾 介面方法預設由public修飾 介面中的抽象方法只能由public修飾 default在介面中只能修飾帶有方法體的方法
使用場景:
當需要一些預設的方法實現時需要使用抽象類
當需要多繼承時使用介面
當需要不斷增加基礎功能的時候使用抽象類 當使用介面時 增加功能就需要修改每個實現了該介面的實現類
117solr怎麼建立索引
1.啟動資料資料庫
2.在solr中配置資料來源
3.啟動tomcat,建立索引
4.登入solr控制檯檢測索引
-
基礎
-
面對物件的三大特性,五大原則
三大基本特性:封裝,繼承,多型
封裝,就是把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏。一個類就是一個封裝了資料以及操作這些資料的程式碼的邏輯實體。在一個物件內部,某些程式碼或某些資料可以是私有的,不能被外界訪問。通過這種方式,物件對內部資料提供了不同級別的保護,以防止程式中無關的部分意外的改變或錯誤的使用了物件的私有部分。
繼承,指可以讓某個型別的物件獲得另一個型別的物件的屬性的方法。它支援按級分類的概念。繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下對這些功能進行擴充套件。 通過繼承建立的新類稱為“子類”或“派生類”,被繼承的類稱為“基類”、“父類”或“超類”。繼承的過程,就是從一般到特殊的過程。要實現繼承,可以通過 “繼承”(Inheritance)和“組合”(Composition)來實現。繼承概念的實現方式有二類:實現繼承與介面繼承。實現繼承是指直接使用 基類的屬性和方法而無需額外編碼的能力;介面繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力。
多型,是指一個類例項的相同方法在不同情形有不同表現形式。多型機制使具有不同內部結構的物件可以共享相同的外部介面。這意味著,雖然針對不同物件的具體操作不同,但通過一個公共的類,它們(那些操作)可以通過相同的方式予以呼叫。
五大基本原則:SPR, OCP, LSP, DIP, ISP
單一職責原則SRP(dSingle Responsibility Principle)
開放封閉原則OCP(Open-Close Principle)
裡式替換原則LSP(the Liskov Substitution Principle LSP)
依賴倒置原則DIP(the Dependency Inversion Principle DIP)
介面分離原則ISP(the Interface Segregation Principle ISP) -
建立類的方法:
1.用new語句建立物件,這是最常用的建立物件的方式。
2.運用反射手段,呼叫Java.lang.Class或者java.lang.reflect.Constructor類的newInstance()例項方法。
3.呼叫物件的clone()方法。
4.運用反序列化手段,呼叫java.io.ObjectInputStream物件的readObject()方法. -
==與equals的區別
==是指對記憶體地址進行比較 , equals()是對字串的內容進行比較 -
&與&&的區別
&和&&都是雙邊為對才對,但是&&單邊錯誤,另一邊就不判斷了直接錯誤。 -
設計模式
工廠模式:spring的IOC容器就是一個大的Bean實列的工廠,複製Bean的週期管理
單列模式:和spring的IOC 是一起的,既然IOC是一個大工程,那麼Bean物件為了減少記憶體開銷就需要提供單列特徵。
代理模式:為其他物件提供一種代理訪問的機制
觀察者模式:當物件發生變化時,則會通知他的依賴物件,屬於行為型模式
MVC模式:Model-View-Controller(模型-檢視-控制器)模式,這種模式用於應用程式的分層開發,Model(模型) - 模型代表一個存取資料的物件或 JAVA POJO。 -
排序方法
氣泡排序、快速排序、插入排序、選擇排序 -
JDK、JRE、JVM是什麼
JDK:Java開發工具包,是整個JAVA開發的核心,包括了JRE,JAVA基本類庫和一堆JAVA工具(比如說編譯器等等)
JRE:Java執行時環境,包含了JVM和JAVA執行時基本類庫
JVM:Java虛擬機器,它是Java實現跨平臺最核心的部分,所有的java檔案被編譯成.class檔案後,通過JVM進行識別執行
8.HTTP和TCP
TCP/IP協議是傳輸層協議,主要解決資料如何在網路中傳輸,而HTTP是應用層協議,主要解決如何包裝資料。
HTTP:超文字傳輸協議,是應用層的協議,以TCP為基礎
TCP:傳輸控制協議,是傳輸層的協議,以IP協議為基礎
9.Gc(垃圾回收機制)的四種演算法
及時清除不再使用的物件,將記憶體清理出來,
①引用計數法:
②標記清除法:
為每個物件儲存一個標記位,記錄物件的狀態(活著或者死亡),死亡則進行清除
③標記壓縮法:
是標記清楚法的改進版,該演算法不會對死亡的物件直接清理,而是將所有存活的對 象整理一下,放到另一個空間,然後把剩下的物件全部清除
優點: 該演算法不會產生大量的碎片空間
缺點: 如果存活物件過多,整理階段將會執行過多的複製操作,導致演算法效率
④複製演算法:
將記憶體評分分成兩部分,然後每次只使用其中一部分,當這部分記憶體滿的時候,將 記憶體中存活的物件複製到另一個記憶體中,然後將之前的記憶體清空,只使用這部分內 存,迴圈下去。
2.資料
- 八大基礎型別:
byte(位元組) 1bit (8位) 、shot(短整型) 2bit (16位)、int(整型) 4bit (32位)、long(長整型) 8bit (64位)、float(浮點型) 4bit (32位)、double(雙精度) 8bit (64位)、char(字元型) 2bit (16位)、boolean(布林型) 1位 - 集合
Connection介面:
— List 有序,可重複
ArrayList
優點: 底層資料結構是陣列,查詢快,增刪慢。
缺點: 執行緒不安全,效率高
Vector
優點: 底層資料結構是陣列,查詢快,增刪慢。
缺點: 執行緒安全,效率低
LinkedList
優點: 底層資料結構是連結串列,查詢慢,增刪快。
缺點: 執行緒不安全,效率高
—Set 無序,唯一
HashSet
底層資料結構是雜湊表。(無序,唯一)
如何來保證元素唯一性?
1.依賴兩個方法:hashCode()和equals()
LinkedHashSet
底層資料結構是連結串列和雜湊表。(FIFO插入有序,唯一)
1.由連結串列保證元素有序
2.由雜湊表保證元素唯一
TreeSet
底層資料結構是紅黑樹。(唯一,有序) - 如何保證元素排序的呢?
自然排序
比較器排序
2.如何保證元素唯一性的呢?
根據比較的返回值是否是0來決定
Map介面有三個比較重要的實現類,分別是HashMap、TreeMap和HashTable。
TreeMap是有序的,HashMap和HashTable是無序的。
Hashtable的方法是同步的,HashMap的方法不是同步的。這是兩者最主要的區別。
這就意味著:
Hashtable是執行緒安全的,HashMap不是執行緒安全的。
HashMap效率較高,Hashtable效率較低。
如果對同步性或與遺留程式碼的相容性沒有任何要求,建議使用HashMap。 檢視Hashtable的原始碼就可以發現,除建構函式外,Hashtable的所有 public 方法宣告中都有 synchronized關鍵字,而HashMap的原始碼中則沒有。
Hashtable不允許null值,HashMap允許null值(key和value都允許)
父類不同:Hashtable的父類是Dictionary,HashMap的父類是AbstractMap
3多執行緒
-
執行緒池的工作原理
先啟動若干數量的執行緒,並讓這些執行緒都處於睡眠狀態,當客戶端有一個新請求時,就會喚醒執行緒池中的某一個睡眠執行緒,讓它來處理客戶端的這個請求,當處理完這個請求後,執行緒又處於睡眠狀態 -
多執行緒中安全集合:
執行緒安全(Thread-safe)的集合物件:
Vector 執行緒安全:
HashTable 執行緒安全:
StringBuffer 執行緒安全: -
鎖的型別
重量級鎖
內建鎖在Java中被抽象為監視器鎖(monitor)。在JDK 1.6之前,監視器鎖可以認為直接對應底層作業系統中的互斥量(mutex)。這種同步方式的成本非常高,包括系統呼叫引起的核心態與使用者態切換、執行緒阻塞造成的執行緒切換等。因此,後來稱這種鎖為“重量級鎖”。
偏向鎖
是一種編譯解釋鎖。如果程式碼中不可能出現多執行緒兵法爭搶同一個鎖的時候,JVM編譯程式碼,解釋執行的時候,會自動放棄同步資訊。消除synchronized的同步程式碼結果。使用鎖標記的形式記錄鎖狀態。再Monitor中有變數ACC_SYNCHRONIZED。當變數值使用的時候,代表偏向鎖鎖定。可以避免鎖的爭搶和鎖池狀態的維護,提高效率。
輕量級鎖
過度鎖。當偏向鎖不滿足,也就是有多執行緒併發訪問,鎖定同一個物件的時候,先提升為輕量級鎖。也是使用標記ACC_SYNCHRONIZED標記記錄的。ACC_UNSYNCHRONIZED標記記錄未獲取到鎖資訊的執行緒。就是隻有兩個執行緒爭搶鎖標記的時候,優先使用輕量級鎖。
兩個執行緒也可能出現重量級鎖。
自旋鎖
是一個過渡鎖,是偏向鎖和輕量級鎖的過渡。
當獲取鎖的過程中,未獲取到。為了提高效率,JVM自動執行若干次空迴圈,在次申請鎖,而不是進入阻塞狀態的情況。稱為自旋鎖。 -
悲觀鎖和樂觀鎖:
悲觀鎖:總是假設最壞的情況發生,因此每次在取資料的時候就會加鎖,操作完成後才釋放鎖。
樂觀鎖:假設大資料情況下不會發生資料衝突,因此在取資料的時候不加鎖,只有在更新的時候判斷該資料在此期間釋放被修改過.實現機制是CAS。 -
執行緒的生命週期
New(初始化狀態)
Runnable(可執行/執行狀態)
Blocked(阻塞狀態)
Waiting(無時間限制的等待狀態)
Timed_Waiting(有時間限制的等待狀態)
Terminated(終止狀態) -
實現多執行緒方法
1.繼承Thread類,重寫run()方法
2.實現Runnable介面並例項化一個執行緒
3.使用ExecutorService、Callable、Future實現有返回結果的多執行緒
7.如何防止死鎖
1.設定加鎖順序
如果一個執行緒需要鎖,那麼就需要按照鎖的順序來獲得鎖。比如說,執行緒1佔據著鎖A,,執行緒2和執行緒3只有在獲取鎖A後才能獲取到鎖B(鎖A是鎖B的必要條件),所以執行緒2或3需要等待執行緒A釋放鎖之後才可以進行加鎖操作
缺點:按照順序加鎖是一個很有效的死鎖預防機制,但是按序加鎖也就意味著需要清楚所有可能用到的鎖以及鎖之間的先後順序
2.設定加鎖時長
若一個執行緒在給定的時間內沒有成功的獲取到所需要的鎖,則會進行回退並釋放其所佔用的的鎖,然後等待一段隨機的時間後在進行嘗試
缺點:有些執行緒可能需要花很長時間去執行任務而導致了鎖的超時,所以並不能確定一定發生了死鎖
3.設定死鎖檢測
當一個執行緒獲取鎖後,會對其進行記錄,記錄在資料結構中,如果有執行緒對某鎖進行請求,也會進行記錄。當一個執行緒請求鎖失敗後,這個執行緒會去遍歷鎖的關係圖,如果發現發生了死鎖,執行緒則會進行回退和等待,當然,也有可能發生回退後大量執行緒搶佔同一批鎖的情況,繼而又發生了死鎖,這裡可以對執行緒設定優先順序,讓部分執行緒先進行回退操作 -
執行緒安全
執行緒安全就是多執行緒訪問時,採用了加鎖機制,當一個執行緒訪問該類的某個資料時,進行保護,其他執行緒不能進行訪問直到該執行緒讀取完,其他執行緒才可使用。不會出現資料不一致或者資料汙染。
執行緒不安全就是不提供資料訪問保護,有可能出現多個執行緒先後更改資料造成所得到的資料是髒資料
4.Spring
-
Spring的工作原理
(1). IoC(Inversion of Control)是指容器控制程式物件之間的關係,而不是傳統實現中,由程式程式碼直接操控。控制權由應用程式碼中轉到了外部容器,控制權的轉移是所謂反轉。 對於Spring而言,就是由Spring來控制物件的生命週期和物件之間的關係;IoC還有另外一個名字——“依賴注入(Dependency Injection)”。從名字上理解,所謂依賴注入,即元件之間的依賴關係由容器在執行期決定,即由容器動態地將某種依賴關係注入到元件之中。
(2). 在Spring的工作方式中,所有的類都會在spring容器中登記,告訴spring這是個什麼東西,你需要什麼東西,然後spring會在系統執行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的建立、銷燬都由 spring來控制,也就是說控制物件生存週期的不再是引用它的物件,而是spring。對於某個具體的物件而言,以前是它控制其他物件,現在是所有物件都被spring控制,所以這叫控制反轉。
(3). 在系統執行中,動態的向某個物件提供它所需要的其他物件。
(4). 依賴注入的思想是通過反射機制實現的,在例項化一個類時,它通過反射呼叫類中set方法將事先儲存在HashMap中的類屬性注入到類中。 總而言之,在傳統的物件建立方式中,通常由呼叫者來建立被呼叫者的例項,而在Spring中建立被呼叫者的工作由Spring來完成,然後注入呼叫者,即所謂的依賴注入or控制反轉。 注入方式有兩種:依賴注入和設定注入; IoC的優點:降低了元件之間的耦合,降低了業務物件之間替換的複雜性,使之能夠靈活的管理物件。
AOP(Aspect Oriented Programming)
(1). AOP面向方面程式設計基於IoC,是對OOP的有益補充;
(2). AOP利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了 多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的 邏輯或責任封裝起來,比如日誌記錄,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。
(3). AOP代表的是一個橫向的關 系,將“物件”比作一個空心的圓柱體,其中封裝的是物件的屬性和行為;則面向方面程式設計的方法,就是將這個圓柱體以切面形式剖開,選擇性的提供業務邏輯。而 剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡,但完成了效果。
(4). 實現AOP的技術,主要分為兩大類:一是採用動態代理技術,利用擷取訊息的方式,對該訊息進行裝飾,以取代原有物件行為的執行;二是採用靜態織入的方式,引入特定的語法建立“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的程式碼。
(5). Spring實現AOP:JDK動態代理和CGLIB代理 JDK動態代理:其代理物件必須是某個介面的實現,它是通過在執行期間建立一個介面的實現類來完成對目標物件的代理;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現原理類似於JDK動態代理,只是它在執行期間生成的代理物件是針對目標類擴充套件的子類。CGLIB是高效的程式碼生成包,底層是依靠ASM(開源的java位元組碼編輯類庫)操作位元組碼實現的,效能比JDK強;需要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ註解驅動的切面實際上底層也是通過動態代理實現的
IOC:準備配置檔案、由IOC容器進行解析後設資料、例項化IOC容器
AOP:一是採用動態代理技術,二是採用靜態織入的方式 -
Spring的注入方式
構造器注入
構造器注入依賴於構造方法的實現,構造方法可以是有引數的,也可以是無引數的 。
setter注入
setter注入利用JAVA Bean規範所定 首先將構造方法設定為無參的構造方法,然後利用setter注入為其設定新的值,這是通過java的反射技術得以實現的
介面注入
有時候資源並非來自於自身的系統,而是來自於外界,比如說資料庫連線資源完全可以在Tomcat下配置,然後通過JNDI的方式去獲取它,這樣的資料庫連線資源就屬於開發工程外的資源。 -
Spring的事務管理
1.程式設計式事務管理對基於 POJO 的應用來說是唯一選擇。我們需要在程式碼中呼叫beginTransaction()、commit()、rollback()等事務管理相關的方法,這就是程式設計式事務管理。
2.基於 TransactionProxyFactoryBean的宣告式事務管理
3.基於 @Transactional 的宣告式事務管理
4.基於Aspectj AOP配置事務 -
Spring單例執行緒是否安全
spring框架裡的bean獲取例項的時候都是預設單例模式,所以在多執行緒開發裡就有可能會出現執行緒不安全的問題。當多個使用者同時請求一個伺服器時,容器(tomcat)會給每一個請求分配一個執行緒,這時多個執行緒會併發執行該請求所對應的業務邏輯(controller裡的方法),此時就要注意啦,如果controller(是單例物件)裡有全域性變數並且又是可以修改的,那麼就需要考慮執行緒安全的問題。解決方案有很多,比如設定@scope(“prototype”)為多例模式,為每個執行緒建立一個controller,還可以使用ThreadLocal。 -
Spring請求過程
-
Spring的優缺點
優點:
有了IOC容器,物件間依賴關係交給spring,更專注業務邏輯程式碼。
有了AOP對應OOP,很多功能更方便簡單使用
像一個膠水一樣,把一些好的框架粘合在一起方便實用(資料方面使用MyBatis,controller選擇struts2,直接用spring粘在一起使用。)
缺點:
對比新出的springboot,肯定沒人家好用(這是知乎的一個解釋,覺得有道理)
spring像一個膠水,將框架黏在一起,後面拆分的話就不容易拆分了(這是面試官的一個回答解釋,表示是一個思路。)
springJSP程式碼過多,過於靈活缺乏一個公用的控制器,不適合分散式(這個是CSDN上幾個部落格說的,不知道誰抄誰的,前半部分不說,後面的分散式你知道spring boot ,spring cloud嗎,這都是什麼時候的事了。)
5.Springmvc
1.Springmvc的工作原理
1.使用者傳送請求給點的控制器DispatcherServlet
2.DispatcherServlet接收到使用者請求後,通過HandlerMapping處理器對映器尋找合理的處理器進行處理
3.處理器對映器找到具體的處理器後,生成處理器物件以及處理器攔截器,並返回給前端控制器
4.前端控制器呼叫處理器介面卡,將請求交給處理器處理
5.處理器介面卡呼叫具體的處理器對請求進行處理
6.處理器處理完成後放回ModelAndView
7.處理器介面卡將放回的ModelAndView返回給前端控制器
8.前端控制器將ModelAndView交給檢視解析器進行解析
9.檢視解析器解析之後返回具體的View
10.前端控制器根據具體的View進行渲染
11.前端控制器響應使用者請求
6.mybatis
1.mybatis中#和$區別,以及應用場景
應用場景:
#{ } :#代表佔位符,用來傳遞引數;
:
{ } :
:用來拼接sql 語句的;
區別:
1、#是預編譯的方式,KaTeX parse error: Expected 'EOF', got '#' at position 10: 是直接拼接; 2、#̲不需要關注資料型別,mybat…不做資料類
型轉換,需要自行判斷資料型別;
3、#可以防止sql注入;KaTeX parse error: Expected 'EOF', got '#' at position 44: …e 只有一個引數,預設情況下,#̲{ }中可以寫任意 的名字;{ }中只能用value來接收。
- mybatis的標籤
https://blog.csdn.net/weixin_40950778/article/details/78655288
7.springboot
1.springboot常用的註解
@Service: 註解在類上,表示這是一個業務層bean
@Controller:註解在類上,表示這是一個控制層bean
@Repository: 註解在類上,表示這是一個資料訪問層bean
@Component: 註解在類上,表示通用bean ,value不寫預設就是類名首字母小寫
@Autowired:按型別注入
@Resource: 按名稱裝配
@Configuration:註解在類上,表示這是一個IOC容器,
@Bean: 註解在方法上,宣告當前方法返回一個Bean
@Scope:註解在類上,描述spring容器如何建立Bean例項。
@Value:註解在變數上,從配置檔案中讀取。
@ConfigurationProperties: 賦值,將註解轉換成物件。
@EnableAutoConfiguration啟用 Spring 應用程式上下文的自動配置,試圖猜測和配置您可能需要的bean。
@SpringBootApplication=@ComponentScan+@Configuration+@EnableAutoConfiguration:約定優於配置
@ComponentScan:註解在類上,掃描標註了@Controller等註解的類,註冊 為bean 。
@RestController @RestController 是一個結合了 @ResponseBody 和 @Controller 的註解
@Responsebody:表示該方法的返回的結果直接寫入 HTTP 響應正文(ResponseBody)中,一般在非同步獲取資料時使用,通常是在使用 @RequestMapping 後,返回值通常解析為跳轉路徑,加上@Responsebody 後返回結果不會被解析為跳轉路徑,而是直接寫入HTTP 響應正文中。
@PathVariable、@RequestParam:兩者的作用都是將request裡的引數的值繫結到contorl裡的方法引數裡的,區別在於,URL寫法不同。
@EnablCaching:pring framework中的註解驅動的快取管理功能。
@suppresswarnings: 抑制警告
@Modifying :增,改,刪加註解
- springboot的優缺點
優點:
快速構建專案、對主流開發框架的無配置整合、專案可獨立執行,無須外部依賴Servlet容器、提供執行時的應用監控、極大地提高了開發效率,部署效率、
與雲端計算的天然整合、使編碼,配置,部署,監控變得更簡單。
缺點:
整合度較高,使用過程中不太容易瞭解底層、因為不要自己做配置,專案有的時候會報錯,不容易解決
8.redis
1.redis的資料型別還有應用場景
String:string 型別進行資料儲存的時候主要有get,set,incr(increase加一遞增),decr(decrease減一遞減)等操作。incr等指令本身具有原子操作,所以我們可以利用redis的incr,incrby,decr,decrby來實現原子計數操作。例如:在某場景下面有三個使用者同事訪問,然後對其進行加一操作,那麼最後的值一定會加三。可以利用這一特性來實現業務上的統計資料的需求。
Llists:redis的list底層不是陣列,而是連結串列。lists常用的操作有lpush(左邊插入),rpush(右邊插入),lrange(取資料,lranger key 開始下標 結束下標)。每往lists中插入一條資料,這條資料將作為下標為0的資料。棧後進先出的那種形式。
例如:我們可以利用list來實現一個訊息佇列,而且可以確保先後順序,可以利用lrange來實現分頁功能。在部落格系統中,每篇博文的評論都可以放在單獨一個list中。
set:reids的集合,是一種無序的集合,集合中的元素沒有先後順序。集合中相關的操作也很豐富,如新增元素,刪除已有元素,取交集,取並集,取差集。
例如:QQ有一個社交功能叫“好友標籤”,大家可以給你的好友貼標籤,這時候就可以用redis集合來實現,把使用者的每個集合存在一個集合中。如果要檢視共同好友,也可以把好友存在集合中,比較交集。
zset: redis的有序集合,每個集合都提供了一個序號,赭石排序的依據。
hash:hashes存的是字串和字串之間的對映,比如一個使用者要儲存其全名,姓氏,年齡等,就適合用hash。hash比較像map。
2.redis的持久化
ROB:在指定的時間間隔能對你的資料進行快照儲存
AOF:記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料
用一句話可以將持久化概括為:將資料(如記憶體中的物件)儲存到可永久儲存的儲存裝置中。持久化的主要應用是將記憶體中的物件儲存在資料庫中,或者儲存在磁碟檔案中、 XML 資料檔案中等等
為什麼要做持久化:因為redis的資料是快取在記憶體中的,當你重啟或者關閉系統後,快取在記憶體中的資料就會消失殆盡,再也找不回來,所以,為了能讓資料長期儲存,就一號將Redis快取在記憶體中的資料做持久化成操作。
怎麼實現持久化:
1、RDB持久化方式能夠在指定的時間間隔能對你的資料進行快照儲存。
2、AOF持久化方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料,AOF命令以redis協議追加儲存每次寫的操作到檔案末尾.Redis還能對AOF檔案進行後臺重寫,使得AOF檔案的體積不至於過大。
3、如果你只希望你的資料在伺服器執行的時候存在,你也可以不使用任何持久化。
4、你也可以同時開啟兩種持久化方式, 在這種情況下, 當redis重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整。
-
redis的優點
速度快,因為資料存在記憶體中,類似於HashMap,HashMap的優勢就是查詢和操作的時間複雜度都是O(1)
支援豐富資料型別,支援string,list,set,sorted set,hash
支援事務,操作都是原子性,所謂的原子性就是對資料的更改要麼全部執行,要麼全部不執行
豐富的特性:可用於快取,訊息,按key設定過期時間,過期後將會自動刪除 -
redis哨兵模式
哨兵是redis叢集架構中非常重要的一個元件,主要功能如下:
叢集監控:負責監控redis master和slave程式是否正常工作
訊息通知:如果某個redis例項有故障,那麼哨兵負責傳送訊息作為報警通知給管理員
故障轉移:如果master node掛掉了,會自動轉移到slave node上
配置中心:如果故障轉移發生了,通知client客戶端新的master地址
哨兵的核心知識
故障轉移時,判斷一個master node是當機了,需要大部分的哨兵都同意才行,涉及到了分散式選舉的問題。哨兵至少需要3個例項,來保證自己的健壯性。哨兵 + redis主從的部署架構,是不會保證資料零丟失的,只能保證redis叢集的高可用性
9.solr
1.solr的資料知識點
2.solr和其他的區別
ElasticSearch vs Solr 總結
(1)es基本是開箱即用,非常簡單。Solr安裝略微複雜一丟丟
(2)Solr 利用 Zookeeper 進行分散式管理,而 Elasticsearch 自身帶有分散式協調管理功能。
(3)Solr 支援更多格式的資料,比如JSON、XML、CSV,而 Elasticsearch 僅支援json檔案格式。
(4)Solr 官方提供的功能更多,而 Elasticsearch 本身更注重於核心功能,高階功能多有第三方外掛提供,例如圖形化介面需要kibana友好支撐
(5)Solr 查詢快,但更新索引時慢(即插入刪除慢),用於電商等查詢多的應用;ES建立索引快(即查詢慢),即實時性查詢快,用於facebook新浪等搜尋。Solr 是傳統搜尋應用的有力解決方案,但 Elasticsearch 更適用於新興的實時搜尋應用。
(6)Solr比較成熟,有一個更大,更成熟的使用者、開發和貢獻者社群,而 Elasticsearch相對開發維護者較少,更新太快,學習使用成本較高。
https://www.cnblogs.com/blueskyli/p/8326229.html
3.solr怎麼建立索引
在schema.xml中,配置標籤《field》,建立索引名,並且其中 indexed=“true” 這個屬性,就代表建立了索引。
10.dubbo
1.dubbo的特點和springcloud的區別
SpringCloud和Dubbo都是現在主流的微服務架構,
區別:1、Dubbo是阿里系的分散式服務框架;SpringCloud是Apache旗下的Spring體系下的微服務解決方案;
3、服務的呼叫方式:Dubbo使用的是RPC遠端呼叫,而SpringCloud使用的是 Rest API;
3、服務的註冊中心:Dubbo使用了第三方的ZooKeeper作為其底層的註冊中心,SpringCloud使用Eureka實現註冊中心
5、服務閘道器:Dubbo並沒有本身的實現,只能通過其他第三方技術的整合,而SpringCloud有Zuul路由閘道器,作為路由伺服器,進行消費者的請求分發;
5、SpringCloud還支援斷路器,與git完美整合分散式配置檔案支援版本控制,事務匯流排實現配置檔案的更新與服務自動裝配等等一系列的微服務架構要素
2.dubbo使用者資訊怎麼獲得
用dubbox搭建的微服各模組註冊資訊從zookeeper註冊中心獲取,
用springcloud搭建的微服各模組註冊資訊從eureka註冊中心獲取。
11.nginx
1.nginx的作用
nginx 是輕量級的Web伺服器。由於配置簡單,容量小被應用於各個專案。在java企業級開發中,常常作為前端靜態資源的代理的伺服器,如果配置的好可支援5W併發量。作用:反向代理、正向代理、負載均衡、HTTP伺服器(包含動靜分離)
區別及意義:
正向代理,代理介於 client 與 service 之間, client 通過proxy 去訪問service 返回資源 (代理客戶端) 想象你掛VPN的代理並設定一些東西就可以通過某臺機器翻牆了。
反響代理:proxyService代理service,client 不知道service 的存在,將訪問service 全全交給了proxyService (代理原始伺服器)
理解:nginx代理伺服器這樣你就不用去編寫任何配置,交給nginx 去配置就好了,nginx收到你的請求會自動根據配置轉發到對應的伺服器去。
均衡負載:(多用於伺服器叢集)其實和ZUUL比較像
均衡負載表示通過代理伺服器統一去管理其他伺服器,然後client 訪問代理伺服器(proxyService),proxyService去均衡的分發請給個其他伺服器,保證每個伺服器得到均衡的併發。nginx 通過反向代理實現均衡負載。實現均衡負載的處理方式:
round-robin:輪詢。以輪詢方式將請求分配到不同伺服器上
least-connected:最少連線數。將下一個請求分配到連線數最少的那臺伺服器上
ip-hash :基於客戶端的IP地址。雜湊函式被用於確定下一個請求分配到哪臺伺服器
動靜分離:Nginx提供的動靜分離是指把動態請求和靜態請求分離開,合適的伺服器處理相應的請求,使整個伺服器系統的效能、效率更高。
Nginx可以根據配置對不同的請求做不同轉發,這是動態分離的基礎。靜態請求對應的靜態資源可以直接放在Nginx上做緩衝,更好的做法是放在相應的緩衝伺服器上。動態請求由相應的後端伺服器處理。
12.mysql
1.mysql資料庫的儲存結構、資料庫鎖
Mysql底層用是B樹結構,mysql的資料是放到外部儲存的,因此我們必須減低磁碟的IO次數,因此我們需要儘量降低樹的高度,樹的分叉越多越好,因此B樹正好符合我們的要求。
資料庫鎖:共享鎖(S鎖)、排它鎖(X鎖)。共享鎖只和自身相容,排它鎖都不相容。
2.mysql語句優化
1.框架自帶的模型查詢比原生的sql要慢
2.應儘量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描
3.in 和 not in 也要慎用,否則會導致全表掃描
4.對於連續的數值,能用 between 就不要用 in ;
5.count優化:
6.%abc%的查詢將導致全表掃描
7.sql子句中儘量不要進行函式操作,表示式操作
8.儘可能的使用 varchar 代替 char,因為首先變長欄位儲存空間小,可以節省儲存空間,其次對於查詢來說,在一個相對較小的欄位內搜尋效率顯然要高些。
9.儘量不要給資料庫留NULL,儘可能的使用 NOT NULL填充資料庫,對於varchar 欄位來說 null 是不佔用任何空間的,查詢起來反而還要快,但是對於char(100)來說,哪怕是null也會佔用100位元組空間
10.任何地方都不要使用 select * from t ,用具體的欄位列表代替“*”,不要返回用不到的欄位。
11.儘量避免向客戶端返回大資料量,若資料量過大,可分批處理
12.應儘量避免在 where 子句中使用 or 來連線條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描
13.儘量使用union all替換union,因為union all不過濾,效率高(union去重代價非常高,儘可能的放在程式中去重)
14.能夠用DISTINCT的就不用GROUP BY
15.大資料量的limit操作,使用延遲關聯技巧:select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10; 對於複雜的場景,我們可以建立符合索引(有where 條件,又想走索引用limit的,必須設計一個索引,將where 放第一位,limit用到的主鍵放第2位,而且只能select 主鍵)
16.向資料庫中插入多條資料,拼接成一條sql語句最快
17. 儘量不要用SELECT INTO語句。SELECT INTO 語句會導致表鎖定,阻止其他使用者訪問該表。
3.mysql與oracle的對比
1、本質的區別
Oracle資料庫是一個物件關聯式資料庫管理系統(ORDBMS)。它通常被稱為Oracle RDBMS或簡稱為Oracle,是一個收費的資料庫。
MySQL是一個開源的關聯式資料庫管理系統(RDBMS)。它是世界上使用最多的RDBMS,作為伺服器執行,提供對多個資料庫的多使用者訪問。它是一個開源、免費的資料庫。
2、資料庫安全性
MySQL使用三個引數來驗證使用者,即使用者名稱,密碼和位置;Oracle使用了許多安全功能,如使用者名稱,密碼,配置檔案,本地身份驗證,外部身份驗證,高階安全增強功能等。
3、SQL語法的區別
Oracle的SQL語法與MySQL有很大不同。Oracle為稱為PL / SQL的程式語言提供了更大的靈活性。Oracle的SQL * Plus工具提供了比MySQL更多的命令,用於生成報表輸出和變數定義。
4、儲存上的區別:
與Oracle相比,MySQL沒有表空間,角色管理,快照,同義詞和包以及自動儲存管理。
5、物件名稱的區別:
雖然某些模式物件名稱在Oracle和MySQL中都不區分大小寫,例如列,儲存過程,索引等。但在某些情況下,兩個資料庫之間的區分大小寫是不同的。
Oracle對所有物件名稱都不區分大小寫;而某些MySQL物件名稱(如資料庫和表)區分大小寫(取決於底層作業系統)。
6、執行程式和外部程式支援:
Oracle資料庫支援從資料庫內部編寫,編譯和執行的幾種程式語言。此外,為了傳輸資料,Oracle資料庫使用XML。
MySQL不支援在系統內執行其他語言,也不支援XML。
7、MySQL和Oracle的字元資料型別比較:
兩個資料庫中支援的字元型別存在一些差異。對於字元型別,MySQL具有CHAR和VARCHAR,最大長度允許為65,535位元組(CHAR最多可以為255位元組,VARCHAR為65.535位元組)。
而,Oracle支援四種字元型別,即CHAR,NCHAR,VARCHAR2和NVARCHAR2; 所有四種字元型別都需要至少1個位元組長; CHAR和NCHAR最大可以是2000個位元組,NVARCHAR2和VARCHAR2的最大限制是4000個位元組。可能會在最新版本中進行擴充套件。
8、MySQL和Oracle的額外功能比較:
MySQL資料庫不支援其伺服器上的任何功能,如Audit Vault。另一方面,Oracle支援其資料庫伺服器上的幾個擴充套件和程式,例如Active Data Guard,Audit Vault,Partitioning和Data Mining等。
9、臨時表的區別:
Oracle和MySQL以不同方式處理臨時表。
在MySQL中,臨時表是僅對當前使用者會話可見的資料庫物件,並且一旦會話結束,這些表將自動刪除。
Oracle中臨時表的定義與MySQL略有不同,因為臨時表一旦建立就會存在,直到它們被顯式刪除,並且對具有適當許可權的所有會話都可見。但是,臨時表中的資料僅對將資料插入表中的使用者會話可見,並且資料可能在事務或使用者會話期間持續存在。
10、MySQL和Oracle中的備份型別:
Oracle提供不同型別的備份工具,如冷備份,熱備份,匯出,匯入,資料泵。Oracle提供了最流行的稱為Recovery Manager(RMAN)的備份實用程式。使用RMAN,我們可以使用極少的命令或儲存指令碼自動化我們的備份排程和恢復資料庫。
MySQL有mysqldump和mysqlhotcopy備份工具。在MySQL中沒有像RMAN這樣的實用程式。
11、Oracle和MySQL的資料庫管理:
在資料庫管理部分,Oracle DBA比MySQL DBA更有收益。與MySQL相比,Oracle DBA有很多可用的範圍。
12、資料庫的認證:
MySQL認證比Oracle認證更容易。
與Oracle(設定為使用資料庫身份驗證時)和大多數僅使用使用者名稱和密碼對使用者進行身份驗證的其他資料庫不同,MySQL在對使用者進行身份驗證location時會使用其他引數。此location引數通常是主機名,IP地址或萬用字元。
使用此附加引數,MySQL可以進一步將使用者對資料庫的訪問限制為域中的特定主機或主機。此外,這還允許根據進行連線的主機為使用者強制實施不同的密碼和許可權集。因此,從abc.com登入的使用者scott可能與從xyz.com登入的使用者scott相同或不同。
4.mysql的執行計劃(EXPLAIN)
13.zookeeper
1.zookeeper原理和作用
ZooKeeper是一個分散式的,開放原始碼的分散式應用程式協調服務。 功能:主要是用來解決分散式應用中經常遇到的一些資料管理問題,如:統一命名服務、狀態同步服務、叢集管理、分散式應用配置項的管理等。 原理:Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啟動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。
14.其他基礎
1.MQ
各種MQ的比較
ActiveMQ:
優點: 技術成熟,功能齊全,歷史悠久,有大量公司在使用
缺點: 偶爾會有較低概率丟失資料,而且社群已經不怎麼維護5.15.X版本
適用場景: 主要用於系統解耦和非同步處理,不適用與大資料量吞吐情況。網際網路公司很少適用
rabitMQ:
優點: 吞吐量高,功能齊全,管理介面易用,社群活躍,效能極好
缺點: 吞吐量只是萬級,erlang難以二次開發和掌控;叢集動態擴充套件非常麻煩
適用場景: 吞吐量不高而要求低延遲,並且不會頻繁調整和擴充套件的場景。非常適合國內中小型網際網路公司適用,因為管理介面非常友好,可以在介面進行配置和優化/叢集監控
rocketMQ
優點: 支援百千級大規模topic。吞吐量高(十萬級,日處理上百億)。介面易用。,分散式易擴充套件,阿里支援。java開發易於掌控
缺點: 與阿里(社群)存在繫結。不相容JMS規範
適用場景: 高吞吐量
Kafka
優點: 超高吞吐量,超高可用性和可靠性,分散式易擴充套件
缺點: topic支援少,MQ功能簡單,訊息可能會重複消費影響資料精確度
適用場景: 超高吞吐量場景而資料精確度沒那麼高,天然適合大資料實時計算和日誌採集場景
2.為什麼要用訊息佇列?
解耦:A系統呼叫B系統、C系統,傳統的呼叫是直接呼叫,但是當B系統說我不需要你提供資料了,這時候A需要改程式碼,C系統說我不需要某個欄位了,這時候A也要改程式碼,如果又多了一個D系統,A又要寫程式碼。為了實現解耦,引入訊息佇列,A將產生的資料丟到訊息佇列中,哪個系統需要,哪個系統就去取;
非同步:A系統呼叫B系統,B系統由於某個需要呼叫第三方介面超時,導致A系統響應速度慢,而B系統的好壞又不會影響業務邏輯,所以可以改為A非同步呼叫B,A將訊息丟到訊息佇列中,B系統訂閱訊息,實現A的快速響應;
削峰:當大量流量請求到系統A時,由於資料庫的處理能力有限,造成資料庫連線異常。使用訊息佇列,大量請求先丟到訊息佇列中,系統A使用按批拉資料的方式,批量處理資料,生產中,高峰期短暫的訊息積壓是允許的。
3.使用訊息佇列有什麼缺點
系統複雜性增加:需要考慮訊息的處理,包括訊息冪等性(重複消費問題),訊息保序性(一個訂單多條訊息問題),以及訊息中介軟體本身的持久化和穩定性可靠性
系統的可用性降低:解耦後,多個系統通過訊息中介軟體互動,訊息中介軟體掛了整個系統就掛了
4.什麼是分散式、叢集?
多臺伺服器合起來跑的才是一套完整程式碼,這就叫分散式;多臺伺服器跑的都是一套完整的程式碼,這就叫叢集
目錄
一、恆生電子面試題 4
1、JVM原理 4
2、事務如何主動回滾? 4
3、dubbo的優點 5
4、spring作用 6
5、事務ACID 7
6、最近在看什麼書? 7
7、最近學會什麼技術? 7
8、消費者呼叫提供者如果網路斷了怎麼辦? 8
二、軟通動力面試題 8
1、說幾個執行緒安全的類 9
2、介紹springMVC 9
3、講講棧記憶體和堆記憶體 10
4、Oracle常用函式 10
1.單行函式 10
2.數值函式 11
3.轉換函式 11
4.聚合函式 11
5、資料庫檢視的優化,儲存過程 12
資料庫優化方式有: 12
使用儲存過程實現優化,因為儲存過程的優點很多: 13
如何保證介面的安全可靠, 13
6、常用的集合和區別 13
1.Collection 13
2.LinkedList類 14
3.AyyayList類 14
4.Vector類 14
5.Set介面 15
6.TreeSet 15
7.Map介面 15
7、gc如何呼叫 15
8、多表連線注意事項 16
9、檢視優缺點 16
1.檢視的優點: 16
2.檢視的缺點: 16
10、使用者登入登出之後要做什麼事 17
11、Linux 命令 17
三、公司面試題 19
1、說說你專案中為什麼使用Springboot,dubbo,redis,activeMQ? 19
1.Spring Boot作為微服務的入門級微框架,有四點好處 19
2、Redis 持久化的原理 20
3、IOC的原理 20
4、如何反射生成一個物件? 21
5、spring註解開發瞭解一下 21
6、前端獲取資料有幾種方式 22
7、Jquery 22
8、盒子模型 22
9、鎖的用法還有注意事項 22
1.減少鎖持有時間 23
2.減小鎖粒度 23
3.鎖分離 23
4.鎖粗化 23
5.鎖消除 23
四、有贊面試題 23
1、redis常用命令: 24
1)連線操作命令 24
2)持久化 24
3)遠端服務控制 24
4)對value操作的命令 24
5)String 24
6)List 25
7)Set 25
8)Hash 25
2、你瞭解hashMap嗎? 底層實現方式?執行緒安全嗎?如何實現安全?CocurrentHashMap瞭解嗎? 26
3、如何建立多執行緒?執行緒池的作用? 26
4、執行緒池 26
一個執行緒池包括以下四個基本組成部分: 26
5、 Object類的常用方法 27
五、海康威視面試題 27
1、Arraylist 呼叫方法注意事項 27
2、支付過程中斷網怎麼辦 27
3、一個專案如何支援兩個資料庫通用,修改哪些部分的程式碼 28
4、Hibernate 和mybstis 差異性 28
5、Spring內部實現機制 29
6、Ioc和aop底層如何實現 29
1.IoC(Inversion of Control) 29
2.AOP(Aspect Oriented Programming) 30
7、註解開發程式碼怎麼寫的,問註解裡面是怎麼實現的? 30
8、JQuery 和ext的區別 30
9、Ext 能實現哪些jQuery 實現不了的 31
10、Ioc通過一個註解實現依賴注入,裡面程式碼是怎麼實現的? 31
11、前端向後端可以發請求,後端怎麼向前端拋訊息? 31
六、崑山媽媽好面試題 31
1、執行緒的啟動停止,如何同步 31
2、保證執行緒同步的方式可以通過以下7種方式: 32
1.同步方法 32
2.同步程式碼塊 32
3.使用特殊域變數(volatile)實現執行緒同步 32
4.使用重入鎖實現執行緒同步 32
5.使用區域性變數實現執行緒同步 32
6.使用阻塞佇列實現執行緒同步 33
7.使用原子變數實現執行緒同步 33
3、springmvc的請求流程 33
4、前端是否使用靜態頁面 34
5、前端框架 34
6、springboot介紹 34
7、web.xml的作用 34
8、執行緒在非同步方法的停止方法 34
8、過濾器的作用 35
9、cloud 35
10、資料庫讀寫分離的實現 35
11、主從資料庫同步的實現思路: 35
七、支付寶螞蟻金服 36
1、String Stringbuffer Stringbuilder 36
2、Dubbox工作原理 36
3、Nginx網段配置 37
4、資料表索引的必要性 37
5、分散式不使用redis和cookie和session怎麼多伺服器共享使用者登入狀態 38
6、資料庫儲存模式 38
7、InnoDB是哪種讀取型別 39
8、資料庫中事務鎖 39
9、樂觀鎖的優勢和劣勢 40
10、網際網路高併發小輕快如何實現 40
11、資料庫優化 40
12、Docker 42
1、簡化程式: 42
2、避免選擇恐懼症: 42
3、節省開支: 42
八、公司筆試題 42
1、多執行緒Hashmap死迴圈的操作是由於哪一步 42
2、講述一下Hashmap的實現原理 43
3、List的實現類有哪些 43
4、微信支付寶銀聯的接入流程 44
5、Maven的操作命令你知道的有哪些 45
6、談談高併發的測試 45
7、你知道哪些演算法 45
1.快速排序演算法 45
2.動態規劃演算法 45
8、Mybatis分頁外掛有了解嗎 45
9、全域性異常怎麼實現 46
10、進行搶購時你們redis的鍵是怎麼設計的 46
11、鎖的原理 46
12、同步程式碼塊和方法加鎖的區別 46
13、mybatis懶載入的原理 46
14用什麼技術代替儲存過程 47
其他面試題 47
1、高併發解決方案: 47
2、資料庫優化思路: 48
3、常用的中介軟體: 48
4、關於事務的面試題: 48
一、什麼是事務?有什麼用?事務的特性ACID 48
二 事務的併發會產生的問題有哪些 48
三 不可重複讀和幻讀的區別 49
四、spring 事務隔離級別 49
五、spring事務的傳播行為 49
六 Spring宣告式事務的回滾機制 50
七 分散式環境下如何處理事務 50
5、微服務架構下處理分散式事務,你必須知道的事兒 50
一致性理論 51
一致性模型 52
分散式事務解決方案 52
選擇建議 56
一、恆生電子面試題
1、JVM原理
內容見<面試必問之JVM原理>,參考地址
JVM->java虛擬機器,直譯器,負責將程式設計師編寫的.java檔案編譯為多平臺通用的位元組碼(.class)檔案,最終將位元組碼解釋給計算機執行
[JVM記憶體區域主要劃分為“執行緒共享區”“非執行緒共享區”,比如,Method Area(方法區,non-heap)與Heap(堆),Direct Memory(執行時資料區域)是執行緒共享的,VM Stack(java方法棧,虛擬機器棧),Native Method Stack(本地方法棧)和Program Counter Register(程式計數器)是非執行緒共享的]
- 工作過程:
:JVM執行時初始分配方法區與堆,遇到執行緒時,分配程式計數器,虛擬機器棧,本地方法棧,執行緒終止時,三者的記憶體空間會被釋放(生命週期==所屬執行緒生命週期),這也是為什麼GC機制只會發生在“執行緒共享區”的原因。
2、事務如何主動回滾?
3. 在spring框架的宣告式事務處理中,只要丟擲的異常是屬於執行時異常的,spring的異常處理機制會自動回滾事務.
↑所屬情景:java中的框架處理
如果是資料庫中的事務,在你commit提交前執行rollback命令就好了,如果是已經commit的事務就不好恢復了。
3、dubbo的優點
首先Dubbo 是阿里巴巴公司開源的一個高效能優秀的服務框架,使得應用可通過高效能的 RPC 實現服務的輸出和輸入功能,可以和 Spring框架無縫整合。
1.遠端通訊: 提供對多種基於長連線的NIO框架抽象封裝,包括多種執行緒模型,序列化,以及“請求-響應”模式的資訊交換方式。
2.軟負載均衡及容錯機制: 提供基於介面方法的透明遠端過程呼叫,包括多協議支援,以及軟負載均衡,失敗容錯,地址路由,動態配置等叢集支援.可在內網替代F5等硬體負載均衡器,降低成本,減少單點
3.服務自動註冊與發現: 基於註冊中心目錄服務,使服務消費方能動態的查詢服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器
4.提供完善的管理控制檯dubbo-admin與簡單的控制中心dubbo-monitor
5.Dubbo提供了伸縮性很好的外掛模型,很方便進行擴充套件(ExtensionLoader)
6.支援多協議
使用方法:
Dubbo採用全Spring配置方式,透明化接入應用,對應用沒有任何API侵入,只需用Spring載入Dubbo的配置即可,Dubbo基於Spring的Schema擴充套件進行載入。
太長不看,背不下來的建議回答如下:
Dubbo,作為阿里的優秀開源框架,確實比較好用,跟spring相容度也不錯,它本身有很多優點,比如負載均衡跟容錯之類做的都比較好,但我覺得最好的一點是它提供了伸縮性很好的外掛模型,這點可以讓你很方便的進行擴充套件,給了我們更多的可能性。
(接下來可以嘗試繞過這個話題了)
4. dubbo中消費者呼叫提供者原理
Provider:暴露服務方稱之為“服務提供者”
Consumer:呼叫遠端服務方稱之為“服務消費者”
Registry:服務註冊與發現的中心目錄服務稱之為“服務註冊中心”
Monitor:統計服務的呼叫次調和呼叫時間的日誌服務稱之為“服務監控中心”
Provider釋出後會在Registry中註冊,Consumer從Registry訂閱服務,一旦註冊中心提供了Provider, Consumer就可以非同步得到通知,從而呼叫Provider的功能,這兩者都會在Monitor監控中心中被記錄呼叫的資訊.
看起來繞口,其實描述不如畫圖↓↓↓↓↓
4、spring作用
Spring框架主要用於與其他技術(struts,hibernate等)進行整合,可將 應用程式中的Bean元件實現低耦合關聯.最終可以提高系統擴充套件和維護 性.將來我們利用Spring框架管理系統的各個元件(Action,Service,DAO)採 用Spring的IOC和AOP機制實現各元件的關聯.從而實現了低耦合呼叫. 增強了系統可維護性和擴充套件性.
降低元件耦合性,實現程式各層解耦;
主流框架整合,如XXX;
低侵入式設計,不影響程式碼;
最主要的還是IOC與AOP,讓我們更加方便快捷的進行開發。
主要解釋IOC與AOP:
IOC:依賴注入(控制反轉),將所需要用到的類以註解或配置檔案的方式提供給spring,由spring生成(預設為單例)物件,更簡單的實現業務物件。 [注入方式有兩種,第一種是設定注入,比較直觀,自然。第二種是構造注入,可以在構造器中指定依賴關係順序]
(底層實現基本就是反射機制那一套,熟的可以BB兩句)
AOP:切面程式設計,基於OOP物件導向的一種補充。主要是提供一個更好更方便的事務管理方式,同時也支援我們自定義切面。[物件導向是將程式分解為各個層次的物件,面向切面是將程式執行過程分解為各個切面。] [OOP是靜態的抽象,AOP是動態的,對應用執行過程中的步驟進行抽象,從而獲得步驟之間的邏輯劃分。]
(*主要特性) AOP以步驟劃分,各個步驟之間有非常好的隔離型,並且與原始碼沒有什麼關聯性。你可以很方便的在某個步驟前後加上自己想要的操作。
5、事務ACID
ACID,指資料庫事務正確執行的四個基本要素的縮寫。包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、永續性(Durability)。一個支援事務(Transaction)的資料庫,必須要具有這四種特性,否則在事務過程(Transaction processing)當中無法保證資料的正確性,交易過程極可能達不到交易方的要求。
原子性:要麼不談,要談就要結婚。
一致性:戀愛時,什麼方式愛我;結婚後還得什麼方式愛我;
隔離性:鬧完洞房後,是倆人的私事。
永續性:一旦領了結婚證,無法後悔。
6、最近在看什麼書?
<JVM虛擬機器原理><java設計模式><重構>
Java高併發程式設計模式與原則
7、最近學會什麼技術?
Shiro框架,還了解了一些SpringCloud體系的Eureka, Config, Bus,Hadoop生態圈MapRecude,HBASE,Spark,Kafka的知識點,正準備深入
SpringCloud:
Q:什麼是springcloud?
A:springcloud是一套完整的微服務解決方案,基於springboot框架。但準確來說,它並不是一個框架,而更像是一個大的容器,將市面上成型比較好的微服務框架整合進來,簡化了開發者的程式碼;
Q:spring核心元件:
A:分兩類
一類是融合在微服務中,依賴其他元件併為其提供服務:
Ribbon客戶端負載均衡;
Hystrix客戶端容錯保護;
Feign宣告式服務呼叫,本質上是Ribbon+Hystrix;
Stream 訊息驅動;
Bus訊息匯流排;
Sleuth分散式服務追蹤
第二類是獨自啟動,不需要依賴其他元件的:
Eureka 服務註冊中心;
Dashboard Hystrix儀表盤;
Zuul API服務閘道器
Config 分散式配置中心
8、消費者呼叫提供者如果網路斷了怎麼辦?
三種方案1,dubbo部署叢集,當前網路中斷可在叢集中匹配到其它提供者實現,如果沒有找到其它提供者, 服務提供者和服務消費者仍能通過本地快取通訊,直到網路恢復.2 消費者在呼叫過程中如果得不到提供者的回饋則設定時間取消操作,事務進行回滾處理.保證事務完整性3將請求訊息放入訊息佇列中,提示使用者操作,當提供者正常服務後進行消費,從而保證事務完整性.
如果是客戶網斷的情況大多不用擔心,根據當前環境判斷是否回滾,給出通知讓使用者上線後知道剛才做了什麼,保留了什麼,業務進行到哪。
如果是伺服器斷網(環境肯定是分散式了)
判斷是否有叢集,有則直接切換。沒有叢集的話消費者讀取本地快取,繼續提供服務,實在獲取不到服務的情況下,為了保證資料安全,消費者將在設定時間後進行事務回滾,除此之外,請求訊息可暫時放入訊息佇列,在提供者上線後再進行操作。
二、軟通動力面試題
1、說幾個執行緒安全的類
Timer,TimerTask,Vector,Stack,HashTable,ConcurrentHashMap,StringBuffer
2、介紹springMVC
Spring MVC框架是有一個MVC框架,通過實現Model-View-Controller模式來很好地將資料、業務與展現進行分離。從這樣一個角度來說,Spring MVC和Struts、Struts2非常類似。Spring MVC的設計是圍繞DispatcherServlet展開的,DispatcherServlet負責將請求派發到特定的handler。通過可配置的handler mappings、view resolution、locale以及theme resolution來處理請求並且轉到對應的檢視,具體的請求流程如下:
1、使用者傳送請求至前端控制器DispatcherServlet
2、DispatcherServlet收到請求呼叫HandlerMapping處理器對映器查詢Handler。HandlerMapping可以根據xml配置、註解配置進行查詢。
3、處理器對映器根據請求url找到具體的處理器,生成處理器物件及處理器攔截器(如果有則生成)一併返回給DispatcherServlet。
4、DispatcherServlet通過HandlerAdapter處理器介面卡呼叫處理器,處理器在實際開發中習慣稱為controller(另一種說法處理器是後端控制器,最終呼叫service進行業務處理)。
5、HandlerAdapter呼叫處理器Handler
6、Handler執行完成返回ModelAndView,ModelAndView是springmvc的封裝物件,將模型和檢視封裝在一個物件中。
7、HandlerAdapter將Handler執行結果ModelAndView返回給DispatcherServlet
8、DispatcherServlet將ModelAndView傳給ViewReslover檢視解析器,ViewReslover根據邏輯檢視名解析View邏輯檢視名:如果指定具體的jsp完整地址不方便,將完整的地址簡化為邏輯的檢視名(串)。view:是一個介面,介面實現了很多型別的view(比如:jstlView、pdfView、freemarker、報表的view)ViewReslover:不同的檢視解析器可以解析出上邊不同的view.
9、ViewReslover返回View
10、DispatcherServlet對View進行渲染檢視(即將模型資料填充至request域)。
11、DispatcherServlet響應使用者(將jsp轉發給使用者,最終由tomcat解析servlet生成html,最終響應)
它在程式中可以設定成單例,因為沒有全域性的資料域.
3、講講棧記憶體和堆記憶體
棧:主要是用來執行程式的,堆:主要用來存放物件的
棧(stack):有編譯器自動分配和釋放,存放函式的引數、區域性變數、臨時變數、函式返回地址等;
堆(heap):一般有程式設計師分配和釋放,如果沒有手動釋放,在程式結束時可能由作業系統自動釋放(?這個可能針對Java那樣的有回收機制的語言而說的,對於c/c++,這樣的必須要手動釋放開闢的堆記憶體),稍有不慎會引起記憶體洩漏。
棧:只要棧的剩餘空間大於所申請的空間,系統將為程式提供記憶體,否則將報異常提示棧溢位。
堆:在記錄空閒記憶體地址的連結串列中尋找一個空間大於所申請空間的堆結點,然後將該結點從空閒結點連結串列中刪除,並將該結點的空間分配給程式。另外,對於大多數系統會在這塊記憶體空間的首地址出記錄本次分配空間的大小,這樣程式碼中的delete 才能正確釋放本記憶體空間。系統會將多餘的那部分重新空閒連結串列中。
棧:由系統自動分配,速度較快。但程式設計師是無法控制的。
堆:由new分配的記憶體,一般速度比較慢,而且容易產生記憶體碎片,不過用起來最方便.
4、Oracle常用函式
1.單行函式
(1)concat(str1,str2)字串拼接函式
(2)initcap(str)將每個單詞首字母大寫,其他字母小寫
(3)instr(x,find_string[,start][,occurrence])返回指定字串在某字串中的位置,可以指定搜尋的開始位置和返回第幾次搜尋出來的結果
(4)length(str)返回表示式中的字元數
(5)lengthb(str)返回表示式中的位元組數
(6)lower(str)將字串轉換為小寫
(7)upper(str)將字串轉換為大寫
(8)lpad(str,width[,pad_string])當字串長度不夠時,左填充補齊,可以指定補齊時用什麼字元補齊,若不指定,則以空格補齊
(9)rpad(str,width[,pad_string])當字串長度不夠時,右填充補齊,原理同左填充
(10)ltrim(x[,trim_string])從字串左側去除指定的所有字串,若沒有指定去除的字串,則預設去除左側空白符
(11)rtrim(x[,trim_string])從字串右側去除指定的所有字串,原理同ltrim()
(12)trim(trim_string from x)從字串兩側去除指定的所有字串
(13)nvl(x,value)將一個NULL轉換為另外一個值,如果x為NULL,則返回value,否則返回x值本身
(14)nvl2(x,value1,value2),如果x不為NULL,返回value1,否則,返回value2
(15)replace(x,search_string,replace_string),從字串x中搜尋search_string字串,並使用replace_string字串替換。並不會修改資料庫中原始值
(16)substr(x,start[,length])返回字串中的指定的字元,這些字元從字串的第start個位置開始,長度為length個字元;如果start是負數,則從x字串的末尾開始算起;如果 length省略,則將返回一直到字串末尾的所有字元
2.數值函式
(1)abs(value)返回value的絕對值
(2)ceil(value)返回大於等於value的最小整數
(3)floor(value)返回小於等於value的最大整數
(4)trunc(value,n)對value進行截斷,如果n>0,保留n位小數;n<0,則保留-n位整數位;n=0,則去掉小數部分
(5)round(value,n)對value進行四捨五入,儲存小數點右側的n位。如果n省略的話,相當於n=0的情況
3.轉換函式
(1)to_char(x[,format]):將x轉化為字串。 format為轉換的格式,可以為數字格式或日期格式
(2)to_number(x [, format]):將x轉換為數字。可以指定format格式
(3)cast(x as type):將x轉換為指定的相容的資料庫型別
(4)to_date(x [,format]):將x字串轉換為日期
4.聚合函式
(1)avg(x):返回x的平均值
(2)count(x):返回統計的行數
(3)max(x):返回x的最大值
(4)min(x):返回x的最小值
(5)sum(x):返回x的總計值
5、資料庫檢視的優化,儲存過程
檢視是指計算機資料庫中的檢視,是一個虛擬表,其內容由查詢定義。對於複雜的連表查詢,可以利用建立檢視來使SQL語句變得簡單。
資料庫優化方式有:
1.給適當的列加上索引。
2儘量避免全表掃描,首先應考慮在where及order by涉及的列上建立索引。
3.避免使用 select * 從資料庫裡讀出越多的資料,那麼查詢就會變得越慢
4永遠為每張表設定一個ID使用VARCHAR型別來當主鍵會使得效能下降
5使用ENUM而不是VARCHAR
sex ENUM(‘男’,‘女’)
如果一個列只含有有限樹木的特定值,比如:性別、狀態等,儘量採用ENUM列舉出所有可能的取值作為資料型別,enum列的值都是以標識數值標識,mysql會處理的更快。
6.儘量避免在where子句中使用or來連線條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描
7.模糊查詢不要以萬用字元開始,否則會導致索引失效而進行全表掃描
select from t_student where sName like ‘a%’
8.儘量避免在where子句中對欄位進行表示式操作,這會導致引擎失效放棄使用索引而進行全表掃描。
select id from t where num/2=100
應該改為 select id from t where num=1002
9.In和not in要慎用,否則可以導致全表掃描,可以用exists代替In。
Select num from a where num in(select num from b)
用下面的語句替換
Select num from a where exists(select 1 from b where num=a.num)
10.一個表的索引最好不要超過6個,若太多則應考慮刪除不常使用的索引
11.儘量避免大事務操作,提高系統併發能力
12.並不是所有索引對查詢都有效,當索引列有大量資料重複時,SQL查詢可能不會去利用索引,如果一表中有欄位sex,male,female幾乎各一半,那麼即使在sex上建了索引頁會查詢效率起不了太大作用
使用儲存過程實現優化,因為儲存過程的優點很多:
1儲存過程只在創造時進行編譯,以後每次執行儲存過程都不需再重新編譯,而一般SQL語句每執行一次就編譯一次,所以使用儲存過程可提高資料庫執行速度。
2當對資料庫進行復雜操作時(如對多個表進行Update,Insert,Query,Delete時),可將此複雜操作用儲存過程封裝起來與資料庫提供的事務處理結合一起使用。
3儲存過程可以重複使用,可減少資料庫開發人員的工作量。
4安全性高,可設定只有某些使用者才具有對指定儲存過程的使用權
如何保證介面的安全可靠,
題意不清.什麼介面?如果是指HTTP介面那麼有如下方式可供選擇
1、選擇攔截過濾器。
在請求的時候對請求方法進行一次攔截處理。比如非正常訪問的方法已經注入插入可執行語句引數驗證等在攔截中進行一次安全校驗保證請求不是非法請求。
2、資料加密。我們知道目前大部分APP介面都是通過Http協議進行呼叫的容易被抓包攔截。我們可以對客戶端和服務端都對資料傳輸的時候進行一個加密處理。常用的MD5 AES等。
3、簽名
根據使用者名稱或者使用者id,結合使用者的ip或者裝置號,生成一個token。在請求後臺,後臺獲取http的head中的token,校驗是否合法(和資料庫或者Redis中記錄的是否一致,在登入或者初始化的時候,存入資料庫/redis)愛旅行專案中就採用的Token方式.
4、使用第三方框架與技術整合支援比如spring的框架中的oauth模組。還有Shiro框架等.
6、常用的集合和區別
1.Collection
Collection是最基本的集合型別,所有實現Collection介面的類都必須提供兩個標準的建構函式:無引數的建構函式用於建立一個共的Collection,有一個Collection引數的建構函式用於建立一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。若要檢查Collection中的元素,可以使用foreach進行遍歷,也可以使用迭代器,Collection支援iterator()方法,通過該方法可以訪問Collection中的每一個元素。
Set和List是由Collection派生的兩個介面.List是有序的Collection,使用此介面能夠精確的控制每個元素插入的位置。使用者能夠使用索引的位置來訪問List中的元素,類似於Java陣列。List允許有相同的元素存在。
實現List介面的常用類有LinkedList、ArrayList、Vector和Stack
2.LinkedList類
LinkedList實現了List類介面,允許null元素。此外LinkedList提供額外的get、remove、insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆疊(stack),佇列(queue)或雙向佇列(deque)
LinkedList沒有同步方法。如果多個執行緒想訪問同一個List,則必須自己實現訪問同步。
3.AyyayList類
ArrayList實現了可變大小的陣列。它允許所有元素,包括null。ArrayList沒有同步。size(),isEmpty(),get(),set()方法執行時間為常數。但是add()方法開銷為分攤的常數,新增n個元素需要O(n)的時間。其他的方法執行時間為線性。每個ArrayList例項都有一個容量(Capactity),即用於儲存元素的陣列的大小。這個容量可隨著不斷新增新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入之前可以呼叫ensureCapacity()方法來增加ArrayList容量已提高插入效率
4.Vector類
Vector非常類似ArrayList,但是Vector是同步的。由Vector建立的iterator,雖然和ArrayLsit建立的iterator是同一介面,但是,因為Vector是同步的,當一個iterator被建立而且這在被使用,另一個執行緒改變了Vector狀態,這時呼叫iterator的方法時將丟擲ConcurrentModificationException,因此必須捕獲該異常。
Stack類
Stack繼承自Vector,實現了一個後進先出的堆疊。Stack提供了5個額外的方法使得Vector得以被當做堆疊使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆疊是否為空,serach方法檢測一個元素在堆疊中的位置。Stack剛建立後是空棧。
5.Set介面
Set是一種不包含重複元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。Set的建構函式有一個約束條件,傳入的Collection引數不能包含重複的元素。請注意:必須小心操作可變物件。如果一個Set中的可變元素改變了自身的狀態導致Object.equals(Object)=true將導致一些問題
HashSet
HashSet呼叫物件的hashCode(),獲得雜湊碼,然後在集合中計算存放物件的位置。通過比較雜湊碼與equals()方法來判別是否重複。所以,過載了equals()方法同時也要過載hashCode();
6.TreeSet
TreeSet 繼承SortedSet介面,能夠對集合中物件排序。預設排序方式是自然排序,但該方式只能對實現了Comparable介面的物件排序,java中對Integer、Byte、Double、Character、String等數值型和字元型物件都實現了該介面。
7.Map介面
Map沒有繼承Collection介面,Map提供key到value的對映。一個Map中不能包含相同的key,每個key只能對映一個value。Map介面提供了3中集合的檢視,Map的內容可以被當作一組key集合,一組value集合,或者一組key–value對映。
HashTable類
HashTable繼承Map介面,實現了一個key–value對映的雜湊表。任何非空的物件都可作為key或者value。新增資料使用put(key,value),取出資料使用get(key),這兩個基本操作的時間開銷為常數。 HashTable通過initial caoacity和load factor兩個引數調整效能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。增大了load factor可以節省空間但相應的查詢時間將增大,這會影響像get和put這樣的操作.HashTable是同步的.
HashMap類
HashMap和HashTable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key,但是將HashMap視為Collection時,其迭子操作時間開銷和HahMap的容量成比例。因此,如果迭代操作的效能相當重要的話,不要將HashMap的初始化容量設的過高,或者load factor過低
7、gc如何呼叫
通過System.gc()方法可以進行呼叫垃圾回收器(GC),但Java的GC是由JVM自行調動的,在需要的時候才執行,上面的指令只是告訴JVM儘快GC一次,但不會立即執行GC。也可以通過對需要回收的物件通過close()或者賦值成null,通知GC儘快回收.
8、多表連線注意事項
.在資料庫中,通常可以通過檢視執行計劃瞭解sql語句的執行順序,以及花費的時間等,但在使用left join時,需要特別注意的是,如果第二張表有篩選條件,應該將連線條件寫在join裡面,而不是寫在where後面.
9、檢視優缺點
1.檢視的優點:
第一點:使用檢視,可以定製使用者資料,聚焦特定的資料。
解釋:在實際過程中,公司有不同角色的工作人員,我們以銷售公司為例的話,採購人員,可以需要一些與其有關的資料,而與他無關的資料,對他沒有任何意義,我們可以根據這一實際情況,專門為採購人員建立一個檢視,以後他在查詢資料時,只需select * from view_caigou 就可以啦。
第二點:使用檢視,可以簡化資料操作。
解釋:我們在使用查詢時,在很多時候我們要使用聚合函式,同時還要顯示其它欄位的資訊,可能還會需要關聯到其它表,這時寫的語句可能會很長,如果這個動作頻繁發生的話,我們可以建立檢視,這以後,我們只需要select * from view1就可以啦,這樣很方便。
第三點:使用檢視,基表中的資料就有了一定的安全性因為檢視是虛擬的,物理上是不存在的,只是儲存了資料的集合,我們可以將基表中重要的欄位資訊,可以不通過檢視給使用者,檢視是動態的資料的集合,資料是隨著基表的更新而更新。同時,使用者對檢視,不可以隨意的更改和刪除,可以保證資料的安全性。
第四點:可以合併分離的資料,建立分割槽檢視
隨著社會的發展,公司的業務量的不斷的擴大,一個大公司,下屬都設有很多的分公司,為了管理方便,我們需要統一表的結構,定期檢視各公司業務情況,而分別看各個公司的資料很不方便,沒有很好的可比性,如果將這些資料合併為一個表格裡,就方便多啦,這時我們就可以使用union關鍵字,將各分公司的資料合併為一個檢視。
2.檢視的缺點:
1)效能差
資料庫必須把檢視查詢轉化成對基本表的查詢,如果這個檢視是由一個複雜的多表查詢所定義,那麼,即使是檢視的一個簡單查詢,資料庫也要把它變成一個複雜的結合體,需要花費一定的時間。
2)修改限制
當使用者試圖修改試圖的某些資訊時,資料庫必須把它轉化為對基本表的某些資訊的修改,對於簡單的試圖來說,這是很方便的,但是,對於比較複雜的試圖,可能是不可修改的。
10、使用者登入登出之後要做什麼事
通常清除使用者會話狀態, 視業務需求而定是否在客戶寫入端cookie資訊在資料儲存登出時間等業務.
11、Linux 命令
ls 顯示檔案或目錄
mkdir 建立目錄
cd 切換目錄
touch 建立空檔案
echo 建立帶有內容的檔案。
cat 檢視檔案內容
cp 拷貝
mv 移動或重新命名
rm 刪除檔案
find 在檔案系統中搜尋某檔案
wc 統計文字中行數、字數、字元數
grep 在文字檔案中查詢某個字串
rmdir 刪除空目錄
tree 樹形結構顯示目錄,需要安裝tree包
pwd 顯示當前目錄
ln 建立連結檔案
more、less 分頁顯示文字檔案內容
head、tail 顯示檔案頭、尾內容
stat 顯示指定檔案的詳細資訊,比ls更詳細
who 顯示線上登陸使用者
whoami 顯示當前操作使用者
hostname 顯示主機名
uname 顯示系統資訊
top 動態顯示當前耗費資源最多程式資訊
ps 顯示瞬間程式狀態 ps -aux
du 檢視目錄大小 du -h /home帶有單位顯示目錄資訊
df 檢視磁碟大小 df -h 帶有單位顯示磁碟資訊
ifconfig 檢視網路情況
ping 測試網路連通
netstat 顯示網路狀態資訊
man 命令不會用了,找男人如:man ls
clear 清屏
alias 對命令重新命名如:alias showmeit=“ps -aux”
kill 殺死程式,可以先用ps 或 top命令檢視程式的id
tar: 打包壓縮
shutdown 關機重啟
halt 關機
reboot 重啟
sudo dpkg -i tree_1.5.3-1_i386.deb 安裝軟體
sudo dpkg -r tree 解除安裝軟體
sudo apt-get install tree 安裝tree
sudo apt-get remove tree 解除安裝tree
sudo apt-get update 更新軟體
sudo apt-get upgrade
vim三種模式:命令模式、插入模式、編輯模式。使用ESC或i或:來切換模式。
命令模式下:
:q 退出
:q! 強制退出
:wq 儲存並退出
:set number 顯示行號
:set nonumber 隱藏行號
yyp 複製游標所在行,並貼上
passwd root 給root設定密碼
/etc/profile 系統環境變數
bash_profile 使用者環境變數
.bashrc 使用者環境變數
su user 切換使用者,載入配置檔案.bashrc
su - user 切換使用者,載入配置檔案/etc/profile ,載入bash_profile
sudo chown [-R] owner[:group] {File|Directory}更改檔案的使用者及使用者組
sudo chmod 777 filename 更改許可權
三、公司面試題
1、說說你專案中為什麼使用Springboot,dubbo,redis,activeMQ?
1.Spring Boot作為微服務的入門級微框架,有四點好處
- Spring Boot使編碼變簡單
- Spring Boot使配置變簡單
- Spring Boot使部署變簡單
- Spring Boot使監控變簡單
Dubbo是一種服務框架,使得應用可通過高效能的 RPC 實現服務的輸出和輸入功能,可以和Spring框架無縫整合。
在專案中使用redis,主要是從兩個角度去考慮:效能和併發。當然,redis還具備可以做分散式鎖,訊息佇列等其他功能,但還有其他中介軟體(如zookpeer,activeMQ等)代替,並不是非要使用redis。因此,主要從效能和併發兩個角度出發去考慮的。
(一)效能
在碰到需要執行耗時特別久,且結果不頻繁變動的SQL,就特別適合將執行結果放入快取。這樣,後面的通過請求就去快取中讀取放入到activeMQ,使得請求能夠迅速響應。
(二)併發
在大併發的情況下,所有的請求直接訪問資料庫,資料庫會出現連線異常。這個時候,就需要使用redis做一個緩衝操作,讓請求先訪問到redis,而不是直接訪問資料庫。
ActiveMQ的特性主要管理訊息的事務,以及訊息持久化,即使在出錯時也不會漏掉一條訊息。訊息伺服器需要進行資訊持久化,一個伺服器叢集可以提高其可用性,ActiveMQ正式這樣的一個高可用性的訊息伺服器,典型的情況就是當一個Server Node掉線的時候,它上面的所有訊息都會被儲存下來,以便在它重新上線時繼續處理。ActiveMQ的的另一個特性是高效能的資料分發,主要關注的是訊息的吞吐率以及高效的訊息投遞路由,中心思想就是在一個大的網路中儘可能快的傳遞大量的並且快速改變的訊息資料。鑑於大量的資料和頻繁的資料資料交換負荷很高,所以這種情況下很少使用資料持久化,在失敗時丟失幾條資料也是可以接受的因為老的資料通常都不再被需要了,最新的資料才是真正我們關心的.
2、Redis 持久化的原理
由於Redis的資料都存放在記憶體中,如果沒有配置持久化,redis重啟後資料就全丟失了,於是需要開啟redis的持久化功能,將資料儲存到磁碟上,當redis重啟後,可以從磁碟中恢復資料。redis提供兩種方式進行持久化,一種是RDB持久化(原理是將Reids在記憶體中的資料庫記錄定時dump到磁碟上的RDB持久化),另外一種是AOF(append only file)持久化(原理是將Reids的操作日誌以追加的方式寫入檔案)。RDB持久化是指在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,實際操作過程是fork一個子程式,先將資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進位制壓縮儲存。AOF持久化以日誌的形式記錄伺服器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文字的方式記錄,可以開啟檔案看到詳細的操作記錄。相比於AOF機制,如果資料集很大,RDB的啟動效率會更高。
3、IOC的原理
Spring Bean的建立是典型的工廠模式,這一系列的Bean工廠,也即IOC容器為開發者管理物件間的依賴關係提供了很多便利和基礎服務,在Spring中有許多的IOC容器的實現供使用者選擇和使用,其中BeanFactory作為最頂層的一個介面類,它定義了IOC容器的基本功能規範,在容器初始化時建立程式所需的物件,實現控制反轉,就是把原先我們程式碼裡面需要實現的物件建立、依賴的程式碼,反轉給容器來幫忙實現。那麼必然的我們需要建立一個容器,同時需要一種描述來讓容器知道需要建立的物件與物件的關係,這就IoC 容器:最主要是完成了完成物件的建立和依賴的管理注入等這個描述最具體表現就是我們可配置的檔案。
4、如何反射生成一個物件?
反射是java特有的一種機制,可以在程式執行的過程中,動態的獲取類的屬性和方法,可以通過類的全限定名,物件本身,類本身獲取位元組碼物件。通過位元組碼物件獲取構造器,欄位,方法等物件。
- 會用什麼開發軟體?
IDE :IDEA,Eclipse,MyEclipse,NetBean,DreamWare
Server:Tomcat,WebLogic,Jetty,
OS:Linux,Ubuntu,Centos,Windows
DB:mysql ,Oracle,SQL Server
5、spring註解開發瞭解一下
springboot是純以註解開發的,基礎的springmvc註解有
@Configuration把一個類作為一個IoC容器,它的某個方法頭上如果 註冊了@Bean,就會作為這個Spring容器中的Bean。
@Scope註解作用域
@Lazy(true) 表示延遲初始化
@Service用於標註業務層元件、
@Controller用於標註控制層元件(如struts中的action)
@RestController 相當於Controller+@ResponseBody
@Repository用於標註資料訪問元件,即DAO元件。
@Component泛指元件,當元件不好歸類的時候,我們可以使用這個註解進行標註。
@Scope用於指定scope作用域的(用在類上)
@PostConstruct用於指定初始化方法(用在方法上)
@PreDestory用於指定銷燬方法(用在方法上)
@DependsOn:定義Bean初始化及銷燬時的順序
@Primary:自動裝配時當出現多個Bean候選者時,被註解為@Primary的Bean將作為首選者,否則將丟擲異常
@Autowired 預設按型別裝配,如果我們想使用按名稱裝配,可以結合@Qualifier註解一起使用。如下:
@Autowired @Qualifier(“personDaoBean”) 存在多個例項配合使用
@Resource預設按名稱裝配,當找不到與名稱匹配的bean才會按型別裝配。
@PostConstruct 初始化註解
@PreDestroy 摧毀註解預設單例啟動就載入
@Async非同步方法呼叫
6、前端獲取資料有幾種方式
1通過URL傳送請求,可以POST或GET形式,獲得伺服器響應
2 伺服器響應的方式可以是xml格式,JSON 格式,如果使用的模板引擎還可以是JAVA物件。前端通過JS處理資料
3 也可以通過cookies的形式儲存在客戶端由前端通過JS解析
7、Jquery
jQuery 是一個 JavaScript 庫,極大地簡化了 JavaScript 程式設計。jQuery 很容易學習,以物件導向的形式進行操作,做為後端開發常用的方法有html(),append(),val(),click(),ready(),ajax(),get(),getJson()等等。
8、盒子模型
盒子模型,英文即box model。無論是div、span、還是a都是盒子。但是,圖片、表單元素一律看作是文字,它們並不是盒子。這個很好理解,比如說,一張圖片裡並不能放東西,它自己就是自己的內容。盒子中的區域主要的屬性就5個:width、height、padding、border、margin:
width和height:內容的寬度、高度(不是盒子的寬度、高度)。
padding:內邊距。
border:邊框。
margin:外邊距。
9、鎖的用法還有注意事項
一旦用到鎖,就說明這是阻塞式的,所以在併發度上一般來說都會比無鎖的情況低一點。因此需要注意鎖的優化。鎖優化,是指在阻塞式的情況下,如何讓效能不要變得太差。但是再怎麼優化,一般來說效能都會比無鎖的情況差一點。
鎖優化的思路和方法總結一下,有以下幾種。
1.減少鎖持有時間
只用在有執行緒安全要求的程式上加鎖,減少其他執行緒等待的時間
2.減小鎖粒度
將大物件(這個物件可能會被很多執行緒訪問),拆成小物件,大大增加並行度,降低鎖競爭。降低了鎖的競爭,偏向鎖,輕量級鎖成功率才會提高。
3.鎖分離
最常見的鎖分離就是讀寫鎖ReadWriteLock,根據功能進行分離成讀鎖和寫鎖,這樣讀讀不互斥,讀寫互斥,寫寫互斥,即保證了執行緒安全,又提高了效能
4.鎖粗化
通常情況下,為了保證多執行緒間的有效併發,會要求每個執行緒持有鎖的時間儘量短,即在使用完公共資源後,應該立即釋放鎖。只有這樣,等待在這個鎖上的其他執行緒才能儘早的獲得資源執行任務。但是,凡事都有一個度,如果對同一個鎖不停的進行請求、同步和釋放,其本身也會消耗系統寶貴的資源,反而不利於效能的優化
5.鎖消除
鎖消除是在編譯器級別的事情。在即時編譯器時,如果發現不可能被共享的物件,則可以消除這些物件的鎖操作。
四、有贊面試題
1、redis常用命令:
1)連線操作命令
quit:關閉連線(connection)
auth:簡單密碼認證
help cmd:檢視cmd幫助,例如:help quit
2)持久化
save:將資料同步儲存到磁碟
bgsave:將資料非同步儲存到磁碟
lastsave:返回上次成功將資料儲存到磁碟的Unix時戳
shundown:將資料同步儲存到磁碟,然後關閉服務
3)遠端服務控制
info:提供伺服器的資訊和統計
monitor:實時轉儲收到的請求
slaveof:改變複製策略設定
config:在執行時配置Redis伺服器
4)對value操作的命令
exists(key):確認一個key是否存在
del(key):刪除一個key
type(key):返回值的型別
keys(pattern):返回滿足給定pattern的所有key
randomkey:隨機返回key空間的一個
keyrename(oldname, newname):重新命名key
dbsize:返回當前資料庫中key的數目
expire:設定一個key的活動時間(s)
ttl:獲得一個key的活動時間
select(index):按索引查詢
move(key, dbindex):移動當前資料庫中的key到dbindex資料庫
flushdb:刪除當前選擇資料庫中的所有key
flushall:刪除所有資料庫中的所有key
5)String
set(key, value):給資料庫中名稱為key的string賦予值value
get(key):返回資料庫中名稱為key的string的value
getset(key, value):給名稱為key的string賦予上一次的value
mget(key1, key2,…, key N):返回庫中多個string的value
setnx(key, value):新增string,名稱為key,值為value
setex(key, time, value):向庫中新增string,設定過期時間time
mset(key N, value N):批量設定多個string的值
msetnx(key N, value N):如果所有名稱為key i的string都不存在
incr(key):名稱為key的string增1操作
incrby(key, integer):名稱為key的string增加integer
decr(key):名稱為key的string減1操作
decrby(key, integer):名稱為key的string減少integer
append(key, value):名稱為key的string的值附加value
substr(key, start, end):返回名稱為key的string的value的子串
6)List
rpush(key, value):在名稱為key的list尾新增一個值為value的元素
lpush(key, value):在名稱為key的list頭新增一個值為value的元素
llen(key):返回名稱為key的list的長度
lrange(key, start, end):返回名稱為key的list中start至end之間的元素
ltrim(key, start, end):擷取名稱為key的list
lindex(key, index):返回名稱為key的list中index位置的元素
lset(key, index, value):給名稱為key的list中index位置的元素賦值
lrem(key, count, value):刪除count個key的list中值為value的元素
lpop(key):返回並刪除名稱為key的list中的首元素
rpop(key):返回並刪除名稱為key的list中的尾元素
blpop(key1, key2,… key N, timeout):lpop命令的block版本。
brpop(key1, key2,… key N, timeout):rpop的block版本。
rpoplpush(srckey, dstkey):返回並刪除名稱為srckey的list的尾元素,並將該元素新增到名稱為dstkey的list的頭部
7)Set
sadd(key, member):向名稱為key的set中新增元素member
srem(key, member) :刪除名稱為key的set中的元素member
spop(key) :隨機返回並刪除名稱為key的set中一個元素
smove(srckey, dstkey, member) :移到集合元素
scard(key) :返回名稱為key的set的基數
sismember(key, member) :member是否是名稱為key的set的元素
sinter(key1, key2,…key N) :求交集
sinterstore(dstkey, (keys)) :求交集並將交集儲存到dstkey的集合
sunion(key1, (keys)) :求並集
sunionstore(dstkey, (keys)) :求並集並將並集儲存到dstkey的集合
sdiff(key1, (keys)) :求差集
sdiffstore(dstkey, (keys)) :求差集並將差集儲存到dstkey的集合
smembers(key) :返回名稱為key的set的所有元素
srandmember(key) :隨機返回名稱為key的set的一個元素
8)Hash
hset(key, field, value):向名稱為key的hash中新增元素field
hget(key, field):返回名稱為key的hash中field對應的value
hmget(key, (fields)):返回名稱為key的hash中field i對應的value
hmset(key, (fields)):向名稱為key的hash中新增元素field
hincrby(key, field, integer):將名稱為key的hash中field的value增加integer
hexists(key, field):名稱為key的hash中是否存在鍵為field的域
hdel(key, field):刪除名稱為key的hash中鍵為field的域
hlen(key):返回名稱為key的hash中元素個數
hkeys(key):返回名稱為key的hash中所有鍵
hvals(key):返回名稱為key的hash中所有鍵對應的value
hgetall(key):返回名稱為key的hash中所有的鍵(field)及其對應的value
2、你瞭解hashMap嗎? 底層實現方式?執行緒安全嗎?如何實現安全?CocurrentHashMap瞭解嗎?
瞭解一點,HashMap的主幹是一個Entry陣列。Entry是HashMap的基本組成單元,每一個Entry包含一個key-value鍵值對。 HashMap中有一個靜態內部類Entry。所以,HashMap的整體結構簡單來說,HashMap由陣列+連結串列組成的,陣列是HashMap的主體,連結串列則是主要為了解決雜湊衝突而存在的,如果定位到的陣列位置不含連結串列(當前entry的next指向null),那麼對於查詢,新增等操作很快,僅需一次定址即可;如果定位到的陣列包含連結串列,對於新增操作,其時間複雜度為O(n),首先遍歷連結串列,存在即覆蓋,否則新增;對於查詢操作來講,仍需遍歷連結串列,然後通過key物件的equals方法逐一比對查詢。所以,效能考慮,HashMap中的連結串列出現越少,效能才會越好。HashMap有4個構造器,其他構造器如果使用者沒有傳入initialCapacity 和loadFactor這兩個引數,會使用預設值。initialCapacity預設為16,loadFactory預設為0.75。是執行緒不安全的。如果需要安全就選擇HashTable或者CocurrentHashMap,這兩個都是安全的。
3、如何建立多執行緒?執行緒池的作用?
在JDK1.5之前,建立執行緒就只有兩種方式,即繼承java.lang.Thread類和實現java.lang.Runnable介面;而在JDK1.5以後,增加了兩個建立執行緒的方式,即實現java.util.concurrent.Callable介面和執行緒池。
1繼承Thread類
2實現Runnable介面
3實現Callable介面
相較於實現Runnable 介面的實現,方法可以有返回值,並且丟擲異常。
4、執行緒池
執行緒池提供了一個執行緒佇列,佇列中儲存著所有等待狀態的執行緒。避免了建立與銷燬額外開銷,提高了響應速度。
java.util.concurrent.Executors提供了一個 java.util.concurrent.Executor介面的實現用於建立執行緒池,多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。假設一個伺服器完成一項任務所需時間為:T1 建立執行緒時間,T2 線上程中執行任務的時間,T3 銷燬執行緒時間。如果:T1 + T3 遠大於 T2,則可以採用執行緒池,以提高伺服器效能。
一個執行緒池包括以下四個基本組成部分:
1、 執行緒池管理器(ThreadPool):用於建立並管理執行緒池,包括建立執行緒池,銷燬執行緒池,新增新任務;
2、 工作執行緒(PoolWorker):執行緒池中執行緒,在沒有任務時處於等待狀態,可以迴圈的執行任務;
3、 任務介面(Task):每個任務必須實現的介面,以供工作執行緒排程任務的執行,它主要規定了任務的入口,任務執行完後的收尾工作,任務的執行狀態等;
4、任務佇列(taskQueue):用於存放沒有處理的任務。提供一種緩衝機制。
執行緒池技術正是關注如何縮短或調整T1,T3時間的技術,從而提高伺服器程式效能的。它把T1,T3分別安排在伺服器程式的啟動和結束的時間段或者一些空閒的時間段,這樣在伺服器程式處理客戶請求時,不會有T1,T3的開銷了。執行緒池不僅調整T1,T3產生的時間段,而且它還顯著減少了建立執行緒的數目。
5、 Object類的常用方法
Object類是一個特殊的類,是所有類的父類,如果一個類沒有用extends明確指出繼承於某個類,那麼它預設繼承Object類。Object類中的常用方法:
1.取得物件資訊的方法:toString()
2.物件相等判斷方法:equals()
3.物件簽名:hashCode()
4.獲得位元組碼物件方法:getClass();
5.等待方法:wait()
6.喚醒方法:notify()
7.喚醒所有其它方法:notifyAll()
五、海康威視面試題
1、Arraylist 呼叫方法注意事項
ArrayList實現了可變大小的陣列。它允許所有元素,包括null。ArrayList沒有同步。size(),isEmpty(),get(),set()方法執行時間為常數。但是add()方法開銷為分攤的常數,新增n個元素需要O(n)的時間。其他的方法執行時間為線性。每個ArrayList例項都有一個容量(Capactity),即用於儲存元素的陣列的大小。這個容量可隨著不斷新增新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入之前可以呼叫ensureCapacity()方法來增加ArrayList容量已提高插入效率,
2、支付過程中斷網怎麼辦
從單服務應用程式斷網角度分析
1在使用者還沒輸入密碼之前:網路原因支付失敗
2使用者輸入密碼過程中:網路原因支付失敗
3密碼已經輸入,第三方支付伺服器已經接收到正確密碼並且確認支付成功。這時,第三方支付伺服器確認支付成功,通知應用程式,但應用程式斷網,此時需要在連線後主動或手動讀取第三方支付伺服器的資訊進行後續處理。
在分散式叢集中的部署可以在其中某臺主機斷網時匹配叢集中其它應用進行處理。但很多時候,一個請求,會呼叫很多service服務,如果service之間是序列的話,那麼一個service超時,很可能會引起連鎖反應,所以在呼叫別的介面的時候(不管是第三方支付介面,還是分散式介面),都需要加一個超時時間,超過這個時間,就不在等待了,視作失敗,或者處理中,然後再後續處理。
3、一個專案如何支援兩個資料庫通用,修改哪些部分的程式碼
mybatis框架3.1以上版本支援多資料庫相容操作,只要修改spring的資料來源配置程式碼或者或者mybatis的databaseIdProvider 節點和mapper對映檔案程式碼,專案中以一種資料庫為主, 如MySQL為主, Oracle則是某些模組使用, 即寫mapper的xml時, 一般都直接不寫databaseId, 唯有Oracle那個模組才寫上 databaseId=”oracle” . 而另一種情況則是, 整個專案都需要相容, 那修改量就相對大一些, 需要2個statement分別標明不同的databaseId.
4、Hibernate 和mybstis 差異性
myBatis載入的欄位很乾淨,沒有太多多餘的欄位,直接對映入關聯中。而hibernate則將整個表的字都會載入到物件中,其中還包括關聯的user欄位。hibernate這種情況下有好有壞,要看具體的場景,對於管理平臺,需要展現的資訊較多,併發要求不高時,hibernate比較有優勢。然而在一些小活動,網際網路網站,高併發情況下,hibernate的方案太不太適合,myBatis+VO則是首選。總體初觀,myBatis在所有情況下,特別是插入與單表查詢,都會微微優於hibernate。不過差異情況並不明顯,可以基本忽略差異。差異比較大的是關聯查詢時,hibernate為了保證POJO的資料完整性,需要將關聯的資料載入,需要額外地查詢更多的資料。這裡hibernate並沒有提供相應的靈活性。關聯時一個差異比較大的地方則是懶載入特性。其中hibernate可以特別地利用POJO完整性來進行快取,可以在一級與二級快取上儲存物件,如果對單一個物件查詢比較多的話,會有很明顯的效能效益。以後關於單物件關聯時,可以通過懶載入加二級快取的方式來提升效能。最後,資料查詢的效能與orm框架關無太大的關係,因為orm主要幫助開發人員將關係資料轉化成物件型資料模型,對程式碼的深析上來看,hibernate設計得比較重量級,對開發來說可以算是重新開發了一個資料庫,不讓開發去過多關心資料庫的特性,直接在hibernate基礎上進行開發,執行上分為了sql生成,資料封裝等過程,這裡花了大量的時間。然而myBatis則比直接,主要是做關聯與輸出欄位之間的一個對映。其中sql基本是已經寫好,直接做替換則可,不需要像hibernate那樣去動態生成整條sql語句。myBatis相對Hibernate 等封裝較為嚴密的ORM 實現而言,因為hibernate對資料物件的操作實現了較為嚴密的封裝,可以保證其作用範圍內的快取同步,而ibatis 提供的是半封閉的封裝實現,因此對快取的操作難以做到完全的自動化同步。以上的快取配置測試僅為效能上的分析,沒有加入可用性上的情況,因為myBatis直接配置快取的話,可能會出現髒資料,。在關聯查詢資料的情況下,hiberntae的懶載入配二級快取是個比較好的方案(無髒資料),也是與myBatis相比有比較明顯的優勢。此情景下,效能與myBatis持平。在真實情況下,myBatis可能不會在這個地方上配置快取,會出現髒資料的情況,因而很有可能在此hibernate效能會更好。
5、Spring內部實現機制
Spring 從建立到銷燬bean,
1.ResourceLoader 載入配置檔案
2.BeanDefinitionReader 解析配置檔案,並將其註冊到BeanDefinitonRegistry中,此時的beanDefinition是半成品,因為此時還無法對佔位符進行解析
3.BeanFactoryPostProcessor從beanDefinitionRegistry中進行進一步加工(解析佔位符),並且將實現了PropertyEditor介面的bean註冊到PropertyEditorRegistry中
4.通過InstantiationStrategy 和BeanWrapper 完成bean的例項化,並進行屬性的注入
5.通過BeanPostProcessor對bean進行進一步加工一個完整的bean就誕生
6、Ioc和aop底層如何實現
1.IoC(Inversion of Control)
(1). IoC(Inversion of Control)是指容器控制程式物件之間的關係,而不是傳統實現中,由程式程式碼直接操控。控制權由應用程式碼中轉到了外部容器,控制權的轉移是所謂反轉。對於Spring而言,就是由Spring來控制物件的生命週期和物件之間的關係;IoC還有另外一個名字——“依賴注入(Dependency Injection)”。從名字上理解,所謂依賴注入,即元件之間的依賴關係由容器在執行期決定,即由容器動態地將某種依賴關係注入到元件之中。
(2). 在Spring的工作方式中,所有的類都會在spring容器中登記,告訴spring這是個什麼東西,你需要什麼東西,然後spring會在系統執行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的建立、銷燬都由 spring來控制,也就是說控制物件生存週期的不再是引用它的物件,而是spring。對於某個具體的物件而言,以前是它控制其他物件,現在是所有物件都被spring控制,所以這叫控制反轉。
(3). 在系統執行中,動態的向某個物件提供它所需要的其他物件。
(4). 依賴注入的思想是通過反射機制實現的,在例項化一個類時,它通過反射呼叫類中set方法將事先儲存在HashMap中的類屬性注入到類中。總而言之,在傳統的物件建立方式中,通常由呼叫者來建立被呼叫者的例項,而在Spring中建立被呼叫者的工作由Spring來完成,然後注入呼叫者,即所謂的依賴注入or控制反轉。注入方式有兩種:依賴注入和設定注入; IoC的優點:降低了元件之間的耦合,降低了業務物件之間替換的複雜性,使之能夠靈活的管理物件。
2.AOP(Aspect Oriented Programming)
(1). AOP面向方面程式設計基於IoC,是對OOP的有益補充;
(2). AOP利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,比如日誌記錄,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。
(3). AOP代表的是一個橫向的關係,將“物件”比作一個空心的圓柱體,其中封裝的是物件的屬性和行為;則面向方面程式設計的方法,就是將這個圓柱體以切面形式剖開,選擇性的提供業務邏輯。而剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡,但完成了效果。
(4). 實現AOP的技術,主要分為兩大類:一是採用動態代理技術,利用擷取訊息的方式,對該訊息進行裝飾,以取代原有物件行為的執行;二是採用靜態織入的方式,引入特定的語法建立“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的程式碼。
(5). Spring實現AOP:JDK動態代理和CGLIB代理 JDK動態代理:其代理物件必須是某個介面的實現,它是通過在執行期間建立一個介面的實現類來完成對目標物件的代理;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現原理類似於JDK動態代理,只是它在執行期間生成的代理物件是針對目標類擴充套件的子類。CGLIB是高效的程式碼生成包,底層是依靠ASM(開源的java位元組碼編輯類庫)操作位元組碼實現的,效能比JDK強;需要引入包asm.jar和cglib.jar。使用AspectJ注入式切面和@AspectJ註解驅動的切面實際上底層也是通過動態代理實現的。
7、註解開發程式碼怎麼寫的,問註解裡面是怎麼實現的?
註解的定義通過@interface符號,註解中有屬性,可以設定預設值,value是特殊屬性,可以在單個賦值省略。註解是用來取代配置檔案的的,通過反射獲取註解屬性後進行操作。
8、JQuery 和ext的區別
JQuery是現在世界上使用最多的javascript庫。是對JS的封裝,很多前端框架是基於jQuery實現的比如,EasyUI,LayUI等,是免費的。而Ext是一套富客戶端(rich client)框架,源自Yahoo UI社群。EXT完全基於JavaScript、css和HTML實現,與主流瀏覽器完全相容,並且無需安裝任何外掛即可在常用瀏覽器中建立出絢麗的頁面效果。商業收費版本功能更為強大。是重量級的前端框架。說的更通俗一點就是:Jquery是一款輕量級的js庫,適用於前臺web動態頁面的設計,而ExtJS則是一款重量級的富客戶端js庫,更適用於類似後臺管理頁面的那種動態頁面效果的設計。
9、Ext 能實現哪些jQuery 實現不了的
Jquery適合小型靈活的web應用,比如新聞釋出系統動態頁面設計,入口網站動態頁面設計,SNS動態頁面等web系統設計;特點是使用簡單明瞭,可以簡單快捷的實現某個效果,比如為了實現某一個動態特效,我們可以迅速定位到使用jquery的某一技術或者找到相應的外掛來實現。Jquery的設計理念就是寫最少的程式碼實現更多的功能。缺點是外掛缺乏統一的管理,使用者往往為了實現某一個特效而苦苦糾結與css,還有js的效果邏輯。
而Ext則提供了豐富的完整的一套UI元件,以及元件對應的CSS包(這裡強調一下,是一套),就必須深入理解ext的中心思想,理解元件之間巢狀後的關係,以及理解ext生成DOM物件的順序。特點是功能提供全,使得開發者解放於介面設計,更多的工作去實現業務邏輯方面的事情,缺點是要想靈活運用有一定的難度,尤其是當遇到Ext的Bug的時候。ExtJS適用於那些富客戶端應用:比如OA系統,ERP系統,MIS系統等富客戶端應用的動態頁面設計。
10、Ioc通過一個註解實現依賴注入,裡面程式碼是怎麼實現的?
五步:1通過讀取配置檔案bean節點資訊獲取class
2 反射建立物件資訊
3 獲取位元組碼中的私有欄位或者公有屬性
4判斷是否有指定註解型別
5 有指定就反射賦值
11、前端向後端可以發請求,後端怎麼向前端拋訊息?
看起來響應的方式有很多,但本質上只有流的形式傳輸,比如檔案下載,XML資料響應,JSON資料,由前端JS解析資料,如果是java中還可以傳輸物件資料給模板引擎,由模板引擎解析資料。
六、崑山媽媽好面試題
1、執行緒的啟動停止,如何同步
執行緒的啟動是通過start()方法,區別與run(),停止執行緒的方式有四種:
1 使用stop方法強行終止,但是不推薦這個方法,因為stop()和suspend()及resume()一樣都是過期作廢的方法。
2 使用interrupt方法中斷執行緒。
3 使用退出標誌,使執行緒正常退出,也就是當run方法完成後執行緒終止
4 wait(),sleep()暫時停止執行緒
2、保證執行緒同步的方式可以通過以下7種方式:
1.同步方法
即有synchronized關鍵字修飾的方法。
由於java的每個物件都有一個內建鎖,當用此關鍵字修飾方法時,
內建鎖會保護整個方法。在呼叫該方法前,需要獲得內建鎖,否則就處於阻塞狀態。注: synchronized關鍵字也可以修飾靜態方法,此時如果呼叫該靜態方法,將會鎖住整個類
2.同步程式碼塊
即有synchronized關鍵字修飾的語句塊。
被該關鍵字修飾的語句塊會自動被加上內建鎖,從而實現同步
注:同步是一種高開銷的操作,因此應該儘量減少同步的內容。
通常沒必要同步整個方法,使用synchronized程式碼塊同步關鍵程式碼即可。
3.使用特殊域變數(volatile)實現執行緒同步
a.volatile關鍵字為域變數的訪問提供了一種免鎖機制,
b.使用volatile修飾域相當於告訴虛擬機器該域可能會被其他執行緒更新,
c.因此每次使用該域就要重新計算,而不是使用暫存器中的值
d.volatile不會提供任何原子操作,它不能用來修飾final型別的變數
4.使用重入鎖實現執行緒同步
在JavaSE5.0中新增了一個java.util.concurrent包來支援同步。ReentrantLock類是可重入、互斥、實現了Lock介面的鎖,
它與使用synchronized方法和快具有相同的基本行為和語義,並且擴充套件了其能力
5.使用區域性變數實現執行緒同步
如果使用ThreadLocal管理變數,則每一個使用該變數的執行緒都獲得該變數的副本,副本之間相互獨立,這樣每一個執行緒都可以隨意修改自己的變數副本,而不會對其他執行緒產生影響。
6.使用阻塞佇列實現執行緒同步
前面5種同步方式都是在底層實現的執行緒同步,但是我們在實際開發當中,應當儘量遠離底層結構。使用javaSE5.0版本中新增的java.util.concurrent包的LinkedBlockingQueue來實現執行緒的同步將有助於簡化開發。
7.使用原子變數實現執行緒同步
需要使用執行緒同步的根本原因在於對普通變數的操作不是原子的。
- 同步用final修飾的區別
final修飾過後的同步方法子類不能重寫
3、springmvc的請求流程
第一步:發起請求到前端控制器(DispatcherServlet)
第二步:前端控制器請求HandlerMapping查詢 Handler (可以根據xml配置、註解進行查詢)
第三步:處理器對映器HandlerMapping向前端控制器返回Handler,HandlerMapping會把請求對映為HandlerExecutionChain物件(包含一個Handler處理器(頁面控制器)物件,多個HandlerInterceptor攔截器物件),通過這種策略模式,很容易新增新的對映策略
第四步:前端控制器呼叫處理器介面卡去執行Handler
第五步:處理器介面卡HandlerAdapter將會根據適配的結果去執行Handler
第六步:Handler執行完成給介面卡返回ModelAndView
第七步:處理器介面卡向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一個底層物件,包括 Model和view)
第八步:前端控制器請求檢視解析器去進行檢視解析(根據邏輯檢視名解析成真正的檢視(jsp)),通過這種策略很容易更換其他檢視技術,只需要更改檢視解析器即可
第九步:檢視解析器向前端控制器返回View
第十步:前端控制器進行檢視渲染(檢視渲染將模型資料(在ModelAndView物件中)填充到request域)
第十一步:前端控制器向使用者響應結果
4、前端是否使用靜態頁面
是的,因為使用靜態頁面會提高響應的速度,為實現前後端的分離提供可能性。
5、前端框架
VUE,React,Bootstrap,Jquery,JqueryEasyUI,Ext等
6、springboot介紹
springboot是純以註解開發的,配置檔案預設application.properties/yml,
Spring Boot作為微服務的入門級微框架,有四點好處
- Spring Boot使編碼變簡單
- Spring Boot使配置變簡單
- Spring Boot使部署變簡單
- Spring Boot使監控變簡單
7、web.xml的作用
web.xml檔案是用來初始化配置資訊:比如Welcome頁面、servlet、servlet-mapping、filter、listener、啟動載入級別等。當web工程沒用到這些時,可以不用web.xml檔案來配置的Application。也可以使用註解取代。每個xml檔案都有定義它書寫規則的Schema檔案,也就是說javaEE的定義web.xml所對應的xml Schema檔案中定義了多少種標籤元素,web.xml中就可以出現它所定義的標籤元素,也就具備哪些特定的功能。web.xml的模式檔案是由Sun 公司定義的,每個web.xml檔案的根元素為中,必須標明這個web.xml使用的是哪個模式檔案。
web.xml的模式檔案中定義的標籤並不是定死的,模式檔案也是可以改變的,一般來說,隨著web.mxl模式檔案的版本升級,裡面定義的功能會越來越複雜,標籤元素的種類肯定也會越來越多。
8、執行緒在非同步方法的停止方法
停止執行緒的方式有四種:
1 使用stop方法強行終止,但是不推薦這個方法,因為stop()和suspend()及resume()一樣都是過期作廢的方法。
2 使用interrupt方法中斷執行緒。
3 使用thread.interrupt退出標誌,使執行緒正常退出,也就是當run方法完成後執行緒終止
4 wait(),sleep()暫時停止執行緒
8、過濾器的作用
過濾器就是可以對瀏覽器向控制器資源發出請求和伺服器回應給瀏覽器的內容進行過濾。這個過濾過程中可以攔截瀏覽器發出的請求和伺服器回應給瀏覽器的內容。攔截之後,就可以進行檢視,並且可以對攔截內容進行提取,或者進行修改。過濾器攔截請求和響應,以便檢視,提取或操作客戶機和伺服器之間交換資料。
9、cloud
雲是什麼?通常雲端計算。雲端計算是分散式處、並行處理和網格計算的發展。雲是雲技術的意思,是分散式計算技術的一種,雲技術(Cloud technology)是基於雲端計算商業模式應用的網路技術、資訊科技、整合技術、管理平臺技術、應用技術等的總稱,可以組成資源池,按需所用,靈活便利。
雲技術最基本的概念,是透過網路將龐大的計算處理程式自動分拆成無數個較小的子程式,再交由多部伺服器所組成的龐大系統經搜尋、計算分析之後將處理結果回傳給使用者。透過這項技術,網路服務提供者可以在數秒之內,達成處理數以千萬計甚至億計的資訊,達到和“超級計算機”同樣強大效能的網路服務。
雲端計算技術體系結構分為4層:物理資源層、資源池層、管理中介軟體層和SOA構建層,如圖所示。物理資源層包括計算機、儲存器、網路設施、資料庫和軟體等。
10、資料庫讀寫分離的實現
隨著使用者量的增多,資料庫操作往往會成為一個系統的瓶頸所在,而且一般的系統“讀”的壓力遠遠大於“寫”,因此我們可以通過實現資料庫的讀寫分離來提高系統的效能。實現思路
通過設定主從資料庫實現讀寫分離,主資料庫負責“寫操作”,從資料庫負責“讀操作”,根據壓力情況,從資料庫可以部署多個提高“讀”的速度,藉此來提高系統總體的效能。
要實現讀寫分離,就要解決主從資料庫資料同步的問題,在主資料庫寫入資料後要保證從資料庫的資料也要更新。
11、主從資料庫同步的實現思路:
主伺服器master記錄資料庫操作日誌到Binary log,從伺服器開啟i/o執行緒將二進位制日誌記錄的操作同步到relay log(存在從伺服器的快取中),另外sql執行緒將relay log日誌記錄的操作在從伺服器執行。
主從資料庫設定的具體步驟
首先要有兩個資料庫伺服器配置主從關係master、slave(也可以用一個伺服器安裝兩套資料庫環境執行在不同埠,slave也可以舉一反三設定多個) ,接下來的問題就是在業務程式碼裡面實現讀寫分離,在配置檔案配置兩個具體的資料來源master、slave,繼承了abstractDataSource,這裡面就配置了資料庫連線的具體屬性,然後配置了動態資料來源,他將決定使用哪個具體的資料來源,這裡面的關鍵就是DataSourceSelector,接下來實現這個bean。下一步設定了資料來源的懶載入,保證在資料來源載入的時候其他依賴的bean已經載入完成。
七、支付寶螞蟻金服
1、String Stringbuffer Stringbuilder
String類被final修飾,所以不可繼承,String的值是不可變的,這就導致每次對String的操作都會生成新的String物件,不僅效率低下,而且浪費大量優先的記憶體空間;
StringBuffer是可變類和執行緒安全的字串操作類,任何對它指向的字串的操作都不會產生新的物件。每個StringBuffer物件都有一定的緩衝區容量,當字串大小沒有超過容量時,不會分配新的容量,當字串大小超過容量時,會自動增加容量,用於多執行緒操作字串
StringBuilder是可變類和執行緒不安全的字串操作類,任何對它指向的字串的操作都不會產生新的物件。每個StringBuffer物件都有一定的緩衝區容量,當字串大小沒有超過容量時,不會分配新的容量,當字串大小超過容量時,會自動增加容量,用於單執行緒操作字串
2、Dubbox工作原理
通過配置中心,和每個Server/Client之間會作一個實時的心跳檢測(因為它們都是建立的Socket長連線),比如幾秒鐘檢測一次。收集每個Server提供的服務的資訊,每個Client的資訊,整理出一個服務列表,當某個Server不可用,那麼就更新受影響的服務對應的serverAddressList,即把這個Server從serverAddressList中踢出去(從地址列表中刪除),同時將推送serverAddressList給這些受影響的服務的clientAddressList裡面的所有Client。如:192.168.0.3掛了,那麼UserService和ProductService的serverAddressList都要把192.168.0.3刪除掉,同時把新的列表告訴對應的Client,當某個Client掛了,那麼更新受影響的服務對應的clientAddressLis,ConfigServer根據服務列表,就能提供一個web管理介面,來檢視管理服務的提供者和使用者。新加一個Server時,由於它會主動與ConfigServer取得聯絡,而ConfigServer又會將這個資訊主動傳送給Client,所以新加一個Server時,只需要啟動Server,然後幾秒鐘內,Client就會使用上它提供的服務Client呼叫服務的機器,每個Client啟動時,主動與ConfigServer建立Socket長連線,並將自己的IP等相應資訊傳送給ConfigServer。Client在使用服務的時候根據服務名稱去ConfigServer中獲取服務提供者資訊(這樣ConfigServer就知道某個服務是當前哪幾個Client在使用),Client拿到這些服務提供者資訊後,與它們都建立連線,後面就可以直接呼叫服務了,當有多個服務提供者的時候,Client根據一定的規則來進行負載均衡,如輪詢,隨機,按權重等。一旦Client使用的服務它對應的服務提供者有變化(服務提供者有新增,刪除的情況),ConfigServer就會把最新的服務提供者列表推送給Client,Client就會依據最新的服務提供者列表重新建立連線,新增的提供者建立連線,刪除的提供者丟棄連線,Server真正提供服務的機器,每個Server啟動時,主動與ConfigServer建立Scoket長連線,並將自己的IP,提供的服務名稱,埠等資訊直接傳送給ConfigServer,ConfigServer就會收集到每個Server提供的服務的資訊。
3、Nginx網段配置
通過nginx模組ngx_http_access_module的指令deny和allow控制某個uri或者一個路徑不讓人訪問。這個模組內建在了nginx中,nginx的訪問控制模組語法很簡單,
allow
語法: allow address | CIDR | unix: | all;
預設值: —
配置段: http, server, location, limit_except
允許某個ip或者一個ip段訪問.如果指定unix:,那將允許socket的訪問.注意:unix在1.5.1中新加入的功能,如果你的版本比這個低,請不要使用這個方法。
deny
語法: deny address | CIDR | unix: | all;
預設值: —
配置段: http, server, location, limit_except
禁止某個ip或者一個ip段訪問.如果指定unix:,那將禁止socket的訪問.注意:unix在1.5.1中新加入的功能,如果版本比這個低,請不要使用這個方法。
4、資料表索引的必要性
索引用來快速地尋找那些具有特定值的記錄,所有MySQL索引都以B-樹的形式儲存。如果沒有索引,執行查詢時MySQL必須從第一個記錄開始掃描整個表的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜尋條件的列上已經建立了索引,MySQL無需掃描任何記錄即可迅速得到目標記錄所在的位置。如果表有1000個記錄,通過索引查詢記錄至少要比順序掃描記錄快100倍。
索引是對資料庫表中一個或多個列(例如,employee表的姓氏(lname)列)的值進行排序的結構。如果想按特定職員的姓來查詢他或她,則與在表中搜尋所有的行相比,索引有助於更快地獲取資訊。
索引提供指標以指向儲存在表中指定列的資料值,然後根據指定的排序次序排列這些指標。資料庫使用索引的方式與使用書的目錄很相似:通過搜尋索引找到特定的值,然後跟隨指標到達包含該值的行。
在資料庫關係圖中,可以為選定的表建立、編輯或刪除索引/鍵屬性頁中的每個索引型別。當儲存附加在此索引上的表或包含此表的資料庫關係圖時,索引同時被儲存。
通常情況下,只有當經常查詢索引列中的資料時,才需要建立索引。索引將佔用磁碟空間,並且降低新增、刪除和更新行的速度。不過在多數情況下,索引所帶來的資料檢索速度的優勢大大超過它的不足之處。然而,如果應用程式非常頻繁地更新資料,或磁碟空間有限,那麼最好限制索引的數量。
5、分散式不使用redis和cookie和session怎麼多伺服器共享使用者登入狀態
分散式下無法使用cookiea實現多伺服器共享使用者登入狀態,因此分散式環境下需要一種全新的登入方式來實現多系統應用群的登入,這就是單點登入。單點登入全稱Single Sign On(以下簡稱SSO),是指在多系統應用群中登入一個系統,便可在其他所有系統中得到授權而無需再次登入,包括單點登入與單點登出兩部分,相比於單系統登入,sso需要一個獨立的認證中心,只有認證中心能接受使用者的使用者名稱密碼等安全資訊,其他系統不提供登入入口,只接受認證中心的間接授權。間接授權通過令牌實現,sso認證中心驗證使用者的使用者名稱密碼沒問題,建立授權令牌,在接下來的跳轉過程中,授權令牌作為引數傳送給各個子系統,子系統拿到令牌,即得到了授權,可以藉此建立區域性會話,區域性會話登入方式與單系統的登入方式相同。這個過程,也就是單點登入的原理。
6、資料庫儲存模式
資料庫系統採用三級模式結構,這是資料庫管理系統內部的系統結構。
資料庫系統設計員可在檢視層、邏輯層和物理層對資料抽象,通過外模式、概念模式和內模式來描述不同層次上的資料特性。
概念模式也稱模式,是資料庫中全部資料的邏輯結構和特徵的描述,它由若干個概念記錄型別組成,只涉及行的描述,不涉及具體的值。概念模式的一個具體值稱為模式的一個例項,同一個模式可以有很多例項。
概念模式反映的是資料庫的結構及其聯絡,所以是相對穩定的;而例項反映的是資料庫某一時刻的狀態,所以是相對變動的。
需要說明的是,概念模式不僅要描述概念記錄型別,還要描述記錄間的聯絡、操作、資料的完整性和安全性等要求。但是,概念模式不涉及儲存結構、訪問技術等細節。只有這樣,概念模式才算做到了“物理資料獨立性”。
描述概念模式的資料定義語言稱為“模式DDL”
外模式也稱使用者模式或子模式,是使用者與資料庫系統的介面,是使用者用到的那部分資料的描述。它由若干個外部記錄型別組成。使用者使用資料操縱語言對資料庫進行操作,實際上是對外模式的外部記錄進行操作。
描述外模式的資料定義語言稱為“外模式DDL”。有了外模式後,程式設計師不必關心概念模式,只與外模式發生聯絡,按外模式的結構儲存和運算元據。
內模式也稱為儲存模式,是資料物理結構和儲存方式的描述,是資料在資料庫內部的表示方式。需要定義所以的內部記錄型別、索引和檔案的組織方式,以及資料控制方面的細節。
例如,記錄的儲存方式是順序儲存、B樹結構儲存還是Hash方法儲存;索引按照什麼方式組織;資料是否壓縮儲存,是否加密;資料的儲存記錄結構有何規定。
需要說明的是,內部記錄並不涉及物理記錄,也不涉及裝置的約束。比內模式更接近於物理儲存和訪問的那些軟體機制是作業系統的一部分(即檔案系統)。例如,從磁碟上讀、寫資料。
描述內模式的資料定義語言稱為“內模式DDL”。
總之,資料按外模式的描述提供給使用者;按內模式的描述儲存在磁碟上;而概念模式提供了連線這兩級模式的相對穩定的中間層,並使得兩級中任意一級的改變都不受另一級的牽制。
資料庫系統在三級模式之間提供了兩級映像:模式/內模式的映像、外模式/模式的映像。這兩級對映保證了資料庫中的資料具有較高的物理獨立性和邏輯獨立性。
7、InnoDB是哪種讀取型別
InnoDB給MySQL的表提供了事務處理、回滾、崩潰修復能力和多版本併發控制的事務安全。在MySQL從3.23.34a開始包含InnnoDB。它是MySQL上第一個提供外來鍵約束的表引擎。而且InnoDB對事務處理的能力,也是其他儲存引擎不能比擬的。靠後版本的MySQL的預設儲存引擎就是InnoDB。
InnoDB的優勢在於提供了良好的事務處理、崩潰修復能力和併發控制。缺點是讀寫效率較差,佔用的資料空間相對較大。
- 複合索引只選擇一部分,查詢是否能命中
看情況,因為聯合索引是由多個欄位組成的索引,查詢時使用聯合索引的一個欄位,如果這個欄位在聯合索引中所有欄位的第一個,那就會用到索引,否則就無法使用到索引。
8、資料庫中事務鎖
事務和鎖的存在都是為了更好的解決併發訪問造成的資料不一致性的的問題樂觀鎖和悲觀鎖都是為了解決併發控制問題,樂觀鎖可以認為是一種在最後提交的時候檢測衝突的手段,而悲觀鎖則是一種避免衝突的手段。樂觀鎖:是應用系統層面和資料的業務邏輯層次上的(實際上並沒有加鎖,只不過大家一直這樣叫而已),利用程式處理併發,它假定當某一個使用者去讀取某一個資料的時候,其他的使用者不會來訪問修改這個資料,但是在最後進行事務的提交的時候會進行版本的檢查,以判斷在該使用者的操作過程中,沒有其他使用者修改了這個資料。開銷比較小樂觀鎖的實現大部分都是基於版本控制實現的,除此之外,還可以通過時間戳的方式,通過提前讀取,事後對比的方式實現
9、樂觀鎖的優勢和劣勢
優勢:如果資料庫記錄始終處於悲觀鎖加鎖狀態,可以想見,如果面對幾百上千個併發,那麼要不斷的加鎖減鎖,而且使用者等待的時間會非常的長,樂觀鎖機制避免了長事務中的資料庫加鎖解鎖開銷,大大提升了大併發量下的系統整體效能表現所以如果系統的併發非常大的話,悲觀鎖定會帶來非常大的效能問題,所以建議就要選擇樂觀鎖定的方法,而如果併發量不大,完全可以使用悲觀鎖定的方法。樂觀鎖也適合於讀比較多的場景。
劣勢:但是樂觀鎖也存在著問題,只能在提交資料時才發現業務事務將要失敗,如果系統的衝突非常的多,而且一旦衝突就要因為重新計算提交而造成較大的代價的話,樂觀鎖也會帶來很大的問題,在某些情況下,發現失敗太遲的代價會非常的大。而且樂觀鎖也無法解決髒讀的問題
10、網際網路高併發小輕快如何實現
不是很清楚,能跟我說說嗎?拆分業務使用微服架構變小?使用成熟框架變輕?使用各種優化提高效能變快?
11、資料庫優化
隨著系統規模的不斷增加,資料量和併發量不斷增大,整個系統架構中最先受到衝擊而形成瓶頸的,定然是資料庫,因此資料庫層面的優化,是一個程式設計師不可或缺的技能,下面就是一些優化方式:
1、索引,建立索引是資料庫優化各種方案之中成本最低,見效最快的解決方案,一般來講,資料庫規模在幾十萬和幾百萬級別的時候見效最快,即便是有不太複雜的表關聯,也能大幅度提高sql的執行效率,這個在我們以前的專案應用中,有非常深刻的體會,本來耗時50s的sql,在增加索引後可以提升到1-2s,而且不需要有程式碼改動,成本低廉,見效明顯
2、分庫分表分割槽
分庫,可以按照業務分庫,分流資料庫併發壓力,使資料庫表更加有條理性,最起碼更加好找吧,我們當時是把查詢庫和系統庫(增刪改比較頻繁的表)分開了,這樣如果有大查詢,不影響系統庫
分表,剛才說了,索引適合應對百萬級別的資料量,千萬級別資料量使用的好,勉強也能湊合,但如果是上億級別的資料量,索引就無能為力了,因為單索引檔案可能就已經上百兆或者更多了,那麼,輪到我們的分表分割槽登場了
分割槽
分割槽的實現道理和分表一樣,也是將相應規則的資料放在一起,唯一不同的是分割槽你只需要設定好分割槽規則,插入的資料會被自動插入到指定的區裡,當然查詢的時候也能很快查詢到需要區,相當於是分表對外透明瞭,出現跨表資料庫自動幫我們合併做了處理,使用起來比分表更加方便,但是分割槽也有自己的問題,每一個資料庫表的併發訪問是有上限的,也就是說,分表能夠抗高併發,而分割槽不能,如何選擇,要考慮實際情況
3、資料庫引擎
mysql比較常用的資料庫引擎有兩種,一種是innodb、一種是myisam 一個千萬級資料量複雜sql測試,myisam的效率大概能夠比innodb快1-2倍,雖然效率提升不是很明顯,但是也有提——之所以mysiam快,是因為他的資料儲存結構、索引儲存結構和innodb不一樣的,mysiam的索引結構是在記憶體中存的當然,mysiam也有弱點,那就是是表級鎖,而innodb是行級鎖,所以,mysiam適用於一次插入,多次查詢的表,或者是讀寫分離中的讀庫中的表,而對於修改插入刪除操作比較頻繁的表,就很不合適了
4、預處理
一般來說,實時資料(當天的資料)還是比較有限的,真正資料量比較大的是歷史資料,基於大表歷史資料的查詢,如果再涉及一些大表關聯,這種sql是非常難以優化的
5、like查詢
大家都知道,like “%str%” 不支援索引,"str%"號是支援索引的因此,如果業務允許,可以使用前匹配的方法是資料庫快速定位到資料,在結果集中再進行like匹配,如果這個結果集不是很大,是可以大幅提升執行效率的,這個需要對業務和程式有靈活的變通,如果業務實在不允許前匹配,那就可以採用solr或者elastisearch來進行模糊匹配,但是進行模糊匹配有個前提,原始資料是字串的話,不要帶有特殊符號,如#,&,% 等,這樣會造成分詞不準,最終導致查詢結果不正確
6、讀寫分離
在資料庫併發大的情況下,最好的做法就是進行橫向擴充套件,增加機器,以提升抗併發能力,而且還兼有資料備份功能
12、Docker
Docker 是一個開源的應用容器引擎,基於 Go 語言並遵從Apache2.0協議開源。Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然後釋出到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面(類似 iPhone 的 app),更重要的是容器效能開銷極低。它的好處是:
1、簡化程式:
Docker 讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上,便可以實現虛擬化。Docker改變了虛擬化的方式,使開發者可以直接將自己的成果放入Docker中進行管理。方便快捷已經是 Docker的最大優勢,過去需要用數天乃至數週的 任務,在Docker容器的處理下,只需要數秒就能完成。
2、避免選擇恐懼症:
如果你有選擇恐懼症,還是資深患者。Docker 幫你 打包你的糾結!比如 Docker 映象;Docker 映象中包含了執行環境和配置,所以 Docker 可以簡化部署多種應用例項工作。比如 Web 應用、後臺應用、資料庫應用、大資料應用比如 Hadoop 叢集、訊息佇列等等都可以打包成一個映象部署。
3、節省開支:
一方面,雲端計算時代到來,使開發者不必為了追求效果而配置高額的硬體,Docker 改變了高效能必然高價格的思維定勢。Docker 與雲的結合,讓雲空間得到更充分的利用。不僅解決了硬體管理的問題,也改變了虛擬化的方式。
2. MySQL 是哪種讀取方式
不好意思,能給我談談什麼是資料庫的讀取方式嗎?如果說是儲存引擎的話,我知道MYSQL有 MYISAM 儲存引擎,是沒有事務的,適合做查詢,比較快,還有一種的資料儲存引擎innodb,是有事務的,適合做增刪改。
八、公司筆試題
1、多執行緒Hashmap死迴圈的操作是由於哪一步
HashMap是採用連結串列解決Hash衝突,因為是連結串列結構,那麼就很容易形成閉合的鏈路,這樣在迴圈的時候只要有執行緒對這個HashMap進行get操作就會產生死迴圈。 在單執行緒情況下,只有一個執行緒對HashMap的資料結構進行操作,是不可能產生閉合的迴路的。那就只有在多執行緒併發的情況下才會出現這種情況,那就是在put操作的時候,如果size>initialCapacity*loadFactor,那麼這時候HashMap就會進行rehash操作,隨之HashMap的結構就會發生翻天覆地的變化。很有可能就是在兩個執行緒在這個時候同時觸發了rehash操作,產生了閉合的迴路。
2、講述一下Hashmap的實現原理
HashMap的工作原理:HashMap是基於雜湊法(又稱雜湊法hashing)的原理,使用put(key, value)儲存物件到HashMap中,使用get(key)從HashMap中獲取物件。當我們給put()方法傳遞鍵和值時,我們先對鍵呼叫hashCode()方法,返回的hashCode用於找到bucket(桶)位置來儲存Entry物件。”HashMap是在bucket中儲存鍵物件和值物件,作為Map.Entry。並不是僅僅只在bucket中儲存值。
3、List的實現類有哪些
1、ArrayList非執行緒安全 基於物件陣列
get(int index)不需要遍歷陣列,速度快;
iterator()方法中呼叫了get(int index),所以速度也快
set(int index, E e)不需要遍歷陣列,速度快
add方法需要考慮擴容與陣列複製問題,速度慢
remove(Object o)需要遍歷陣列,並複製陣列元素,速度慢
remove(int index)不需要遍歷陣列,需要複製陣列元素,但不常用
contain(E)需要遍歷陣列
2、LinkedList 非執行緒安全 基於環形雙向連結串列
get(int index)需要遍歷連結串列,速度慢;
iterator()方法中呼叫了get(int index),所以速度也慢
set(int index, E e)方法中呼叫了get(int index),所以速度也慢
add方法不需要考慮擴容與陣列複製問題,只需建立新物件,再將新物件的前後節點的指標指向重新分配一下就好,速度快
remove(Object o)需要遍歷連結串列,但不需要複製元素,只需將所要刪除的物件的前後節點的指標指向重新分配一下以及將所要刪除的物件的三個屬性置空即可,速度快
remove(int index)需要遍歷連結串列,但不需要複製元素,只需將所要刪除的物件的前後節點的指標指向重新分配一下以及將所要刪除的物件的三個屬性置空即可,但不常用
contain(E)需要遍歷連結串列
3、Vector(執行緒安全的ArrayList)
擴容機制與ArrayList不同
4、Stack(繼承於Vector)執行緒安全
效率低下,可採用雙端佇列Deque或LinkedList來實現,Deque用的較多
- Redis有哪些資料型別
Redis支援五種資料型別:string(字串),hash(雜湊),list(列表),set(集合)及zset(sorted set:有序集合)。 - 訊息佇列是如何進行消費的
JMS規範目前支援兩種訊息模型:點對點(point to point, queue)和釋出/訂閱(publish/subscribe,topic)在點對點模式中,訊息生產者生產訊息傳送到queue中,然後訊息消費者從queue中取出並且消費訊息。訊息被消費以後,queue中不再有儲存,所以訊息消費者不可能消費到已經被消費的訊息。Queue支援存在多個消費者,但是對一個訊息而言,只會有一個消費者可以消費。
4、微信支付寶銀聯的接入流程 - 使用Dobbox開發如何提供http協議的介面
- Springboot如何用最簡單的方法讀其它的配置檔案
使用註解@PropertySource@Value - Dobbox如何優化
先檢視資源使用有沒有出現瓶頸的地方。根據監控資訊顯示從以下幾個方面來分析問題。
•整體環境
•CPU:
•記憶體:
•網路:
•線上網路利用率
•程式環境
5、Maven的操作命令你知道的有哪些
七大常用,三大生命週期,clean,compile,test,package,site,install,deploy
6、談談高併發的測試
通過Apache的JMetty高併發測試軟體工具實現測試
7、你知道哪些演算法
1.快速排序演算法
歸併排序(Merge sort,臺灣譯作:合併排序)是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。
二分查詢演算法是一種在有序陣列中查詢某一特定元素的搜尋演算法。搜素過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜素過程結束;如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為空,則代表找不到。這種搜尋演算法每一次比較都使搜尋範圍縮小一半。折半搜尋每次把搜尋區域減少一半,時間複雜度為Ο(logn) 。
BFPRT演算法解決的問題十分經典,即從某n個元素的序列中選出第k大(第k小)的元素,通過巧妙的分析,BFPRT可以保證在最壞情況下仍為線性時間複雜度。該演算法的思想與快速排序思想相似。
2.深度優先搜尋演算法(Depth-First-Search),是搜尋演算法的一種。
廣度優先搜尋演算法(Breadth-First-Search),是一種圖形搜尋演算法。簡單的說,BFS是從根節點開始,沿著樹(圖)的寬度遍歷樹(圖)的節點。如果所有節點均被訪問,則演算法中止。BFS同樣屬於盲目搜尋。一般用佇列資料結構來輔助實現BFS演算法。
戴克斯特拉演算法(Dijkstra’s algorithm)是由荷蘭電腦科學家艾茲赫爾·戴克斯特拉提出。迪科斯徹演算法使用了廣度優先搜尋解決非負權有向圖的單源最短路徑問題,演算法最終得到一個最短路徑樹。該演算法常用於路由演算法或者作為其他圖演算法的一個子模組。
2.動態規劃演算法
樸素貝葉斯分類演算法 - 使用的ORM框架有什麼
hibernate全自動化ORM,ibatis,Mybatis半自動化ORM,Jfinal等
8、Mybatis分頁外掛有了解嗎
有,PageHelper實現了通用的分頁查詢,其支援的資料有,mysql、Oracle、DB2、PostgreSQL等主流的資料庫
9、全域性異常怎麼實現
springMVC中配置全域性異常解析器SimpleMappingExceptionResolver即可對所有異常進行統一處理。
10、進行搶購時你們redis的鍵是怎麼設計的
用裝置來源拼接使用者資訊拼接商品主鍵拼接隨機串,比如pc-2ad67f912a7a87a-1-adf5da5,用來儲存使用者資訊和商品資訊保證唯一性
九、公司面試題
11、鎖的原理
為了保證共享資料在同一時刻只被一個執行緒使用,我們有一種很簡單的實現思想,就是在共享資料裡儲存一個鎖,當沒有執行緒訪問時,鎖是空的。當有第一個執行緒訪問時,就在鎖裡儲存這個執行緒的標識並允許這個執行緒訪問共享資料。在當前執行緒釋放共享資料之前,如果再有其他執行緒想要訪問共享資料,就要等待鎖釋放。
12、同步程式碼塊和方法加鎖的區別
同步方法是直接在方法上加synchronized實現加鎖,同步程式碼塊則在方法內部加鎖,很明顯,同步方法鎖的範圍比較大,而同步程式碼塊範圍要小點,一般同步的範圍越大,效能就越差,一般需要加鎖進行同步的時候,肯定是範圍越小越好,這樣效能更好
13、mybatis懶載入的原理
mybatis 其實第一步是解析配置檔案,把配置檔案對映為 mybatis 的 Configuration 類,把配置檔案的 xml 屬性都對映為 Java 物件中的屬性值。xml mapper 檔案的處理比較複雜,< resultMap/>標籤對映為 ResultMap 物件,標籤中的< id/>、< result/>、< association/>等對映為 ResultMapping 物件。接著再講建立好 result 物件之後,mybatis 會迴圈 resultMappings(標籤中的每個子標籤都對映為一個 resultMapping,這些 resultMapping 組成了一個集合就是 resultMappings)集合,看有沒有需要懶載入的屬性,如果有的話,則會為這個 result 物件建立一個代理物件。什麼情況下才會出現需要懶載入的屬性呢?只有< association property=”author” column=”author_id” select=”selectAuthor” fetchType=”lazy”/>和< collection property=”xxx” column=”xxx” select=”xxxx” fetchType=”lazy”/>作為一個子標籤出現在< resultMap/>標籤(也不一定只是< resultMap/>標籤,< collection/>等標籤事實上也算是一個< resultMap/>標籤)之內才會出現需要懶載入的屬性。select 屬性和 fetchType=”lazy” 必須同時出現在< collection/>或< association/>屬性中才需要懶載入,select 表示的是巢狀查詢語句的 id ,fetchType=”lazy” 表示的是懶載入。
14用什麼技術代替儲存過程
為什麼要取代儲存過程?如果不用儲存過程,那隻要java技術好,邏輯嚴謹,業務規範,就可以通過程式碼的形式控制業務從而用來代替儲存過程
其他面試題
1、高併發解決方案:
參考文件:https://www.cnblogs.com/cn-sbo/p/10853469.html
https://www.cnblogs.com/donghang/p/9233796.html
- 流量優化:防盜鏈處理
Web資源防盜鏈處理解決方案:
通過請求頭中的referer或者簽名,網站可以檢測目標網頁訪問的來源網頁.
- 前端優化:減少HTTP請求,合併css或js,新增非同步請求,啟用瀏覽器快取和檔案壓縮,CDN加速,建立獨立圖片伺服器.
2.1. 減少HTTP請求次數
2.2. 瀏覽器快取和資料壓縮優化
2.3. CDN加速
2.4. 建立獨立的圖片伺服器
- 服務端優化:頁面靜態化,併發處理,佇列處理,叢集和分散式
頁面靜態化:伺服器返回json格式資料
併發處理:執行緒池分散式鎖
佇列處理:Kafka,ActiveMQ,ZeroMQ,RabbitMQ,Redis
叢集和分散式:採用微服務架構
- 資料庫優化:資料庫快取,分庫分表,分割槽操作,讀寫分離,負載均衡
資料庫中介軟體MyCat
- web伺服器優化:負載均衡,nginx反向代理,7,4層LVS軟體
反向代理:就是客戶端訪問的伺服器不直接提供資源,該伺服器從別的伺服器獲取資源並返回給使用者主要由3個作用
1.可以負載均衡
2.可以轉發請求
3.可以作為前端伺服器和實際請求伺服器整合。
2、資料庫優化思路:
- 根據服務層面:配置mysql效能優化引數;
- 從系統層面增強mysql的效能:優化資料表結構、欄位型別、欄位索引、分表,分庫、讀寫分離等等。
- 從資料庫層面增強效能:優化SQL語句,合理使用欄位索引
- 從程式碼層面增強效能:使用快取和NoSQL資料庫方式儲存
MongoDB/Memcached/Redis來緩解高併發下資料庫查詢的壓力 - 不常使用的資料遷移備份,避免每次都在海量資料中去檢索。
- 提升資料庫伺服器硬體配置,或者搭建資料庫叢集
3、常用的中介軟體:
- 資料庫中介軟體mycat druid
- 訊息中介軟體rabbitmq ActiveMQ
4、關於事務的面試題:
一、什麼是事務?有什麼用?事務的特性ACID
事務提供了一種機制,可用來將一系列資料庫更改歸入一個邏輯操作。更改資料庫後,所做的更改可以作為一個單元進行提交或取消。事務可確保遵循原子性、一致性、隔離性和持續性(ACID)這幾種屬性,以使資料能夠正確地提交到資料庫中。
1)原子性(Atomicity)原子性是指事務是一個不可分割的工作單位,事務中的操作 要麼都發生,要麼都不發生。
2)一致性(Consistency)一個事務中,事務前後資料的完整性必須保持一致。
3)隔離性(Isolation)多個事務,事務的隔離性是指多個使用者併發訪問資料庫時, 一個使用者的 事務不能被其它使用者的事務所干擾,多個併發事務之間資料要相互隔離。
4)永續性(Durability)永續性是指一個事務一旦被提交,它對資料庫中資料的改變 就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響。
二 事務的併發會產生的問題有哪些
1.髒讀
一個事務正在對資料進行更新操作,但是更新還未提交,另一個事務這時也來操作這組資料,並且讀取了前一個事務還未提交的資料,而前一個事務如果操作失敗進行了回滾,後一個事務讀取的就是錯誤的資料,這樣就造成了髒讀
2.不可重複讀
一個事務多次讀取同一個資料,在該事務還未結束時,另一個事務也對該資料進行 了操作,而且在第一個事務兩次讀取之間,第二個事務對資料進行了更新,那麼第一個 事務前後兩個讀取到的資料是不同的,這樣就造成了不可重複讀
3.幻讀
第一個資料正在查詢某一條資料,這時,另一個事務又插入了一條符合條件的資料,第一個事務在第二次查詢符合同一條件的資料時,發現多了一條前一次查詢時沒有的資料,彷彿幻覺一樣,這就是幻讀
三 不可重複讀和幻讀的區別
不可重複讀是指在同一查詢事務中多次進行,由於其他提交事務所做的修改和刪除,每次返回不同的結果集,此時發生不可重複讀
幻讀是指在同一查詢事務中多次進行,由於其他提交的事務所做的插入操作,每次返回不同的結果集,此時發生幻讀表面上看,區別就在於不可重複讀能看見其他事務提交的修改和刪除,而幻讀能看見其他事務提交的插入
四、spring 事務隔離級別
1.default:(預設)
預設隔離級別,使用資料庫預設的事務隔離級別
2.read_uncommitted:(讀未提交)
這是事務最低的隔離級別,他允許另外一個事務可以看到這個事務未提交的資料,這種隔離級別會產生髒讀,不可重複讀和幻讀
3.read_committed(讀已提交)
保證一個事務修改的資料提交後才能被另外一個事務讀取,另外一個事務不能讀取該事務未提交的資料.這種事務隔離級別可以避免髒讀,但是可能會出現不可重複讀和幻讀
4.repeatable_read(可重複讀)
這種事務級別可以防止髒讀,不可重複讀.但是可能出現幻讀.他除了保證一個事務不能讀取另一個事務未提交的資料外,還保證了不可重複讀
5.Serializable 序列化
這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。防止了髒讀、不可重複讀、幻讀
總結:
髒讀 不可重複讀 幻讀
讀未提交 會 會 會
讀已提交 不會 會 會
可重複讀 不會 不會 會
序列化 不會 不會不會
五、spring事務的傳播行為
1.requierd
如果有事務那麼加入事務,沒有的話新建一個
2.not_supported
不開啟事務
3.requires_new
不管是否存在事務,都建立一個新的事務,原來的掛起,新的執行完,繼續執行老事務
4.mandatory
必須在一個已有的事務中執行,否則丟擲異常
5.never
必須在一個沒有的事務中執行,否則丟擲異常
6.supports
如果其他bean呼叫這個方法,在其他bean中宣告事務,那就用事務.如果其他bean沒有宣告事務那就不用事務
六 Spring宣告式事務的回滾機制
在Spring 的事務框架中推薦的事務回滾方法是,在當前執行的事務上下文中丟擲一個異常。如果異常未被處理,當丟擲異常呼叫堆疊的時候,Spring 的事務框架程式碼將捕獲任何未處理的異常,然後並決定是否將此事務標記為回滾。
在預設配置中,Spring 的事務框架程式碼只會將出現runtime, unchecked 異常的事務標記為回滾;也就是說事務中丟擲的異常時RuntimeException或者是其子類,這樣事務才會回滾(預設情況下Error也會導致事務回滾)。在預設配置的情況下,所有的 checked 異常都不會引起事務回滾。如果有需要,可以通過rollback-for 和no-rollback-for進行指定。
七 分散式環境下如何處理事務
分散式事務處理是很難保證acid的。一般做法是犧牲一致性,滿足可用性和分割槽容錯。採用的方式可以是二階段提交,由於二階段提交存在著諸如同步阻塞、單點問題、資料不一致、當機等缺陷,所以還可以採用TCC(補償事務)的方式實現,TCC核心思想是:針對每個操作,都要註冊一個與其對應的確認和補償(撤銷)操作。它分為三個階段,本質也是2階段提交,缺點也比較明顯的,在確認和補償時都有可能失敗,一些業務流程可能用TCC不太好定義及處理。分散式事務還可以基於 mq(訊息佇列)/rpc(遠端方法呼叫)實現最終一致性。還有Mycat可以通過使用者會話Session中設定autocommit=false啟動事務,通過設定ServerConnection中變數txInterrupted=true來控制是否事務異常需要回滾。在Mycat中的事務是一種二階段提交事務方式,但是從實際應用場景出發這種出現故障的概率還是比較小的,因此這種實現方式可以滿足很多應用需求,但如果出現問題,會很麻煩。但在分庫分表,立即可見的應用上是不能滿足業務需求的,所以分散式事務需要根據具體業務的需要權衡取捨的。
------------------面試能用自己的語言用自己的理解描述清楚這個---------------
5、微服務架構下處理分散式事務,你必須知道的事兒
根據微服務架構的鼻祖 Martin Fowler 的忠告,微服務架構中應當儘量避免分散式事務。然而,在某些領域,分散式事務如同宿命中的對手無法避免。
根據微服務架構的鼻祖 Martin Fowler 的忠告,微服務架構中應當儘量避免分散式事務。然而,在某些領域,分散式事務如同宿命中的對手無法避免。
在工程領域,分散式事務的討論主要聚焦於強一致性和最終一致性的解決方案。
典型方案包括:
• 兩階段提交(2PC, Two-phase Commit)方案。
• eBay 事件佇列方案。
• TCC 補償模式。
• 快取資料最終一致性。
一致性理論
分散式事務的目的是保障分庫資料一致性,而跨庫事務會遇到各種不可控制的問題,如個別節點永久性當機,像單機事務一樣的 ACID 是無法奢望的。
另外,業界著名的 CAP 理論也告訴我們,對分散式系統,需要將資料一致性和系統可用性、分割槽容忍性放在天平上一起考慮。
兩階段提交協議(簡稱2PC)是實現分散式事務較為經典的方案,但 2PC 的可擴充套件性很差,在分散式架構下應用代價較大,eBay 架構師 Dan Pritchett 提出了 BASE 理論,用於解決大規模分散式系統下的資料一致性問題。
BASE 理論告訴我們:可以通過放棄系統在每個時刻的強一致性來換取系統的可擴充套件性。
01.CAP 理論
在分散式系統中,一致性(Consistency)、可用性(Availability)和分割槽容忍性(Partition Tolerance)3 個要素最多隻能同時滿足兩個,不可兼得。其中,分割槽容忍性又是不可或缺的。
• 一致性:分散式環境下,多個節點的資料是否強一致。
• 可用性:分散式服務能一直保證可用狀態。當使用者發出一個請求後,服務能在有限時間內返回結果。
• 分割槽容忍性:特指對網路分割槽的容忍性。
舉例:Cassandra、Dynamo 等,預設優先選擇 AP,弱化 C;HBase、MongoDB 等,預設優先選擇 CP,弱化 A。
02.BASE 理論
核心思想:
• 基本可用(Basically Available):指分散式系統在出現故障時,允許損失部分的可用性來保證核心可用。
• 軟狀態(Soft State):指允許分散式系統存在中間狀態,該中間狀態不會影響到系統的整體可用性。
• 最終一致性(Eventual Consistency):指分散式系統中的所有副本資料經過一定時間後,最終能夠達到一致的狀態。
一致性模型
資料的一致性模型可以分成以下三類:
• 強一致性:資料更新成功後,任意時刻所有副本中的資料都是一致的,一般採用同步的方式實現。
• 弱一致性:資料更新成功後,系統不承諾立即可以讀到最新寫入的值,也不承諾具體多久之後可以讀到。
• 最終一致性:弱一致性的一種形式,資料更新成功後,系統不承諾立即可以返回最新寫入的值,但是保證最終會返回上一次更新操作的值。
分散式系統資料的強一致性、弱一致性和最終一致性可以通過 Quorum NRW 演算法分析。
分散式事務解決方案
01.2PC 方案——強一致性
2PC 的核心原理是通過提交分階段和記日誌的方式,記錄下事務提交所處的階段狀態,在元件當機重啟後,可通過日誌恢復事務提交的階段狀態,並在這個狀態節點重試。
如 Coordinator 重啟後,通過日誌可以確定提交處於 Prepare 還是 Prepare All 狀態。若是前者,說明有節點可能沒有 Prepare 成功,或所有節點 Prepare 成功但還沒有下發 Commit,狀態恢復後給所有節點下發 RollBack。
若是 Prepare All 狀態,需要給所有節點下發 Commit,資料庫節點需要保證 Commit 冪等。
2PC 方案的三個問題:
• 同步阻塞。
• 資料不一致。
• 單點問題。
升級的 3PC 方案旨在解決這些問題,主要有兩個改進:
• 增加超時機制。
• 兩階段之間插入準備階段。
但三階段提交也存在一些缺陷,要徹底從協議層面避免資料不一致,可以採用 Paxos 或者 Raft 演算法。
02.eBay 事件佇列方案——最終一致性
eBay 的架構師 Dan Pritchett,曾在一篇解釋 BASE 原理的論文《Base:An Acid Alternative》中提到一個 eBay 分散式系統一致性問題的解決方案。
它的核心思想是將需要分散式處理的任務通過訊息或者日誌的方式來非同步執行,訊息或日誌可以存到本地檔案、資料庫或訊息佇列,再通過業務規則進行失敗重試,它要求各服務的介面是冪等的。
描述的場景為,有使用者表 user 和交易表 transaction,使用者表儲存使用者資訊、總銷售額和總購買額。交易表儲存每一筆交易的流水號、買家資訊、賣家資訊和交易金額。如果產生了一筆交易,需要在交易表增加記錄,同時還要修改使用者表的金額。
論文中提出的解決方法是將更新交易表記錄和使用者表更新訊息放在一個本地事務來完成,為了避免重複消費使用者表更新訊息帶來的問題,增加一個操作記錄表 updates_applied 來記錄已經完成的交易相關的資訊。
這個方案的核心在於第二階段的重試和冪等執行。失敗後重試,這是一種補償機制,它是能保證系統最終一致的關鍵流程。
03.TCC (Try-Confirm-Cancel)補償模式——最終一致性
某業務模型如圖,由服務 A、服務 B、服務 C、服務 D 共同組成的一個微服務架構系統。服務 A 需要依次呼叫服務 B、服務 C 和服務 D 共同完成一個操作。
當服務 A 呼叫服務 D 失敗時,若要保證整個系統資料的一致性,就要對服務 B 和服務 C 的 invoke 操作進行回滾,執行反向的 revert 操作。回滾成功後,整個微服務系統是資料一致的。
實現的三個關鍵要素:
• 服務呼叫鏈必須被記錄下來。
• 每個服務提供者都需要提供一組業務邏輯相反的操作,互為補償,同時回滾操作要保證冪等。
• 必須按失敗原因執行不同的回滾策略。
實現的兩個難點:
• 補償模式的特點是實現簡單,但是想形成一定程度的通用方案比較困難,特別是服務鏈的記錄,因為大部分時候,業務引數或者業務邏輯千差萬別。
• 很多業務特徵使得該服務無法提供一個安全的回滾操作。
04.快取資料最終一致性
在我們的業務系統中,快取(Redis 或者 Memcached)通常被用在資料庫前面,作為資料讀取的緩衝,使得 I/O 操作不至於直接落在資料庫上。
以商品詳情頁為例,假如賣家修改了商品資訊,並寫回到資料庫,但是這時候使用者從商品詳情頁看到的資訊還是從快取中拿到的過時資料,這就出現了快取系統和資料庫系統中的資料不一致的現象。
要解決該場景下快取和資料庫資料不一致的問題,我們有以下兩種解決方案:
• 為快取資料設定過期時間。當快取中資料過期後,業務系統會從資料庫中獲取資料,並將新值放入快取。這個過期時間就是系統可以達到最終一致的容忍時間。
• 更新資料庫資料後,同時清除快取資料。資料庫資料更新後,同步刪除快取中資料,使得下次對商品詳情的獲取直接從資料庫中獲取,並同步到快取。
選擇建議
在面臨資料一致性問題的時候,首先要從業務需求的角度出發,確定我們對於三種一致性模型的接受程度,再通過具體場景來決定解決方案。
從應用角度看,分散式事務的現實場景常常無法規避,在有能力給出其他解決方案前,2PC 也是一個不錯的選擇。
對購物轉賬等電商和金融業務,中介軟體層的 2PC 最大問題在於業務不可見,一旦出現不可抗力或意想不到的一致性破壞。
如資料節點永久性當機,業務難以根據 2PC 的日誌進行補償。金融場景下,資料一致性是命根,業務需要對資料有百分之百的掌控力。
建議使用 TCC 這類分散式事務模型,或基於訊息佇列的柔性事務框架,這兩種方案都在業務層實現,業務開發者具有足夠掌控力,可以結合 SOA 框架來架構,包括 Dubbo、Spring Cloud 等。
多執行緒面試題
38、Syngniazed鎖的四種狀態,怎麼演化的
無鎖狀態、 多個執行緒同時修改資源,只有一個能成功。
偏向鎖狀態、 不存在多執行緒競爭,自動枷鎖
輕量級鎖狀態、 處於偏向鎖的狀態中,被另一個執行緒訪問,會升級為輕量級鎖
重量級鎖狀態 一個執行緒獲取鎖後,其他等待獲取執行緒的鎖都會被阻塞。
synchronized原始採用的是CPU悲觀鎖機制,即執行緒獲得的是獨佔鎖。獨佔鎖意味著其他執行緒只能依靠阻塞來等待執行緒釋放鎖。
高併發面試題:
1、高併發解決方案:
參考文件:https://www.cnblogs.com/cn-sbo/p/10853469.html
https://www.cnblogs.com/donghang/p/9233796.html
- 流量優化:防盜鏈處理
Web資源防盜鏈處理解決方案:
通過請求頭中的referer或者簽名,網站可以檢測目標網頁訪問的來源網頁.
- 前端優化:減少HTTP請求,合併css或js,新增非同步請求,啟用瀏覽器快取和檔案壓縮,CDN加速,建立獨立圖片伺服器.
7.1. 減少HTTP請求次數
7.2. 瀏覽器快取和資料壓縮優化
7.3. CDN加速
7.4. 建立獨立的圖片伺服器
- 服務端優化:頁面靜態化,併發處理,佇列處理,叢集和分散式
頁面靜態化:伺服器返回json格式資料
併發處理:執行緒池 分散式鎖
佇列處理:Kafka,ActiveMQ,ZeroMQ,RabbitMQ,Redis
叢集和分散式:採用微服務架構
- 資料庫優化:資料庫快取,分庫分表,分割槽操作,讀寫分離,負載均衡
資料庫中介軟體 MyCat
- web伺服器優化:負載均衡,nginx反向代理,7,4層LVS軟體
反向代理:就是客戶端訪問的伺服器不直接提供資源,該伺服器從別的伺服器獲取資源並返回給使用者主要由3個作用
1.可以負載均衡
2.可以轉發請求
3.可以作為前端伺服器和實際請求伺服器整合。
2、資料庫優化思路:
7. 根據服務層面:配置mysql效能優化引數;
8. 從系統層面增強mysql的效能:優化資料表結構、欄位型別、欄位索引、分表,分庫、讀寫分離等等。
9. 從資料庫層面增強效能:優化SQL語句,合理使用欄位索引
10. 從程式碼層面增強效能:使用快取和NoSQL資料庫方式儲存
MongoDB/Memcached/Redis來緩解高併發下資料庫查詢的壓力
11. 不常使用的資料遷移備份,避免每次都在海量資料中去檢索。
12. 提升資料庫伺服器硬體配置,或者搭建資料庫叢集
3、常用的中介軟體:
- 資料庫中介軟體 mycat druid
- 訊息中介軟體 rabbitmq ActiveMQ
4、關於事務的面試題:
一、什麼是事務?有什麼用?事務的特性ACID
事務提供了一種機制,可用來將一系列資料庫更改歸入一個邏輯操作。更改資料庫後,所做的更改可以作為一個單元進行提交或取消。事務可確保遵循原子性、一致性、隔離性和持續性(ACID)這幾種屬性,以使資料能夠正確地提交到資料庫中。
1)原子性(Atomicity)原子性是指事務是一個不可分割的工作單位,事務中的操作 要麼都發生,要麼都不發生。
2)一致性(Consistency)一個事務中,事務前後資料的完整性必須保持一致。
3)隔離性(Isolation)多個事務,事務的隔離性是指多個使用者併發訪問資料庫時, 一個使用者的 事務不能被其它使用者的事務所干擾,多個併發事務之間資料要相互隔離。
4)永續性(Durability)永續性是指一個事務一旦被提交,它對資料庫中資料的改變 就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響。
二 事務的併發會產生的問題有哪些
1.髒讀
一個事務正在對資料進行更新操作,但是更新還未提交,另一個事務這時也來操作這組資料,並且讀取了前一個事務還未提交的資料,而前一個事務如果操作失敗進行了回滾,後一個事務讀取的就是錯誤的資料,這樣就造成了髒讀
2.不可重複讀
一個事務多次讀取同一個資料,在該事務還未結束時,另一個事務也對該資料進行 了操作,而且在第一個事務兩次讀取之間,第二個事務對資料進行了更新,那麼第一個 事務前後兩個讀取到的資料是不同的,這樣就造成了不可重複讀
3.幻讀
第一個資料正在查詢某一條資料,這時,另一個事務又插入了一條符合條件的資料,第一個事務在第二次查詢符合同一條件的資料時,發現多了一條前一次查詢時沒有的資料,彷彿幻覺一樣,這就是幻讀
三 不可重複讀和幻讀的區別
不可重複讀是指在同一查詢事務中多次進行,由於其他提交事務所做的修改和刪除,每次返回不同的結果集,此時發生不可重複讀
幻讀是指在同一查詢事務中多次進行,由於其他提交的事務所做的插入操作,每次返回不同的結果集,此時發生幻讀表面上看,區別就在於不可重複讀能看見其他事務提交的修改和刪除,而幻讀能看見其他事務提交的插入
四、spring 事務隔離級別
1.default:(預設)
預設隔離級別,使用資料庫預設的事務隔離級別
2.read_uncommitted:(讀未提交)
這是事務最低的隔離級別,他允許另外一個事務可以看到這個事務未提交的資料,這種隔離級別會產生髒讀,不可重複讀和幻讀
3.read_committed(讀已提交)
保證一個事務修改的資料提交後才能被另外一個事務讀取,另外一個事務不能讀取該事務未提交的資料.這種事務隔離級別可以避免髒讀,但是可能會出現不可重複讀和幻讀
4.repeatable_read(可重複讀)
這種事務級別可以防止髒讀,不可重複讀.但是可能出現幻讀.他除了保證一個事務不能讀取另一個事務未提交的資料外,還保證了不可重複讀
5.Serializable 序列化
這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。防止了髒讀、不可重複讀、幻讀
總結:
髒讀 不可重複讀 幻讀
讀未提交 會 會 會
讀已提交 不會 會 會
可重複讀 不會 不會 會
序列化 不會 不會 不會
五、spring事務的傳播行為
1.requierd
如果有事務那麼加入事務,沒有的話新建一個
2.not_supported
不開啟事務
3.requires_new
不管是否存在事務,都建立一個新的事務,原來的掛起,新的執行完,繼續執行老事務
4.mandatory
必須在一個已有的事務中執行,否則丟擲異常
5.never
必須在一個沒有的事務中執行,否則丟擲異常
6.supports
如果其他bean呼叫這個方法,在其他bean中宣告事務,那就用事務.如果其他bean沒有宣告事務那就不用事務
六 Spring宣告式事務的回滾機制
在Spring 的事務框架中推薦的事務回滾方法是,在當前執行的事務上下文中丟擲一個異常。如果異常未被處理,當丟擲異常呼叫堆疊的時候,Spring 的事務框架程式碼將捕獲任何未處理的異常,然後並決定是否將此事務標記為回滾。
在預設配置中,Spring 的事務框架程式碼只會將出現runtime, unchecked 異常的事務標記為回滾;也就是說事務中丟擲的異常時RuntimeException或者是其子類,這樣事務才會回滾(預設情況下Error也會導致事務回滾)。在預設配置的情況下,所有的 checked 異常都不會引起事務回滾。如果有需要,可以通過rollback-for 和no-rollback-for進行指定。
七 分散式環境下如何處理事務
分散式事務處理是很難保證acid的。一般做法是犧牲一致性,滿足可用性和分割槽容錯。採用的方式可以是二階段提交,由於二階段提交存在著諸如同步阻塞、單點問題、資料不一致、當機等缺陷,所以還可以採用TCC(補償事務)的方式實現,TCC核心思想是:針對每個操作,都要註冊一個與其對應的確認和補償(撤銷)操作。它分為三個階段,本質也是2階段提交,缺點也比較明顯的,在確認和補償時都有可能失敗,一些業務流程可能用TCC不太好定義及處理。分散式事務還可以基於 mq(訊息佇列)/rpc(遠端方法呼叫)實現最終一致性。還有Mycat可以通過使用者會話Session中設定autocommit=false啟動事務,通過設定ServerConnection中變數txInterrupted=true來控制是否事務異常需要回滾。在Mycat中的事務是一種二階段提交事務方式,但是從實際應用場景出發這種出現故障的概率還是比較小的,因此這種實現方式可以滿足很多應用需求,但如果出現問題,會很麻煩。但在分庫分表,立即可見的應用上是不能滿足業務需求的,所以分散式事務需要根據具體業務的需要權衡取捨的。
------------------面試能用自己的語言用自己的理解描述清楚這個---------------
5、微服務架構下處理分散式事務,你必須知道的事兒
根據微服務架構的鼻祖 Martin Fowler 的忠告,微服務架構中應當儘量避免分散式事務。然而,在某些領域,分散式事務如同宿命中的對手無法避免。
根據微服務架構的鼻祖 Martin Fowler 的忠告,微服務架構中應當儘量避免分散式事務。然而,在某些領域,分散式事務如同宿命中的對手無法避免。
在工程領域,分散式事務的討論主要聚焦於強一致性和最終一致性的解決方案。
典型方案包括:
• 兩階段提交(2PC, Two-phase Commit)方案。
• eBay 事件佇列方案。
• TCC 補償模式。
• 快取資料最終一致性。
一致性理論
分散式事務的目的是保障分庫資料一致性,而跨庫事務會遇到各種不可控制的問題,如個別節點永久性當機,像單機事務一樣的 ACID 是無法奢望的。
另外,業界著名的 CAP 理論也告訴我們,對分散式系統,需要將資料一致性和系統可用性、分割槽容忍性放在天平上一起考慮。
兩階段提交協議(簡稱2PC)是實現分散式事務較為經典的方案,但 2PC 的可擴充套件性很差,在分散式架構下應用代價較大,eBay 架構師 Dan Pritchett 提出了 BASE 理論,用於解決大規模分散式系統下的資料一致性問題。
BASE 理論告訴我們:可以通過放棄系統在每個時刻的強一致性來換取系統的可擴充套件性。
01.CAP 理論
在分散式系統中,一致性(Consistency)、可用性(Availability)和分割槽容忍性(Partition Tolerance)3 個要素最多隻能同時滿足兩個,不可兼得。其中,分割槽容忍性又是不可或缺的。
• 一致性:分散式環境下,多個節點的資料是否強一致。
• 可用性:分散式服務能一直保證可用狀態。當使用者發出一個請求後,服務能在有限時間內返回結果。
• 分割槽容忍性:特指對網路分割槽的容忍性。
舉例:Cassandra、Dynamo 等,預設優先選擇 AP,弱化 C;HBase、MongoDB 等,預設優先選擇 CP,弱化 A。
02.BASE 理論
核心思想:
• 基本可用(Basically Available):指分散式系統在出現故障時,允許損失部分的可用性來保證核心可用。
• 軟狀態(Soft State):指允許分散式系統存在中間狀態,該中間狀態不會影響到系統的整體可用性。
• 最終一致性(Eventual Consistency):指分散式系統中的所有副本資料經過一定時間後,最終能夠達到一致的狀態。
一致性模型
資料的一致性模型可以分成以下三類:
• 強一致性:資料更新成功後,任意時刻所有副本中的資料都是一致的,一般採用同步的方式實現。
• 弱一致性:資料更新成功後,系統不承諾立即可以讀到最新寫入的值,也不承諾具體多久之後可以讀到。
• 最終一致性:弱一致性的一種形式,資料更新成功後,系統不承諾立即可以返回最新寫入的值,但是保證最終會返回上一次更新操作的值。
分散式系統資料的強一致性、弱一致性和最終一致性可以通過 Quorum NRW 演算法分析。
分散式事務解決方案
01.2PC 方案——強一致性
2PC 的核心原理是通過提交分階段和記日誌的方式,記錄下事務提交所處的階段狀態,在元件當機重啟後,可通過日誌恢復事務提交的階段狀態,並在這個狀態節點重試。
如 Coordinator 重啟後,通過日誌可以確定提交處於 Prepare 還是 Prepare All 狀態。若是前者,說明有節點可能沒有 Prepare 成功,或所有節點 Prepare 成功但還沒有下發 Commit,狀態恢復後給所有節點下發 RollBack。
若是 Prepare All 狀態,需要給所有節點下發 Commit,資料庫節點需要保證 Commit 冪等。
2PC 方案的三個問題:
• 同步阻塞。
• 資料不一致。
• 單點問題。
升級的 3PC 方案旨在解決這些問題,主要有兩個改進:
• 增加超時機制。
• 兩階段之間插入準備階段。
但三階段提交也存在一些缺陷,要徹底從協議層面避免資料不一致,可以採用 Paxos 或者 Raft 演算法。
02.eBay 事件佇列方案——最終一致性
eBay 的架構師 Dan Pritchett,曾在一篇解釋 BASE 原理的論文《Base:An Acid Alternative》中提到一個 eBay 分散式系統一致性問題的解決方案。
它的核心思想是將需要分散式處理的任務通過訊息或者日誌的方式來非同步執行,訊息或日誌可以存到本地檔案、資料庫或訊息佇列,再通過業務規則進行失敗重試,它要求各服務的介面是冪等的。
描述的場景為,有使用者表 user 和交易表 transaction,使用者表儲存使用者資訊、總銷售額和總購買額。交易表儲存每一筆交易的流水號、買家資訊、賣家資訊和交易金額。如果產生了一筆交易,需要在交易表增加記錄,同時還要修改使用者表的金額。
論文中提出的解決方法是將更新交易表記錄和使用者表更新訊息放在一個本地事務來完成,為了避免重複消費使用者表更新訊息帶來的問題,增加一個操作記錄表 updates_applied 來記錄已經完成的交易相關的資訊。
這個方案的核心在於第二階段的重試和冪等執行。失敗後重試,這是一種補償機制,它是能保證系統最終一致的關鍵流程。
03.TCC (Try-Confirm-Cancel)補償模式——最終一致性
某業務模型如圖,由服務 A、服務 B、服務 C、服務 D 共同組成的一個微服務架構系統。服務 A 需要依次呼叫服務 B、服務 C 和服務 D 共同完成一個操作。
當服務 A 呼叫服務 D 失敗時,若要保證整個系統資料的一致性,就要對服務 B 和服務 C 的 invoke 操作進行回滾,執行反向的 revert 操作。回滾成功後,整個微服務系統是資料一致的。
實現的三個關鍵要素:
• 服務呼叫鏈必須被記錄下來。
• 每個服務提供者都需要提供一組業務邏輯相反的操作,互為補償,同時回滾操作要保證冪等。
• 必須按失敗原因執行不同的回滾策略。
實現的兩個難點:
• 補償模式的特點是實現簡單,但是想形成一定程度的通用方案比較困難,特別是服務鏈的記錄,因為大部分時候,業務引數或者業務邏輯千差萬別。
• 很多業務特徵使得該服務無法提供一個安全的回滾操作。
04.快取資料最終一致性
在我們的業務系統中,快取(Redis 或者 Memcached)通常被用在資料庫前面,作為資料讀取的緩衝,使得 I/O 操作不至於直接落在資料庫上。
以商品詳情頁為例,假如賣家修改了商品資訊,並寫回到資料庫,但是這時候使用者從商品詳情頁看到的資訊還是從快取中拿到的過時資料,這就出現了快取系統和資料庫系統中的資料不一致的現象。
要解決該場景下快取和資料庫資料不一致的問題,我們有以下兩種解決方案:
• 為快取資料設定過期時間。當快取中資料過期後,業務系統會從資料庫中獲取資料,並將新值放入快取。這個過期時間就是系統可以達到最終一致的容忍時間。
• 更新資料庫資料後,同時清除快取資料。資料庫資料更新後,同步刪除快取中資料,使得下次對商品詳情的獲取直接從資料庫中獲取,並同步到快取。
選擇建議
在面臨資料一致性問題的時候,首先要從業務需求的角度出發,確定我們對於三種一致性模型的接受程度,再通過具體場景來決定解決方案。
從應用角度看,分散式事務的現實場景常常無法規避,在有能力給出其他解決方案前,2PC 也是一個不錯的選擇。
對購物轉賬等電商和金融業務,中介軟體層的 2PC 最大問題在於業務不可見,一旦出現不可抗力或意想不到的一致性破壞。
如資料節點永久性當機,業務難以根據 2PC 的日誌進行補償。金融場景下,資料一致性是命根,業務需要對資料有百分之百的掌控力。
建議使用 TCC 這類分散式事務模型,或基於訊息佇列的柔性事務框架,這兩種方案都在業務層實現,業務開發者具有足夠掌控力,可以結合 SOA 框架來架構,包括 Dubbo、Spring Cloud 等。
參考資料 https://www.cnblogs.com/cn-sbo/p/10853469.html
高併發的解決方案:
流量優化:防盜鏈處理
防止別人通過一些技術手段繞過本站的資源展示頁面,盜用本站的資源,讓繞開本站資源展示頁面的資源連結失效,可以大大減輕伺服器及頻寬的壓力
前端優化:減少HTTP請求,合併css或js,新增非同步請求,啟用瀏覽器快取和檔案壓縮,CDN加速,建立獨立圖片伺服器,
服務端優化:頁面靜態化,併發處理,佇列處理
資料庫優化:資料庫快取,分庫分表,分割槽操作,讀寫分離,負載均衡
web伺服器優化:負載均衡,nginx反向代理,7,4層LVS軟體
資料庫的優化問題
參考檔案連結地址: https://www.cnblogs.com/ycqi/p/10833617.html
資料庫的優化主要從一下8點出發
一、 根據服務層面:配置mysql效能優化引數
1、 目的:
湖州街29號時瑞大廈6層
通過根據伺服器目前狀況,修改Mysql的系統引數,達到合理利用伺服器現有資源,最大合理的提高MySQL效能。
2、伺服器引數:
32G記憶體、4個CPU,每個CPU 8核。
3、MySQL目前安裝狀況。
MySQL目前安裝,用的是MySQL預設的最大支援配置。拷貝的是my-huge.cnf.編碼已修改為UTF-8.具體修改及安裝MySQL,可以參考<<Linux系統上安裝MySQL 5.5>>幫助文件。
4、修改MySQL配置
參考檔案的位置: https://www.cnblogs.com/angryprogrammer/p/6667741.html
開啟MySQL配置檔案my.cnf
vi /etc/my.cnf
4.1 MySQL非快取引數變數介紹及修改
4.1.1修改back_log引數值:由預設的50修改為500.(每個連線256kb,佔用:125M)
back_log=500
back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆疊中。也就是說,如果MySql的連線資料達到max_connections時,新來的請求將會被存在堆疊中,以等待某一連線釋放資源,該堆疊的數量即back_log,如果等待連線的數量超過back_log,將不被授予連線資源。將會報:unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待連線程式時.
back_log值不能超過TCP/IP連線的偵聽佇列的大小。若超過則無效,檢視當前系統的TCP/IP連線的偵聽佇列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系統為1024。對於Linux系統推薦設定為小於512的整數。
修改系統核心引數,)http://www.51testing.com/html/64/n-810764.html
檢視mysql 當前系統預設back_log值,命令:
show variables like ‘back_log’; 檢視當前數量
4.1.2修改wait_timeout引數值,由預設的8小時,修改為30分鐘。(本次不用)
wait_timeout=1800(單位為妙)
我對wait-timeout這個引數的理解:MySQL客戶端的資料庫連線閒置最大時間值。
說得比較通俗一點,就是當你的MySQL連線閒置超過一定時間後將會被強行關閉。MySQL預設的wait-timeout 值為8個小時,可以通過命令show variables like 'wait_timeout’檢視結果值;。
設定這個值是非常有意義的,比如你的網站有大量的MySQL連結請求(每個MySQL連線都是要記憶體資源開銷的 ),由於你的程式的原因有大量的連線請求空閒啥事也不幹,白白佔用記憶體資源,或者導致MySQL超過最大連線數從來無法新建連線導致“Too many connections”的錯誤。在設定之前你可以檢視一下你的MYSQL的狀態(可用show processlist),如果經常發現MYSQL中有大量的Sleep程式,則需要 修改wait-timeout值了。
interactive_timeout:伺服器關閉互動式連線前等待活動的秒數。互動式客戶端定義為在mysql_real_connect()中使用CLIENT_INTERACTIVE選項的客戶端。
wait_timeout:伺服器關閉非互動連線之前等待活動的秒數。線上程啟動時,根據全域性wait_timeout值或全域性 interactive_timeout值初始化會話wait_timeout值,取決於客戶端型別(由mysql_real_connect()的連線選項CLIENT_INTERACTIVE定義).
這兩個引數必須配合使用。否則單獨設定wait_timeout無效
4.1.3修改max_connections引數值,由預設的151,修改為3000(750M)。
max_connections=3000
max_connections是指MySql的最大連線數,如果伺服器的併發連線請求量比較大,建議調高此值,以增加並行連線數量,當然這建立在機器能支撐的情況下,因為如果連線數越多,介於MySql會為每個連線提供連線緩衝區,就會開銷越多的記憶體,所以要適當調整該值,不能盲目提高設值。可以過’conn%'萬用字元檢視當前狀態的連線數量,以定奪該值的大小。
MySQL伺服器允許的最大連線數16384;
檢視系統當前最大連線數:
show variables like ‘max_connections’;
4.1…4修改max_user_connections值,由預設的0,修改為800
max_user_connections=800
max_user_connections是指每個資料庫使用者的最大連線
針對某一個賬號的所有客戶端並行連線到MYSQL服務的最大並行連線數。簡單說是指同一個賬號能夠同時連線到mysql服務的最大連線數。設定為0表示不限制。
目前預設值為:0不受限制。
這兒順便介紹下Max_used_connections:它是指從這次mysql服務啟動到現在,同一時刻並行連線數的最大值。它不是指當前的連線情況,而是一個比較值。如果在過去某一個時刻,MYSQL服務同時有1000個請求連線過來,而之後再也沒有出現這麼大的併發請求時,則Max_used_connections=1000.請注意與show variables 裡的max_user_connections的區別。預設為0表示無限大。
檢視max_user_connections值
show variables like ‘max_user_connections’;
4.1.5修改thread_concurrency值,由目前預設的8,修改為64
thread_concurrency=64
thread_concurrency的值的正確與否, 對mysql的效能影響很大, 在多個cpu(或多核)的情況下,錯誤設定了thread_concurrency的值, 會導致mysql不能充分利用多cpu(或多核), 出現同一時刻只能一個cpu(或核)在工作的情況。
thread_concurrency應設為CPU核數的2倍. 比如有一個雙核的CPU, 那thread_concurrency 的應該為4; 2個雙核的cpu, thread_concurrency的值應為8.
比如:根據上面介紹我們目前系統的配置,可知道為4個CPU,每個CPU為8核,按照上面的計算規則,這兒應為:482=64
檢視系統當前thread_concurrency預設配置命令:
show variables like ‘thread_concurrency’;
4.1.6新增skip-name-resolve,預設被註釋掉,沒有該引數。
skip-name-resolve
skip-name-resolve:禁止MySQL對外部連線進行DNS解析,使用這一選項可以消除MySQL進行DNS解析的時間。但需要注意,如果開啟該選項,則所有遠端主機連線授權都要使用IP地址方式,否則MySQL將無法正常處理連線請求!
4.1.7 skip-networking,預設被註釋掉。沒有該引數。(本次無用)
skip-networking建議被註釋掉,不要開啟
開啟該選項可以徹底關閉MySQL的TCP/IP連線方式,如果WEB伺服器是以遠端連線的方式訪問MySQL資料庫伺服器則不要開啟該選項!否則將無法正常連線!
4.1.8 default-storage-engine(設定MySQL的預設儲存引擎)
default-storage-engine= InnoDB(設定InnoDB型別,另外還可以設定MyISAM型別)
設定建立資料庫及表預設儲存型別
show table status like ‘tablename’顯示錶的當前儲存狀態值
檢視MySQL有哪些儲存狀態及預設儲存狀態
show engines;
建立表並指定儲存型別
CREATE TABLE mytable (id int, title char(20)) ENGINE = INNODB;
修改表儲存型別:
Alter table tableName engine =engineName
備註:設定完後把以下幾個開啟:
Uncomment the following if you are using InnoDB tables
innodb_data_home_dir = /var/lib/mysql
#innodb_data_file_path = ibdata1:1024M;ibdata2:10M:autoextend(要註釋掉,否則會建立一個新的把原來的替換的。)
innodb_log_group_home_dir = /var/lib/mysql
You can set …_buffer_pool_size up to 50 - 80 %
of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 1000M
innodb_additional_mem_pool_size = 20M
Set …_log_file_size to 25 % of buffer pool size
innodb_log_file_size = 500M
innodb_log_buffer_size = 20M
innodb_flush_log_at_trx_commit = 0
innodb_lock_wait_timeout = 50
設定完後一定記得把MySQL安裝目錄地址(我們目前是預設安裝所以地址/var/lib/mysql/)下的ib_logfile0和ib_logfile1刪除掉。否則重啟MySQL起動失敗。
4.2 MySQL快取變數介紹及修改
資料庫屬於IO密集型的應用程式,其主職責就是資料的管理及儲存工作。而我們知道,從記憶體中讀取一個資料庫的時間是微秒級別,而從一塊普通硬碟上讀取一個 IO是在毫秒級別,二者相差3個數量級。所以,要優化資料庫,首先第一步需要優化的就是IO,儘可能將磁碟IO轉化為記憶體IO。本文先從MySQL資料庫 IO相關引數(快取引數)的角度來看看可以通過哪些引數進行IO優化
4.2.1全域性快取
啟動MySQL時就要分配並且總是存在的全域性快取。目前有:key_buffer_size(預設值:402653184,即384M)、innodb_buffer_pool_size(預設值:134217728即:128M)、innodb_additional_mem_pool_size(預設值:8388608即:8M)、innodb_log_buffer_size(預設值:8388608即:8M)、query_cache_size(預設值:33554432即:32M)等五個。總共:560M.
這些變數值都可以通過命令如:show variables like ‘變數名’;檢視到。
4.2.1.1:key_buffer_size,本系統目前為384M,可修改為400M
key_buffer_size=400M
key_buffer_size是用於索引塊的緩衝區大小,增加它可得到更好處理的索引(對所有讀和多重寫),對MyISAM(MySQL表儲存的一種型別,可以百度等檢視詳情)表效能影響最大的一個引數。如果你使它太大,系統將開始換頁並且真的變慢了。嚴格說是它決定了資料庫索引處理的速度,尤其是索引讀的速度。對於記憶體在4GB左右的伺服器該引數可設定為256M或384M.
怎麼才能知道key_buffer_size的設定是否合理呢,一般可以檢查狀態值Key_read_requests和Key_reads ,比例key_reads / key_read_requests應該儘可能的低,比如1:100,1:1000 ,1:10000。其值可以用以下命令查得:show status like ‘key_read%’;
比如檢視系統當前key_read和key_read_request值為:
±------------------±------+
| Variable_name | Value |
±------------------±------+
| Key_read_requests | 28535 |
| Key_reads | 269 |
±------------------±------+
可知道有28535個請求,有269個請求在記憶體中沒有找到直接從硬碟讀取索引.
未命中快取的概率為:0.94%=269/28535100%. 一般未命中概率在0.1之下比較好。目前已遠遠大於0.1,證明效果不好。若命中率在0.01以下,則建議適當的修改key_buffer_size值。
http://dbahacker.com/mysql/innodb-myisam-compare(InnoDB與MyISAM的六大區別)
http://kb.cnblogs.com/page/99810/(檢視儲存引擎介紹)
MyISAM、InnoDB、MyISAM Merge引擎、InnoDB、memory(heap)、archive
4.2.1.2:innodb_buffer_pool_size(預設128M)
innodb_buffer_pool_size=1024M(1G)
innodb_buffer_pool_size:主要針對InnoDB表效能影響最大的一個引數。功能與Key_buffer_size一樣。InnoDB佔用的記憶體,除innodb_buffer_pool_size用於儲存頁面快取資料外,另外正常情況下還有大約8%的開銷,主要用在每個快取頁幀的描述、adaptive hash等資料結構,如果不是安全關閉,啟動時還要恢復的話,還要另開大約12%的記憶體用於恢復,兩者相加就有差不多21%的開銷。假設:12G的innodb_buffer_pool_size,最多的時候InnoDB就可能佔用到14.5G的記憶體。若系統只有16G,而且只執行MySQL,且MySQL只用InnoDB,
那麼為MySQL開12G,是最大限度地利用記憶體了。
另外InnoDB和 MyISAM 儲存引擎不同, MyISAM 的 key_buffer_size 只能快取索引鍵,而 innodb_buffer_pool_size 卻可以快取資料塊和索引鍵。適當的增加這個引數的大小,可以有效的減少 InnoDB 型別的表的磁碟 I/O 。
當我們操作一個 InnoDB 表的時候,返回的所有資料或者去資料過程中用到的任何一個索引塊,都會在這個記憶體區域中走一遭。
可以通過 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 計算快取命中率,並根據命中率來調整 innodb_buffer_pool_size 引數大小進行優化。值可以用以下命令查得:show status like ‘Innodb_buffer_pool_read%’;
比如檢視當前系統中系統中
| Innodb_buffer_pool_read_requests | 1283826 |
| Innodb_buffer_pool_reads | 519 |
±--------------------------------------±--------+
其命中率99.959%=(1283826-519)/1283826100% 命中率越高越好。
4.2.1.3:innodb_additional_mem_pool_size(預設8M)
innodb_additional_mem_pool_size=20M
innodb_additional_mem_pool_size 設定了InnoDB儲存引擎用來存放資料字典資訊以及一些內部資料結構的記憶體空間大小,所以當我們一個MySQL Instance中的資料庫物件非常多的時候,是需要適當調整該引數的大小以確保所有資料都能存放在記憶體中提高訪問效率的。
這個引數大小是否足夠還是比較容易知道的,因為當過小的時候,MySQL會記錄Warning資訊到資料庫的error log中,這時候你就知道該調整這個引數大小了。
檢視當前系統mysql的error日誌 cat /var/lib/mysql/機器名.error 發現有很多waring警告。所以要調大為20M.
根據MySQL手冊,對於2G記憶體的機器,推薦值是20M。
32G記憶體的 100M
4.2.1.4:innodb_log_buffer_size(預設8M)
innodb_log_buffer_size=20M
innodb_log_buffer_size 這是InnoDB儲存引擎的事務日誌所使用的緩衝區。類似於Binlog Buffer,InnoDB在寫事務日誌的時候,為了提高效能,也是先將資訊寫入Innofb Log Buffer中,當滿足innodb_flush_log_trx_commit引數所設定的相應條件(或者日誌緩衝區寫滿)之後,才會將日誌寫到檔案 (或者同步到磁碟)中。可以通過innodb_log_buffer_size 引數設定其可以使用的最大記憶體空間。
InnoDB 將日誌寫入日誌磁碟檔案前的緩衝大小。理想值為 1M 至 8M。大的日誌緩衝允許事務執行時不需要將日誌儲存入磁碟而只到事務被提交(commit)。 因此,如果有大的事務處理,設定大的日誌緩衝可以減少磁碟I/O。 在 my.cnf中以數字格式設定。
預設是8MB,系的如頻繁的系統可適當增大至4MB~8MB。當然如上面介紹所說,這個引數實際上還和另外的flush引數相關。一般來說不建議超過32MB
注:innodb_flush_log_trx_commit引數對InnoDB Log的寫入效能有非常關鍵的影響,預設值為1。該引數可以設定為0,1,2,解釋如下:
0:log buffer中的資料將以每秒一次的頻率寫入到log file中,且同時會進行檔案系統到磁碟的同步操作,但是每個事務的commit並不會觸發任何log buffer 到log file的重新整理或者檔案系統到磁碟的重新整理操作;
1:在每次事務提交的時候將log buffer 中的資料都會寫入到log file,同時也會觸發檔案系統到磁碟的同步;
2:事務提交會觸發log buffer到log file的重新整理,但並不會觸發磁碟檔案系統到磁碟的同步。此外,每秒會有一次檔案系統到磁碟同步操作。
實際測試發現,該值對插入資料的速度影響非常大,設定為2時插入10000條記錄只需要2秒,設定為0時只需要1秒,而設定為1時則需要229秒。因此,MySQL手冊也建議儘量將插入操作合併成一個事務,這樣可以大幅提高速度。根據MySQL手冊,在存在丟失最近部分事務的危險的前提下,可以把該值設為0。
4.5.1.5:query_cache_size(預設32M)
query_cache_size=40M
query_cache_size: 主要用來快取MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當我們開啟了 Query Cache功能,MySQL在接受到一條select語句的請求後,如果該語句滿足Query Cache的要求(未顯式說明不允許使用Query Cache,或者已經顯式申明需要使用Query Cache),MySQL會直接根據預先設定好的HASH演算法將接受到的select語句以字串方式進行hash,然後到Query Cache中直接查詢是否已經快取。也就是說,如果已經在快取中,該select請求就會直接將資料返回,從而省略了後面所有的步驟(如SQL語句的解析,優化器優化以及向儲存引擎請求資料等),極大的提高效能。根據MySQL使用者手冊,使用查詢緩衝最多可以達到238%的效率。
當然,Query Cache也有一個致命的缺陷,那就是當某個表的資料有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的快取資料失效。所以,當我們的資料變化非常頻繁的情況下,使用Query Cache可能會得不償失
Query Cache的使用需要多個引數配合,其中最為關鍵的是query_cache_size和query_cache_type,前者設定用於快取 ResultSet的記憶體大小,後者設定在何場景下使用Query Cache。在以往的經驗來看,如果不是用來快取基本不變的資料的MySQL資料庫,query_cache_size一般256MB是一個比較合適的大小。當然,這可以通過計算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))來進行調整。 query_cache_type可以設定為0(OFF),1(ON)或者2(DEMOND),分別表示完全不使用query cache,除顯式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有顯示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,則表明經常出現緩衝. 如果Qcache_hits的值也非常大,則表明查詢緩衝使用非常頻繁,此時需要增加緩衝大小;
根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,一般不建議太大,256MB可能已經差不多了,大型的配置型靜態資料可適當調大.
可以通過命令:show status like ‘Qcache_%’;檢視目前系統Query catch使用大小
| Qcache_hits | 1892463 |
| Qcache_inserts | 35627
命中率98.17%=1892463/(1892463 +35627 )*100
4.2.2區域性快取
除了全域性緩衝,MySql還會為每個連線發放連線緩衝。個連線到MySQL伺服器的執行緒都需要有自己的緩衝。大概需要立刻分配256K,甚至線上程空閒時,它們使用預設的執行緒堆疊,網路快取等。事務開始之後,則需要增加更多的空間。執行較小的查詢可能僅給指定的執行緒增加少量的記憶體消耗,然而如果對資料表做複雜的操作例如掃描、排序或者需要臨時表,則需分配大約read_buffer_size,
sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的記憶體空間. 不過它們只是在需要的時候才分配,並且在那些操作做完之後就釋放了。有的是立刻分配成單獨的組塊。tmp_table_size 可能高達MySQL所能分配給這個操作的最大記憶體空間了
。注意,這裡需要考慮的不只有一點——可能會分配多個同一種型別的快取,例如用來處理子查詢。一些特殊的查詢的記憶體使用量可能更大——如果在MyISAM表上做成批的插入
時需要分配 bulk_insert_buffer_size 大小的記憶體;執行 ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 命令時需要分配 myisam_sort_buffer_size 大小的記憶體。
4.2.2.1:read_buffer_size(預設值:2097144即2M)
read_buffer_size=4M
read_buffer_size 是MySql讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會為它分配一段記憶體緩衝區。read_buffer_size變數控制這一
緩衝區的大小。如果對錶的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變數值以及記憶體緩衝區大小提高其效能.
4.2.2.2:sort_buffer_size(預設值:2097144即2M)
sort_buffer_size=4M
sort_buffer_size是MySql執行排序使用的緩衝大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試增加sort_buffer_size變數的大小
4.2.2.3: read_rnd_buffer_size(預設值:8388608即8M)
read_rnd_buffer_size=8M
read_rnd_buffer_size 是MySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀快取區。進行排序查詢時,MySql會首先掃描一遍該緩衝,以避免磁碟搜尋,提高查詢速度,如果需要排序大量資料,可適當調高該值。但MySql會為每個客戶連線發放該緩衝空間,所以應儘量適當設定該值,以避免記憶體開
銷過大。
4.2.2.4: tmp_table_size(預設值:8388608 即:16M)
tmp_table_size=16M
tmp_table_size是MySql的heap (堆積)表緩衝大小。所有聯合在一個DML指令內完成,並且大多數聯合甚至可以不用臨時表即可以完成。大多數臨時表是基於內
存的(HEAP)表。具有大的記錄長度的臨時表 (所有列的長度的和)或包含BLOB列的表儲存在硬碟上。如果某個內部heap(堆積)表大小超過tmp_table_size,MySQL可以根據需要自
動將記憶體中的heap表改為基於硬碟的MyISAM表。還可以通過設定tmp_table_size選項來增加臨時表的大小。也就是說,如果調高該值,MySql同時將增加heap表的大小,可達到提高
聯接查詢速度的效果。
4.2.2.5:record_buffer:(預設值:)
record_buffer每個進行一個順序掃描的執行緒為其掃描的每張表分配這個大小的一個緩衝區。如果你做很多順序掃描,你可能想要增加該值。預設數值是131072
(128K)
4.2.3其它快取:
4.2.3.1:table_cache(預設值:512)
TABLE_CACHE(5.1.3及以後版本又名TABLE_OPEN_CACHE)
table_cache指定表快取記憶體的大小。每當MySQL訪問一個表時,如果在表緩衝區中還有空間,該表就被開啟並放入其中,這樣可以更快地訪問表內容。通過檢查峰值時間的狀態值Open_tables和Opened_tables,可以決定是否需要增加table_cache的值。如果你發現open_tables等於table_cache,並且opened_tables在不斷增長,那麼你就需要增加table_cache的值了(上述狀態值可以使用SHOW STATUS LIKE ‘Open%tables’獲得)。注意,不能盲目地把table_cache設定成很大的值。如果設定得太高,可能會造成檔案描述符不足,從而造成效能不穩定或者連線失敗。
SHOW STATUS LIKE ‘Open%tables’;
±--------------±------+
| Variable_name | Value |
±--------------±------+
| Open_tables | 356 |
| Opened_tables | 0 |
±--------------±------+
2 rows in set (0.00 sec)
open_tables表示當前開啟的表快取數,如果執行flush tables操作,則此係統會關閉一些當前沒有使用的表快取而使得此狀態值減小;
opend_tables表示曾經開啟的表快取數,會一直進行累加,如果執行flush tables操作,值不會減小。
在mysql預設安裝情況下,table_cache的值在2G記憶體以下的機器中的值預設時256到512,如果機器有4G記憶體,則預設這個值 是2048,但這決意味著機器記憶體越大,這個值應該越大,因為table_cache加大後,使得mysql對SQL響應的速度更快了,不可避免的會產生 更多的死鎖(dead lock),這樣反而使得資料庫整個一套操作慢了下來,嚴重影響效能。所以平時維護中還是要根據庫的實際情況去作出判斷,找到最適合你維護的庫的 table_cache值。
由於MySQL是多執行緒的機制,為了提高效能,每個執行緒都是獨自開啟自己需要的表的檔案描 述符,而不是通過共享已經開啟的.針對不同儲存引擎處理的方法當然也不一樣
在myisam表引擎中,資料檔案的描述符 (descriptor)是不共享的,但是索引檔案的描述符卻是所有執行緒共享的.Innodb中和使用表空間型別有關,假如是共享表空間那麼實際就一個數 據檔案,當然佔用的資料檔案描述符就會比獨立表空間少.
mysql手冊上給的建議大小 是:table_cache=max_connections*n
n表示查詢語句中最大表數, 還需要為臨時表和檔案保留一些額外的檔案描述符。
這個資料遭到很多質疑,table_cache夠用就好,檢查 Opened_tables值,如果這個值很大,或增長很快那麼你就得考慮加大table_cache了.
table_cache:所有執行緒開啟的表的數目。增大該值可以增加mysqld需要的檔案描述符的數量。預設值是64.
4.2.3.2 thread_cache_size (伺服器執行緒快取)
thread_cache_size=64
預設的thread_cache_size=8,但是看到好多配置的樣例裡的值一般是32,64,甚至是128,感覺這個引數對優化應該有幫助,於是查了下:
根據調查發現以上伺服器執行緒快取thread_cache_size沒有進行設定,或者設定過小,這個值表示可以重新利用儲存在快取中執行緒的數量,當斷開連線時如果快取中還有空間,那麼客戶端的執行緒將被放到快取中,如果執行緒重新被請求,那麼請求將從快取中讀取,如果快取中是空的或者是新的請求,那麼這個執行緒將被重新建立,如果有很多新的執行緒,增加這個值可以改善系統效能.通過比較 Connections 和 Threads_created 狀態的變數,可以看到這個變數的作用。(–>表示要調整的值) 根據實體記憶體設定規則如下:
1G —> 8
2G —> 16
3G —> 32 >3G —> 64
mysql> show status like ‘thread%’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 0 | <—當前被快取的空閒執行緒的數量
| Threads_connected | 1 | <—正在使用(處於連線狀態)的執行緒
| Threads_created | 1498 | <—服務啟動以來,建立了多少個執行緒
| Threads_running | 1 | <—正在忙的執行緒(正在查詢資料,傳輸資料等等操作)
+——————-+——-+
檢視開機起來資料庫被連線了多少次?
mysql> show status like ‘%connection%’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Connections | 1504 | –>服務啟動以來,歷史連線數
| Max_used_connections | 2 |
+———————-+——-+
通過連線執行緒池的命中率來判斷設定值是否合適?命中率超過90%以上,設定合理。
(Connections - Threads_created) / Connections * 100 %
二、 從系統層面增強mysql的效能:優化資料表結構、欄位型別、欄位索引、分表,分庫、讀寫分離等等
表結構:資料型別選擇;字元編碼;適當拆分;適度冗餘;儘量使用 NOT NULL 詳細, 讀寫分離
表結構的優化:
https://www.cnblogs.com/eeds-wangwei/p/8135771.html
由於MySQL資料庫是基於行(Row)儲存的資料庫,而資料庫操作 IO 的時候是以 page(block)的方式,也就是說,如果我們每條記錄所佔用的空間量減小,就會使每個page中可存放的資料行數增大,那麼每次 IO 可訪問的行數也就增多了。反過來說,處理相同行數的資料,需要訪問的 page 就會減少,也就是 IO 操作次數降低,直接提升效能。此外,由於我們的記憶體是有限的,增加每個page中存放的資料行數,就等於增加每個記憶體塊的快取資料量,同時還會提升記憶體換中資料命中的機率,也就是快取命中率。
一、資料型別選擇
資料庫操作中最為耗時的操作就是 IO 處理,大部分資料庫操作 90% 以上的時間都花在了 IO 讀寫上面。所以儘可能減少 IO 讀寫量,可以在很大程度上提高資料庫操作的效能。
我們無法改變資料庫中需要儲存的資料,但是我們可以在這些資料的儲存方式方面花一些心思。下面的這些關於欄位型別的優化建議主要適用於記錄條數較多,資料量較大的場景,因為精細化的資料型別設定可能帶來維護成本的提高,過度優化也可能會帶來其他的問題:
1.數字型別:非萬不得已不要使用DOUBLE,不僅僅只是儲存長度的問題,同時還會存在精確性的問題。同樣,固定精度的小數,也不建議使用DECIMAL,建議乘以固定倍數轉換成整數儲存,可以大大節省儲存空間,且不會帶來任何附加維護成本。對於整數的儲存,在資料量較大的情況下,建議區分開 TINYINT / INT / BIGINT 的選擇,因為三者所佔用的儲存空間也有很大的差別,能確定不會使用負數的欄位,建議新增unsigned定義。當然,如果資料量較小的資料庫,也可以不用嚴格區分三個整數型別。
2.字元型別:非萬不得已不要使用 TEXT 資料型別,其處理方式決定了他的效能要低於char或者是varchar型別的處理。定長欄位,建議使用 CHAR 型別,不定長欄位儘量使用 VARCHAR,且僅僅設定適當的最大長度,而不是非常隨意的給一個很大的最大長度限定,因為不同的長度範圍,MySQL也會有不一樣的儲存處理。
3.時間型別:儘量使用TIMESTAMP型別,因為其儲存空間只需要 DATETIME 型別的一半。對於只需要精確到某一天的資料型別,建議使用DATE型別,因為他的儲存空間只需要3個位元組,比TIMESTAMP還少。不建議通過INT型別類儲存一個unix timestamp 的值,因為這太不直觀,會給維護帶來不必要的麻煩,同時還不會帶來任何好處。
4.ENUM & SET:對於狀態欄位,可以嘗試使用 ENUM 來存放,因為可以極大的降低儲存空間,而且即使需要增加新的型別,只要增加於末尾,修改結構也不需要重建表資料。如果是存放可預先定義的屬性資料呢?可以嘗試使用SET型別,即使存在多種屬性,同樣可以遊刃有餘,同時還可以節省不小的儲存空間。
5.LOB型別:強烈反對在資料庫中存放 LOB 型別資料,雖然資料庫提供了這樣的功能,但這不是他所擅長的,我們更應該讓合適的工具做他擅長的事情,才能將其發揮到極致。在資料庫中儲存 LOB 資料就像讓一個多年前在學校學過一點Java的營銷專業人員來寫 Java 程式碼一樣。
二、字元編碼
字符集直接決定了資料在MySQL中的儲存編碼方式,由於同樣的內容使用不同字符集表示所佔用的空間大小會有較大的差異,所以通過使用合適的字符集,可以幫助我們儘可能減少資料量,進而減少IO操作次數。
1.純拉丁字元能表示的內容,沒必要選擇 latin1 之外的其他字元編碼,因為這會節省大量的儲存空間。
2.如果我們可以確定不需要存放多種語言,就沒必要非得使用UTF8或者其他UNICODE字元型別,這回造成大量的儲存空間浪費。
3.MySQL的資料型別可以精確到欄位,所以當我們需要大型資料庫中存放多位元組資料的時候,可以通過對不同表不同欄位使用不同的資料型別來較大程度減小資料儲存量,進而降低 IO 操作次數並提高快取命中率。
三、適當拆分
有些時候,我們可能會希望將一個完整的物件對應於一張資料庫表,這對於應用程式開發來說是很有好的,但是有些時候可能會在效能上帶來較大的問題。
當我們的表中存在類似於 TEXT 或者是很大的 VARCHAR型別的大欄位的時候,如果我們大部分訪問這張表的時候都不需要這個欄位,我們就該義無反顧的將其拆分到另外的獨立表中,以減少常用資料所佔用的儲存空間。這樣做的一個明顯好處就是每個資料塊中可以儲存的資料條數可以大大增加,既減少物理 IO 次數,也能大大提高記憶體中的快取命中率。
上面幾點的優化都是為了減少每條記錄的儲存空間大小,讓每個資料庫中能夠儲存更多的記錄條數,以達到減少 IO 操作次數,提高快取命中率。下面這個優化建議可能很多開發人員都會覺得不太理解,因為這是典型的反正規化設計,而且也和上面的幾點優化建議的目標相違背。
四、適度冗餘
為什麼我們要冗餘?這不是增加了每條資料的大小,減少了每個資料塊可存放記錄條數嗎?
確實,這樣做是會增大每條記錄的大小,降低每條記錄中可存放資料的條數,但是在有些場景下我們仍然還是不得不這樣做:
1.被頻繁引用且只能通過 Join 2張(或者更多)大表的方式才能得到的獨立小欄位。
2.這樣的場景由於每次Join僅僅只是為了取得某個小欄位的值,Join到的記錄又大,會造成大量不必要的 IO,完全可以通過空間換取時間的方式來優化。不過,冗餘的同時需要確保資料的一致性不會遭到破壞,確保更新的同時冗餘欄位也被更新。
五、儘量使用 NOT NULL
NULL 型別比較特殊,SQL 難優化。雖然 MySQL NULL型別和 Oracle 的NULL 有差異,會進入索引中,但如果是一個組合索引,那麼這個NULL 型別的欄位會極大影響整個索引的效率。此外,NULL 在索引中的處理也是特殊的,也會佔用額外的存放空間。
很多人覺得 NULL 會節省一些空間,所以儘量讓NULL來達到節省IO的目的,但是大部分時候這會適得其反,雖然空間上可能確實有一定節省,倒是帶來了很多其他的優化問題,不但沒有將IO量省下來,反而加大了SQL的IO量。所以儘量確保 DEFAULT 值不是 NULL,也是一個很好的表結構設計優化習慣。
主從配置讀寫分離
https://www.cnblogs.com/luckcs/articles/2543607.html
MySQL主從複製(Master-Slave)與讀寫分離(MySQL-Proxy)實踐
Mysql作為目前世界上使用最廣泛的免費資料庫,相信所有從事系統運維的工程師都一定接觸過。但在實際的生產環境中,由單臺Mysql作為獨立的資料庫是完全不能滿足實際需求的,無論是在安全性,高可用性以及高併發等各個方面。
因此,一般來說都是通過 主從複製(Master-Slave)的方式來同步資料,再通過讀寫分離(MySQL-Proxy)來提升資料庫的併發負載能力 這樣的方案來進行部署與實施的。
如下圖所示:
下面是我在實際工作過程中所整理的筆記,在此分享出來,以供大家參考。
一、MySQL的安裝與配置
具體的安裝過程,建議參考我的這一篇文章:http://heylinux.com/archives/993.html
值得一提的是,我的安裝過程都是原始碼包編譯安裝的,並且所有的配置與資料等都統一規劃到了/opt/mysql目錄中,因此在一臺伺服器上安裝完成以後,可以將整個mysql目錄打包,然後傳到其它伺服器上解包,便可立即使用。
二、MySQL主從複製
場景描述:
主資料庫伺服器:192.168.10.130,MySQL已經安裝,並且無應用資料。
從資料庫伺服器:192.168.10.131,MySQL已經安裝,並且無應用資料。
2.1 主伺服器上進行的操作
啟動mysql服務
/opt/mysql/init.d/mysql start
通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
授權給從資料庫伺服器192.168.10.131
mysql> GRANT REPLICATION SLAVE ON . to ‘rep1’@‘192.168.10.131’ identified by ‘password’;
查詢主資料庫狀態
Mysql> show master status;
±-----------------±---------±-------------±-----------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
±-----------------±---------±-------------±-----------------+
| mysql-bin.000005 | 261 | | |
±-----------------±---------±-------------±-----------------+
記錄下 FILE 及 Position 的值,在後面進行從伺服器操作的時候需要用到。
2.2 配置從伺服器
修改從伺服器的配置檔案/opt/mysql/etc/my.cnf
將 server-id = 1修改為 server-id = 10,並確保這個ID沒有被別的MySQL服務所使用。
啟動mysql服務
/opt/mysql/init.d/mysql start
通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
執行同步SQL語句
mysql> change master to
master_host=’192.168.10.130’,
master_user=’rep1’,
master_password=’password’,
master_log_file=’mysql-bin.000005’,
master_log_pos=261;
正確執行後啟動Slave同步程式
mysql> start slave;
主從同步檢查
mysql> show slave status\G
**************** 1. row *******************
Slave_IO_State:
Master_Host: 192.168.10.130
Master_User: rep1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 415
Relay_Log_File: localhost-relay-bin.000008
Relay_Log_Pos: 561
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: YES
Slave_SQL_Running: YES
Replicate_Do_DB:
……………省略若干……………
Master_Server_Id: 1
1 row in set (0.01 sec)
其中Slave_IO_Running 與 Slave_SQL_Running 的值都必須為YES,才表明狀態正常。
如果主伺服器已經存在應用資料,則在進行主從複製時,需要做以下處理:
(1)主資料庫進行鎖表操作,不讓資料再進行寫入動作
mysql> FLUSH TABLES WITH READ LOCK;
(2)檢視主資料庫狀態
mysql> show master status;
(3)記錄下 FILE 及 Position 的值。
將主伺服器的資料檔案(整個/opt/mysql/data目錄)複製到從伺服器,建議通過tar歸檔壓縮後再傳到從伺服器解壓。
(4)取消主資料庫鎖定
mysql> UNLOCK TABLES;
2.3 驗證主從複製效果
主伺服器上的操作
在主伺服器上建立資料庫first_db
mysql> create database first_db;
Query Ok, 1 row affected (0.01 sec)
在主伺服器上建立表first_tb
mysql> create table first_tb(id int(3),name char(10));
Query Ok, 1 row affected (0.00 sec)
在主伺服器上的表first_tb中插入記錄
mysql> insert into first_tb values (001,’myself’);
Query Ok, 1 row affected (0.00 sec)
在從伺服器上檢視
mysql> show databases;
±-------------------+
| Database |
±-------------------+
| information_schema |
| first_db |
| mysql |
| performance_schema |
| test |
±-------------------+
5 rows in set (0.01 sec)
資料庫first_db已經自動生成
mysql> use first_db
Database chaged
mysql> show tables;
±-------------------+
| Tables_in_first_db |
±-------------------+
| first_tb |
±-------------------+
1 row in set (0.02 sec)
資料庫表first_tb也已經自動建立
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
1 rows in set (0.00 sec)
記錄也已經存在
由此,整個MySQL主從複製的過程就完成了,接下來,我們進行MySQL讀寫分離的安裝與配置。
三、MySQL讀寫分離
場景描述:
資料庫Master主伺服器:192.168.10.130
資料庫Slave從伺服器:192.168.10.131
MySQL-Proxy排程伺服器:192.168.10.132
以下操作,均是在192.168.10.132即MySQL-Proxy排程伺服器 上進行的。
3.1 MySQL的安裝與配置
具體的安裝過程與上文相同。
3.2 檢查系統所需軟體包
通過 rpm -qa | grep name 的方式驗證以下軟體包是否已全部安裝。
gcc* gcc-c++* autoconf* automake* zlib* libxml* ncurses-devel* libmcrypt* libtool* flex* pkgconfig*
libevent* glib*
若缺少相關的軟體包,可通過yum -y install方式線上安裝,或直接從系統安裝光碟中找到並通過rpm -ivh方式安裝。
3.3 編譯安裝lua
MySQL-Proxy的讀寫分離主要是通過rw-splitting.lua指令碼實現的,因此需要安裝lua。
lua可通過以下方式獲得
從http://www.lua.org/download.html下載原始碼包
從rpm.pbone.net搜尋相關的rpm包
download.fedora.redhat.com/pub/fedora/epel/5/i386/lua-5.1.4-4.el5.i386.rpm
download.fedora.redhat.com/pub/fedora/epel/5/x86_64/lua-5.1.4-4.el5.x86_64.rpm
這裡我們建議採用原始碼包進行安裝
cd /opt/install
wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
tar zvfx lua-5.1.4.tar.gz
cd lua-5.1.4
vi src/Makefile
在 CFLAGS= -O2 -Wall
(MYCFLAGS)這一行記錄里加上−fPIC,更改為CFLAGS=−O2−Wall−fPIC
(MYCFLAGS)這一行記錄里加上−fPIC,更改為CFLAGS=−O2−Wall−fPIC
(MYCFLAGS) 來避免編譯過程中出現錯誤。
make linux
make install
cp etc/lua.pc /usr/lib/pkgconfig/
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig
3.4 安裝配置MySQL-Proxy
MySQL-Proxy可通過以下網址獲得:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/
推薦採用已經編譯好的二進位制版本,因為採用原始碼包進行編譯時,最新版的MySQL-Proxy對automake,glib以及libevent的版本都有很高的要求,而這些軟體包都是系統的基礎套件,不建議強行進行更新。
並且這些已經編譯好的二進位制版本在解壓後都在統一的目錄內,因此建議選擇以下版本:
32位RHEL5平臺:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
64位RHEL5平臺:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-64bit.tar.gz
測試平臺為RHEL5 32位,因此選擇32位的軟體包
wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
tar xzvf mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
mv mysql-proxy-0.8.1-linux-rhel5-x86-32bit /opt/mysql-proxy
建立mysql-proxy服務管理指令碼
mkdir /opt/mysql-proxy/init.d/
vim mysql-proxy
01
#!/bin/sh
02
03
mysql-proxy This script starts and stops the mysql-proxy daemon
04
05
chkconfig: - 78 30
06
processname: mysql-proxy
07
description: mysql-proxy is a proxy daemon to mysql
08
09
Source function library.
10
. /etc/rc.d/init.d/functions
11
12
#PROXY_PATH=/usr/local/bin
13
PROXY_PATH=/opt/mysql-proxy/bin
14
15
prog=“mysql-proxy”
16
17
Source networking configuration.
18
. /etc/sysconfig/network
19
20
Check that networking is up.
21
[ ${NETWORKING} = “no” ] && exit 0
22
23
Set default mysql-proxy configuration.
24
#PROXY_OPTIONS="–daemon"
25
PROXY_OPTIONS="–admin-username=root --admin-password=password --proxy-read-only-backend-addresses=192.168.10.131:3306 --proxy-backend-addresses=192.168.10.130:3306 --admin-lua-script=/opt/mysql-proxy/lib/mysql-proxy/lua/admin.lua --proxy-lua-script=/opt/mysql-proxy/scripts/rw-splitting.lua"
26
PROXY_PID=/opt/mysql-proxy/run/mysql-proxy.pid
27
28
Source mysql-proxy configuration.
29
if [ -f /etc/sysconfig/mysql-proxy ]; then
30
. /etc/sysconfig/mysql-proxy
31
fi
32
33
PATH=
P
A
T
H
:
/
u
s
r
/
b
i
n
:
/
u
s
r
/
l
o
c
a
l
/
b
i
n
:
PATH:/usr/bin:/usr/local/bin:
PATH:/usr/bin:/usr/local/bin:PROXY_PATH
34
35
By default it’s all good
36
RETVAL=0
37
38
See how we were called.
39
case “$1” in
40
start)
41
# Start daemon.
42
echo -n $"Starting $prog: "
43
NICELEVEL
NICELEVEL
PROXY_PATH/mysql-proxy
P
R
O
X
Y
O
P
T
I
O
N
S
−
−
d
a
e
m
o
n
−
−
p
i
d
−
f
i
l
e
=
PROXY_OPTIONS --daemon --pid-file=
PROXYOPTIONS−−daemon−−pid−file=PROXY_PID --user=mysql --log-level=warning --log-file=/opt/mysql-proxy/log/mysql-proxy.log
44
RETVAL=$?
45
echo
46
if [ $RETVAL = 0 ]; then
47
touch /var/lock/subsys/mysql-proxy
48
fi
49
;;
50
stop)
51
# Stop daemons.
52
echo -n $"Stopping $prog: "
53
killproc
p
r
o
g
54
R
E
T
V
A
L
=
prog 54 RETVAL=
prog54RETVAL=?
55
echo
56
if [ $RETVAL = 0 ]; then
57
rm -f /var/lock/subsys/mysql-proxy
58
rm -f $PROXY_PID
59
fi
60
;;
61
restart)
62
$0 stop
63
sleep 3
64
$0 start
65
;;
66
condrestart)
67
[ -e /var/lock/subsys/mysql-proxy ] &&
0
r
e
s
t
a
r
t
68
;
;
69
s
t
a
t
u
s
)
70
s
t
a
t
u
s
m
y
s
q
l
−
p
r
o
x
y
71
R
E
T
V
A
L
=
0 restart 68 ;; 69 status) 70 status mysql-proxy 71 RETVAL=
0restart68;;69status)70statusmysql−proxy71RETVAL=?
72
;;
73
*)
74
echo “Usage: $0 {start|stop|restart|status|condrestart}”
75
RETVAL=1
76
;;
77
esac
78
79
exit $RETVAL
指令碼引數詳解:
PROXY_PATH=/opt/mysql-proxy/bin //定義mysql-proxy服務二進位制檔案路徑
PROXY_OPTIONS="–admin-username=root \ //定義內部管理伺服器賬號
–admin-password=password \ //定義內部管理伺服器密碼
–proxy-read-only-backend-addresses=192.168.10.131:3306 \ //定義後端只讀從伺服器地址
–proxy-backend-addresses=192.168.10.130:3306 \ //定義後端主伺服器地址
–admin-lua-script=/opt/mysql-proxy/lib/mysql-proxy/lua/admin.lua \ //定義lua管理指令碼路徑
–proxy-lua-script=/opt/mysql-proxy/scripts/rw-splitting.lua" \ //定義lua讀寫分離指令碼路徑
PROXY_PID=/opt/mysql-proxy/run/mysql-proxy.pid //定義mysql-proxy PID檔案路徑
NICELEVEL
NICELEVEL
PROXY_PATH/mysql-proxy
PROX
Y
O
PTIONS −−daemon //定義以守護程式模式啟動−−keepalive //使程式在異常關閉後能夠自動恢復−−pid−file=
PROXYOPTIONS −−daemon //定義以守護程式模式啟動−−keepalive //使程式在異常關閉後能夠自動恢復−−pid−file=
PROXY_PID \ //定義mysql-proxy PID檔案路徑
–user=mysql \ //以mysql使用者身份啟動服務
–log-level=warning \ //定義log日誌級別,由高到低分別有(error|warning|info|message|debug)
–log-file=/opt/mysql-proxy/log/mysql-proxy.log //定義log日誌檔案路徑
cp mysql-proxy /opt/mysql-proxy/init.d/
chmod +x /opt/mysql-proxy/init.d/mysql-proxy
mkdir /opt/mysql-proxy/run
mkdir /opt/mysql-proxy/log
mkdir /opt/mysql-proxy/scripts
配置並使用rw-splitting.lua讀寫分離指令碼
最新的指令碼我們可以從最新的mysql-proxy原始碼包中獲取
cd /opt/install
wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1.tar.gz
tar xzvf mysql-proxy-0.8.1.tar.gz
cd mysql-proxy-0.8.1
cp lib/rw-splitting.lua /opt/mysql-proxy/scripts
修改讀寫分離指令碼rw-splitting.lua
修改預設連線,進行快速測試,不修改的話要達到連線數為4時才啟用讀寫分離
vim /opt/mysql-proxy/scripts/rw-splitting.lua
– connection pool
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1, //預設為4
max_idle_connections = 1, //預設為8
is_debug = false
}
end
修改完成後,啟動mysql-proxy
/opt/mysql-proxy/init.d/mysql-proxy start
3.5 測試讀寫分離效果
建立用於讀寫分離的資料庫連線使用者
登陸主資料庫伺服器192.168.10.130,通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
mysql> GRANT ALL ON . TO ‘proxy1’@‘192.168.10.132’ IDENTIFIED BY ‘password’;
由於我們配置了主從複製功能,因此從資料庫伺服器192.168.10.131上已經同步了此操作。
為了清晰的看到讀寫分離的效果,需要暫時關閉MySQL主從複製功能
登陸從資料庫伺服器192.168.10.131,通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
關閉Slave同步程式
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
連線MySQL-Proxy
/opt/mysql/bin/mysql -uproxy1 -p’password’ -P4040 -h192.168.10.132
登陸成功後,在first_db資料的first_tb表中插入兩條記錄
mysql> use first_db;
Database changed
mysql> insert into first_tb values (007,’first’);
Query Ok, 1 row affected (0.00 sec)
mysql> insert into first_tb values (110,’second’);
Query Ok, 1 row affected (0.00 sec)
查詢記錄
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
1 rows in set (0.00 sec)
通過讀操作並沒有看到新記錄
mysql> quit
退出MySQL-Proxy
下面,分別登陸到主從資料庫伺服器,對比記錄資訊
首先,檢查主資料庫伺服器
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
| 007 | first |
±-----±-----+
| 110 | second |
±-----±-----+
3 rows in set (0.00 sec)
兩條新記錄都已經存在
然後,檢查從資料庫伺服器
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
1 rows in set (0.00 sec)
沒有新記錄存在
由此驗證,我們已經實現了MySQL讀寫分離,目前所有的寫操作都全部在Master主伺服器上,用來避免資料的不同步;
另外,所有的讀操作都分攤給了其它各個Slave從伺服器上,用來分擔資料庫壓力。
經驗分享:
1.當MySQL主從複製在 show slave status\G 時出現Slave_IO_Running或Slave_SQL_Running 的值不為YES時,需要首先通過 stop slave 來停止從伺服器,然後再執行一次本文 2.1與2.2 章節中的步驟即可恢復,但如果想盡可能的同步更多的資料,可以在Slave上將master_log_pos節點的值在之前同步失效的值的基礎上增大一些,然後反覆測試,直到同步OK。因為MySQL主從複製的原理其實就是從伺服器讀取主伺服器的binlog,然後根據binlog的記錄來更新資料庫。
2.MySQL-Proxy的rw-splitting.lua指令碼在網上有很多版本,但是最準確無誤的版本仍然是原始碼包中所附帶的lib/rw-splitting.lua指令碼,如果有lua指令碼程式設計基礎的話,可以在這個指令碼的基礎上再進行優化;
3.MySQL-Proxy實際上非常不穩定,在高併發或有錯誤連線的情況下,程式很容易自動關閉,因此開啟–keepalive引數讓程式自動恢復是個比較好的辦法,但還是不能從根本上解決問題,因此通常最穩妥的做法是在每個從伺服器上安裝一個MySQL-Proxy供自身使用,雖然比較低效但卻能保證穩定性;
4.一主多從的架構並不是最好的架構,通常比較優的做法是通過程式程式碼和中介軟體等方面,來規劃,比如設定對錶資料的自增id值差異增長等方式來實現兩個或多個主伺服器,但一定要注意保證好這些主伺服器資料的完整性,否則效果會比多個一主多從的架構還要差;
5.MySQL-Cluster 的穩定性也不是太好;
6.Amoeba for MySQL 是一款優秀的中介軟體軟體,同樣可以實現讀寫分離,負載均衡等功能,並且穩定性要大大超過MySQL-Proxy,建議大家用來替代MySQL-Proxy,甚至MySQL-Cluster。
三、 從資料庫層面增強效能:優化SQL語句,合理使用欄位索引
四、 從程式碼層面增強效能:使用快取和NoSQL資料庫方式儲存,如MongoDB/Memcached/Redis來緩解高併發下資料庫查詢的壓力。
五、 減少資料庫操作次數,儘量使用資料庫訪問驅動的批處理方法。
六、 不常使用的資料遷移備份,避免每次都在海量資料中去檢索。
七、 提升資料庫伺服器硬體配置,或者搭建資料庫叢集。
程式設計手段防止SQL隱碼攻擊:使用JDBC PreparedStatement按位插入或查詢;正規表示式過濾(非法字串過濾
資料庫的優化問題
參考檔案連結地址: https://www.cnblogs.com/ycqi/p/10833617.html
資料庫的優化主要從一下8點出發
一、 根據服務層面:配置mysql效能優化引數
1、 目的:
湖州街29號時瑞大廈6層
通過根據伺服器目前狀況,修改Mysql的系統引數,達到合理利用伺服器現有資源,最大合理的提高MySQL效能。
2、伺服器引數:
32G記憶體、4個CPU,每個CPU 8核。
3、MySQL目前安裝狀況。
MySQL目前安裝,用的是MySQL預設的最大支援配置。拷貝的是my-huge.cnf.編碼已修改為UTF-8.具體修改及安裝MySQL,可以參考<<Linux系統上安裝MySQL 5.5>>幫助文件。
4、修改MySQL配置
參考檔案的位置: https://www.cnblogs.com/angryprogrammer/p/6667741.html
開啟MySQL配置檔案my.cnf
vi /etc/my.cnf
4.1 MySQL非快取引數變數介紹及修改
4.1.1修改back_log引數值:由預設的50修改為500.(每個連線256kb,佔用:125M)
back_log=500
back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆疊中。也就是說,如果MySql的連線資料達到max_connections時,新來的請求將會被存在堆疊中,以等待某一連線釋放資源,該堆疊的數量即back_log,如果等待連線的數量超過back_log,將不被授予連線資源。將會報:unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待連線程式時.
back_log值不能超過TCP/IP連線的偵聽佇列的大小。若超過則無效,檢視當前系統的TCP/IP連線的偵聽佇列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系統為1024。對於Linux系統推薦設定為小於512的整數。
修改系統核心引數,)http://www.51testing.com/html/64/n-810764.html
檢視mysql 當前系統預設back_log值,命令:
show variables like ‘back_log’; 檢視當前數量
4.1.2修改wait_timeout引數值,由預設的8小時,修改為30分鐘。(本次不用)
wait_timeout=1800(單位為妙)
我對wait-timeout這個引數的理解:MySQL客戶端的資料庫連線閒置最大時間值。
說得比較通俗一點,就是當你的MySQL連線閒置超過一定時間後將會被強行關閉。MySQL預設的wait-timeout 值為8個小時,可以通過命令show variables like 'wait_timeout’檢視結果值;。
設定這個值是非常有意義的,比如你的網站有大量的MySQL連結請求(每個MySQL連線都是要記憶體資源開銷的 ),由於你的程式的原因有大量的連線請求空閒啥事也不幹,白白佔用記憶體資源,或者導致MySQL超過最大連線數從來無法新建連線導致“Too many connections”的錯誤。在設定之前你可以檢視一下你的MYSQL的狀態(可用show processlist),如果經常發現MYSQL中有大量的Sleep程式,則需要 修改wait-timeout值了。
interactive_timeout:伺服器關閉互動式連線前等待活動的秒數。互動式客戶端定義為在mysql_real_connect()中使用CLIENT_INTERACTIVE選項的客戶端。
wait_timeout:伺服器關閉非互動連線之前等待活動的秒數。線上程啟動時,根據全域性wait_timeout值或全域性 interactive_timeout值初始化會話wait_timeout值,取決於客戶端型別(由mysql_real_connect()的連線選項CLIENT_INTERACTIVE定義).
這兩個引數必須配合使用。否則單獨設定wait_timeout無效
4.1.3修改max_connections引數值,由預設的151,修改為3000(750M)。
max_connections=3000
max_connections是指MySql的最大連線數,如果伺服器的併發連線請求量比較大,建議調高此值,以增加並行連線數量,當然這建立在機器能支撐的情況下,因為如果連線數越多,介於MySql會為每個連線提供連線緩衝區,就會開銷越多的記憶體,所以要適當調整該值,不能盲目提高設值。可以過’conn%'萬用字元檢視當前狀態的連線數量,以定奪該值的大小。
MySQL伺服器允許的最大連線數16384;
檢視系統當前最大連線數:
show variables like ‘max_connections’;
4.1…4修改max_user_connections值,由預設的0,修改為800
max_user_connections=800
max_user_connections是指每個資料庫使用者的最大連線
針對某一個賬號的所有客戶端並行連線到MYSQL服務的最大並行連線數。簡單說是指同一個賬號能夠同時連線到mysql服務的最大連線數。設定為0表示不限制。
目前預設值為:0不受限制。
這兒順便介紹下Max_used_connections:它是指從這次mysql服務啟動到現在,同一時刻並行連線數的最大值。它不是指當前的連線情況,而是一個比較值。如果在過去某一個時刻,MYSQL服務同時有1000個請求連線過來,而之後再也沒有出現這麼大的併發請求時,則Max_used_connections=1000.請注意與show variables 裡的max_user_connections的區別。預設為0表示無限大。
檢視max_user_connections值
show variables like ‘max_user_connections’;
4.1.5修改thread_concurrency值,由目前預設的8,修改為64
thread_concurrency=64
thread_concurrency的值的正確與否, 對mysql的效能影響很大, 在多個cpu(或多核)的情況下,錯誤設定了thread_concurrency的值, 會導致mysql不能充分利用多cpu(或多核), 出現同一時刻只能一個cpu(或核)在工作的情況。
thread_concurrency應設為CPU核數的2倍. 比如有一個雙核的CPU, 那thread_concurrency 的應該為4; 2個雙核的cpu, thread_concurrency的值應為8.
比如:根據上面介紹我們目前系統的配置,可知道為4個CPU,每個CPU為8核,按照上面的計算規則,這兒應為:482=64
檢視系統當前thread_concurrency預設配置命令:
show variables like ‘thread_concurrency’;
4.1.6新增skip-name-resolve,預設被註釋掉,沒有該引數。
skip-name-resolve
skip-name-resolve:禁止MySQL對外部連線進行DNS解析,使用這一選項可以消除MySQL進行DNS解析的時間。但需要注意,如果開啟該選項,則所有遠端主機連線授權都要使用IP地址方式,否則MySQL將無法正常處理連線請求!
4.1.7 skip-networking,預設被註釋掉。沒有該引數。(本次無用)
skip-networking建議被註釋掉,不要開啟
開啟該選項可以徹底關閉MySQL的TCP/IP連線方式,如果WEB伺服器是以遠端連線的方式訪問MySQL資料庫伺服器則不要開啟該選項!否則將無法正常連線!
4.1.8 default-storage-engine(設定MySQL的預設儲存引擎)
default-storage-engine= InnoDB(設定InnoDB型別,另外還可以設定MyISAM型別)
設定建立資料庫及表預設儲存型別
show table status like ‘tablename’顯示錶的當前儲存狀態值
檢視MySQL有哪些儲存狀態及預設儲存狀態
show engines;
建立表並指定儲存型別
CREATE TABLE mytable (id int, title char(20)) ENGINE = INNODB;
修改表儲存型別:
Alter table tableName engine =engineName
備註:設定完後把以下幾個開啟:
Uncomment the following if you are using InnoDB tables
innodb_data_home_dir = /var/lib/mysql
#innodb_data_file_path = ibdata1:1024M;ibdata2:10M:autoextend(要註釋掉,否則會建立一個新的把原來的替換的。)
innodb_log_group_home_dir = /var/lib/mysql
You can set …_buffer_pool_size up to 50 - 80 %
of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 1000M
innodb_additional_mem_pool_size = 20M
Set …_log_file_size to 25 % of buffer pool size
innodb_log_file_size = 500M
innodb_log_buffer_size = 20M
innodb_flush_log_at_trx_commit = 0
innodb_lock_wait_timeout = 50
設定完後一定記得把MySQL安裝目錄地址(我們目前是預設安裝所以地址/var/lib/mysql/)下的ib_logfile0和ib_logfile1刪除掉。否則重啟MySQL起動失敗。
4.2 MySQL快取變數介紹及修改
資料庫屬於IO密集型的應用程式,其主職責就是資料的管理及儲存工作。而我們知道,從記憶體中讀取一個資料庫的時間是微秒級別,而從一塊普通硬碟上讀取一個 IO是在毫秒級別,二者相差3個數量級。所以,要優化資料庫,首先第一步需要優化的就是IO,儘可能將磁碟IO轉化為記憶體IO。本文先從MySQL資料庫 IO相關引數(快取引數)的角度來看看可以通過哪些引數進行IO優化
4.2.1全域性快取
啟動MySQL時就要分配並且總是存在的全域性快取。目前有:key_buffer_size(預設值:402653184,即384M)、innodb_buffer_pool_size(預設值:134217728即:128M)、innodb_additional_mem_pool_size(預設值:8388608即:8M)、innodb_log_buffer_size(預設值:8388608即:8M)、query_cache_size(預設值:33554432即:32M)等五個。總共:560M.
這些變數值都可以通過命令如:show variables like ‘變數名’;檢視到。
4.2.1.1:key_buffer_size,本系統目前為384M,可修改為400M
key_buffer_size=400M
key_buffer_size是用於索引塊的緩衝區大小,增加它可得到更好處理的索引(對所有讀和多重寫),對MyISAM(MySQL表儲存的一種型別,可以百度等檢視詳情)表效能影響最大的一個引數。如果你使它太大,系統將開始換頁並且真的變慢了。嚴格說是它決定了資料庫索引處理的速度,尤其是索引讀的速度。對於記憶體在4GB左右的伺服器該引數可設定為256M或384M.
怎麼才能知道key_buffer_size的設定是否合理呢,一般可以檢查狀態值Key_read_requests和Key_reads ,比例key_reads / key_read_requests應該儘可能的低,比如1:100,1:1000 ,1:10000。其值可以用以下命令查得:show status like ‘key_read%’;
比如檢視系統當前key_read和key_read_request值為:
±------------------±------+
| Variable_name | Value |
±------------------±------+
| Key_read_requests | 28535 |
| Key_reads | 269 |
±------------------±------+
可知道有28535個請求,有269個請求在記憶體中沒有找到直接從硬碟讀取索引.
未命中快取的概率為:0.94%=269/28535100%. 一般未命中概率在0.1之下比較好。目前已遠遠大於0.1,證明效果不好。若命中率在0.01以下,則建議適當的修改key_buffer_size值。
http://dbahacker.com/mysql/innodb-myisam-compare(InnoDB與MyISAM的六大區別)
http://kb.cnblogs.com/page/99810/(檢視儲存引擎介紹)
MyISAM、InnoDB、MyISAM Merge引擎、InnoDB、memory(heap)、archive
4.2.1.2:innodb_buffer_pool_size(預設128M)
innodb_buffer_pool_size=1024M(1G)
innodb_buffer_pool_size:主要針對InnoDB表效能影響最大的一個引數。功能與Key_buffer_size一樣。InnoDB佔用的記憶體,除innodb_buffer_pool_size用於儲存頁面快取資料外,另外正常情況下還有大約8%的開銷,主要用在每個快取頁幀的描述、adaptive hash等資料結構,如果不是安全關閉,啟動時還要恢復的話,還要另開大約12%的記憶體用於恢復,兩者相加就有差不多21%的開銷。假設:12G的innodb_buffer_pool_size,最多的時候InnoDB就可能佔用到14.5G的記憶體。若系統只有16G,而且只執行MySQL,且MySQL只用InnoDB,
那麼為MySQL開12G,是最大限度地利用記憶體了。
另外InnoDB和 MyISAM 儲存引擎不同, MyISAM 的 key_buffer_size 只能快取索引鍵,而 innodb_buffer_pool_size 卻可以快取資料塊和索引鍵。適當的增加這個引數的大小,可以有效的減少 InnoDB 型別的表的磁碟 I/O 。
當我們操作一個 InnoDB 表的時候,返回的所有資料或者去資料過程中用到的任何一個索引塊,都會在這個記憶體區域中走一遭。
可以通過 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 計算快取命中率,並根據命中率來調整 innodb_buffer_pool_size 引數大小進行優化。值可以用以下命令查得:show status like ‘Innodb_buffer_pool_read%’;
比如檢視當前系統中系統中
| Innodb_buffer_pool_read_requests | 1283826 |
| Innodb_buffer_pool_reads | 519 |
±--------------------------------------±--------+
其命中率99.959%=(1283826-519)/1283826100% 命中率越高越好。
4.2.1.3:innodb_additional_mem_pool_size(預設8M)
innodb_additional_mem_pool_size=20M
innodb_additional_mem_pool_size 設定了InnoDB儲存引擎用來存放資料字典資訊以及一些內部資料結構的記憶體空間大小,所以當我們一個MySQL Instance中的資料庫物件非常多的時候,是需要適當調整該引數的大小以確保所有資料都能存放在記憶體中提高訪問效率的。
這個引數大小是否足夠還是比較容易知道的,因為當過小的時候,MySQL會記錄Warning資訊到資料庫的error log中,這時候你就知道該調整這個引數大小了。
檢視當前系統mysql的error日誌 cat /var/lib/mysql/機器名.error 發現有很多waring警告。所以要調大為20M.
根據MySQL手冊,對於2G記憶體的機器,推薦值是20M。
32G記憶體的 100M
4.2.1.4:innodb_log_buffer_size(預設8M)
innodb_log_buffer_size=20M
innodb_log_buffer_size 這是InnoDB儲存引擎的事務日誌所使用的緩衝區。類似於Binlog Buffer,InnoDB在寫事務日誌的時候,為了提高效能,也是先將資訊寫入Innofb Log Buffer中,當滿足innodb_flush_log_trx_commit引數所設定的相應條件(或者日誌緩衝區寫滿)之後,才會將日誌寫到檔案 (或者同步到磁碟)中。可以通過innodb_log_buffer_size 引數設定其可以使用的最大記憶體空間。
InnoDB 將日誌寫入日誌磁碟檔案前的緩衝大小。理想值為 1M 至 8M。大的日誌緩衝允許事務執行時不需要將日誌儲存入磁碟而只到事務被提交(commit)。 因此,如果有大的事務處理,設定大的日誌緩衝可以減少磁碟I/O。 在 my.cnf中以數字格式設定。
預設是8MB,系的如頻繁的系統可適當增大至4MB~8MB。當然如上面介紹所說,這個引數實際上還和另外的flush引數相關。一般來說不建議超過32MB
注:innodb_flush_log_trx_commit引數對InnoDB Log的寫入效能有非常關鍵的影響,預設值為1。該引數可以設定為0,1,2,解釋如下:
0:log buffer中的資料將以每秒一次的頻率寫入到log file中,且同時會進行檔案系統到磁碟的同步操作,但是每個事務的commit並不會觸發任何log buffer 到log file的重新整理或者檔案系統到磁碟的重新整理操作;
1:在每次事務提交的時候將log buffer 中的資料都會寫入到log file,同時也會觸發檔案系統到磁碟的同步;
2:事務提交會觸發log buffer到log file的重新整理,但並不會觸發磁碟檔案系統到磁碟的同步。此外,每秒會有一次檔案系統到磁碟同步操作。
實際測試發現,該值對插入資料的速度影響非常大,設定為2時插入10000條記錄只需要2秒,設定為0時只需要1秒,而設定為1時則需要229秒。因此,MySQL手冊也建議儘量將插入操作合併成一個事務,這樣可以大幅提高速度。根據MySQL手冊,在存在丟失最近部分事務的危險的前提下,可以把該值設為0。
4.5.1.5:query_cache_size(預設32M)
query_cache_size=40M
query_cache_size: 主要用來快取MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當我們開啟了 Query Cache功能,MySQL在接受到一條select語句的請求後,如果該語句滿足Query Cache的要求(未顯式說明不允許使用Query Cache,或者已經顯式申明需要使用Query Cache),MySQL會直接根據預先設定好的HASH演算法將接受到的select語句以字串方式進行hash,然後到Query Cache中直接查詢是否已經快取。也就是說,如果已經在快取中,該select請求就會直接將資料返回,從而省略了後面所有的步驟(如SQL語句的解析,優化器優化以及向儲存引擎請求資料等),極大的提高效能。根據MySQL使用者手冊,使用查詢緩衝最多可以達到238%的效率。
當然,Query Cache也有一個致命的缺陷,那就是當某個表的資料有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的快取資料失效。所以,當我們的資料變化非常頻繁的情況下,使用Query Cache可能會得不償失
Query Cache的使用需要多個引數配合,其中最為關鍵的是query_cache_size和query_cache_type,前者設定用於快取 ResultSet的記憶體大小,後者設定在何場景下使用Query Cache。在以往的經驗來看,如果不是用來快取基本不變的資料的MySQL資料庫,query_cache_size一般256MB是一個比較合適的大小。當然,這可以通過計算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))來進行調整。 query_cache_type可以設定為0(OFF),1(ON)或者2(DEMOND),分別表示完全不使用query cache,除顯式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有顯示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,則表明經常出現緩衝. 如果Qcache_hits的值也非常大,則表明查詢緩衝使用非常頻繁,此時需要增加緩衝大小;
根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,一般不建議太大,256MB可能已經差不多了,大型的配置型靜態資料可適當調大.
可以通過命令:show status like ‘Qcache_%’;檢視目前系統Query catch使用大小
| Qcache_hits | 1892463 |
| Qcache_inserts | 35627
命中率98.17%=1892463/(1892463 +35627 )*100
4.2.2區域性快取
除了全域性緩衝,MySql還會為每個連線發放連線緩衝。個連線到MySQL伺服器的執行緒都需要有自己的緩衝。大概需要立刻分配256K,甚至線上程空閒時,它們使用預設的執行緒堆疊,網路快取等。事務開始之後,則需要增加更多的空間。執行較小的查詢可能僅給指定的執行緒增加少量的記憶體消耗,然而如果對資料表做複雜的操作例如掃描、排序或者需要臨時表,則需分配大約read_buffer_size,
sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的記憶體空間. 不過它們只是在需要的時候才分配,並且在那些操作做完之後就釋放了。有的是立刻分配成單獨的組塊。tmp_table_size 可能高達MySQL所能分配給這個操作的最大記憶體空間了
。注意,這裡需要考慮的不只有一點——可能會分配多個同一種型別的快取,例如用來處理子查詢。一些特殊的查詢的記憶體使用量可能更大——如果在MyISAM表上做成批的插入
時需要分配 bulk_insert_buffer_size 大小的記憶體;執行 ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 命令時需要分配 myisam_sort_buffer_size 大小的記憶體。
4.2.2.1:read_buffer_size(預設值:2097144即2M)
read_buffer_size=4M
read_buffer_size 是MySql讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會為它分配一段記憶體緩衝區。read_buffer_size變數控制這一
緩衝區的大小。如果對錶的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變數值以及記憶體緩衝區大小提高其效能.
4.2.2.2:sort_buffer_size(預設值:2097144即2M)
sort_buffer_size=4M
sort_buffer_size是MySql執行排序使用的緩衝大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試增加sort_buffer_size變數的大小
4.2.2.3: read_rnd_buffer_size(預設值:8388608即8M)
read_rnd_buffer_size=8M
read_rnd_buffer_size 是MySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀快取區。進行排序查詢時,MySql會首先掃描一遍該緩衝,以避免磁碟搜尋,提高查詢速度,如果需要排序大量資料,可適當調高該值。但MySql會為每個客戶連線發放該緩衝空間,所以應儘量適當設定該值,以避免記憶體開
銷過大。
4.2.2.4: tmp_table_size(預設值:8388608 即:16M)
tmp_table_size=16M
tmp_table_size是MySql的heap (堆積)表緩衝大小。所有聯合在一個DML指令內完成,並且大多數聯合甚至可以不用臨時表即可以完成。大多數臨時表是基於內
存的(HEAP)表。具有大的記錄長度的臨時表 (所有列的長度的和)或包含BLOB列的表儲存在硬碟上。如果某個內部heap(堆積)表大小超過tmp_table_size,MySQL可以根據需要自
動將記憶體中的heap表改為基於硬碟的MyISAM表。還可以通過設定tmp_table_size選項來增加臨時表的大小。也就是說,如果調高該值,MySql同時將增加heap表的大小,可達到提高
聯接查詢速度的效果。
4.2.2.5:record_buffer:(預設值:)
record_buffer每個進行一個順序掃描的執行緒為其掃描的每張表分配這個大小的一個緩衝區。如果你做很多順序掃描,你可能想要增加該值。預設數值是131072
(128K)
4.2.3其它快取:
4.2.3.1:table_cache(預設值:512)
TABLE_CACHE(5.1.3及以後版本又名TABLE_OPEN_CACHE)
table_cache指定表快取記憶體的大小。每當MySQL訪問一個表時,如果在表緩衝區中還有空間,該表就被開啟並放入其中,這樣可以更快地訪問表內容。通過檢查峰值時間的狀態值Open_tables和Opened_tables,可以決定是否需要增加table_cache的值。如果你發現open_tables等於table_cache,並且opened_tables在不斷增長,那麼你就需要增加table_cache的值了(上述狀態值可以使用SHOW STATUS LIKE ‘Open%tables’獲得)。注意,不能盲目地把table_cache設定成很大的值。如果設定得太高,可能會造成檔案描述符不足,從而造成效能不穩定或者連線失敗。
SHOW STATUS LIKE ‘Open%tables’;
±--------------±------+
| Variable_name | Value |
±--------------±------+
| Open_tables | 356 |
| Opened_tables | 0 |
±--------------±------+
2 rows in set (0.00 sec)
open_tables表示當前開啟的表快取數,如果執行flush tables操作,則此係統會關閉一些當前沒有使用的表快取而使得此狀態值減小;
opend_tables表示曾經開啟的表快取數,會一直進行累加,如果執行flush tables操作,值不會減小。
在mysql預設安裝情況下,table_cache的值在2G記憶體以下的機器中的值預設時256到512,如果機器有4G記憶體,則預設這個值 是2048,但這決意味著機器記憶體越大,這個值應該越大,因為table_cache加大後,使得mysql對SQL響應的速度更快了,不可避免的會產生 更多的死鎖(dead lock),這樣反而使得資料庫整個一套操作慢了下來,嚴重影響效能。所以平時維護中還是要根據庫的實際情況去作出判斷,找到最適合你維護的庫的 table_cache值。
由於MySQL是多執行緒的機制,為了提高效能,每個執行緒都是獨自開啟自己需要的表的檔案描 述符,而不是通過共享已經開啟的.針對不同儲存引擎處理的方法當然也不一樣
在myisam表引擎中,資料檔案的描述符 (descriptor)是不共享的,但是索引檔案的描述符卻是所有執行緒共享的.Innodb中和使用表空間型別有關,假如是共享表空間那麼實際就一個數 據檔案,當然佔用的資料檔案描述符就會比獨立表空間少.
mysql手冊上給的建議大小 是:table_cache=max_connections*n
n表示查詢語句中最大表數, 還需要為臨時表和檔案保留一些額外的檔案描述符。
這個資料遭到很多質疑,table_cache夠用就好,檢查 Opened_tables值,如果這個值很大,或增長很快那麼你就得考慮加大table_cache了.
table_cache:所有執行緒開啟的表的數目。增大該值可以增加mysqld需要的檔案描述符的數量。預設值是64.
4.2.3.2 thread_cache_size (伺服器執行緒快取)
thread_cache_size=64
預設的thread_cache_size=8,但是看到好多配置的樣例裡的值一般是32,64,甚至是128,感覺這個引數對優化應該有幫助,於是查了下:
根據調查發現以上伺服器執行緒快取thread_cache_size沒有進行設定,或者設定過小,這個值表示可以重新利用儲存在快取中執行緒的數量,當斷開連線時如果快取中還有空間,那麼客戶端的執行緒將被放到快取中,如果執行緒重新被請求,那麼請求將從快取中讀取,如果快取中是空的或者是新的請求,那麼這個執行緒將被重新建立,如果有很多新的執行緒,增加這個值可以改善系統效能.通過比較 Connections 和 Threads_created 狀態的變數,可以看到這個變數的作用。(–>表示要調整的值) 根據實體記憶體設定規則如下:
1G —> 8
2G —> 16
3G —> 32 >3G —> 64
mysql> show status like ‘thread%’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 0 | <—當前被快取的空閒執行緒的數量
| Threads_connected | 1 | <—正在使用(處於連線狀態)的執行緒
| Threads_created | 1498 | <—服務啟動以來,建立了多少個執行緒
| Threads_running | 1 | <—正在忙的執行緒(正在查詢資料,傳輸資料等等操作)
+——————-+——-+
檢視開機起來資料庫被連線了多少次?
mysql> show status like ‘%connection%’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Connections | 1504 | –>服務啟動以來,歷史連線數
| Max_used_connections | 2 |
+———————-+——-+
通過連線執行緒池的命中率來判斷設定值是否合適?命中率超過90%以上,設定合理。
(Connections - Threads_created) / Connections * 100 %
二、 從系統層面增強mysql的效能:優化資料表結構、欄位型別、欄位索引、分表,分庫、讀寫分離等等
表結構:資料型別選擇;字元編碼;適當拆分;適度冗餘;儘量使用 NOT NULL 詳細, 讀寫分離
表結構的優化:
https://www.cnblogs.com/eeds-wangwei/p/8135771.html
由於MySQL資料庫是基於行(Row)儲存的資料庫,而資料庫操作 IO 的時候是以 page(block)的方式,也就是說,如果我們每條記錄所佔用的空間量減小,就會使每個page中可存放的資料行數增大,那麼每次 IO 可訪問的行數也就增多了。反過來說,處理相同行數的資料,需要訪問的 page 就會減少,也就是 IO 操作次數降低,直接提升效能。此外,由於我們的記憶體是有限的,增加每個page中存放的資料行數,就等於增加每個記憶體塊的快取資料量,同時還會提升記憶體換中資料命中的機率,也就是快取命中率。
一、資料型別選擇
資料庫操作中最為耗時的操作就是 IO 處理,大部分資料庫操作 90% 以上的時間都花在了 IO 讀寫上面。所以儘可能減少 IO 讀寫量,可以在很大程度上提高資料庫操作的效能。
我們無法改變資料庫中需要儲存的資料,但是我們可以在這些資料的儲存方式方面花一些心思。下面的這些關於欄位型別的優化建議主要適用於記錄條數較多,資料量較大的場景,因為精細化的資料型別設定可能帶來維護成本的提高,過度優化也可能會帶來其他的問題:
1.數字型別:非萬不得已不要使用DOUBLE,不僅僅只是儲存長度的問題,同時還會存在精確性的問題。同樣,固定精度的小數,也不建議使用DECIMAL,建議乘以固定倍數轉換成整數儲存,可以大大節省儲存空間,且不會帶來任何附加維護成本。對於整數的儲存,在資料量較大的情況下,建議區分開 TINYINT / INT / BIGINT 的選擇,因為三者所佔用的儲存空間也有很大的差別,能確定不會使用負數的欄位,建議新增unsigned定義。當然,如果資料量較小的資料庫,也可以不用嚴格區分三個整數型別。
2.字元型別:非萬不得已不要使用 TEXT 資料型別,其處理方式決定了他的效能要低於char或者是varchar型別的處理。定長欄位,建議使用 CHAR 型別,不定長欄位儘量使用 VARCHAR,且僅僅設定適當的最大長度,而不是非常隨意的給一個很大的最大長度限定,因為不同的長度範圍,MySQL也會有不一樣的儲存處理。
3.時間型別:儘量使用TIMESTAMP型別,因為其儲存空間只需要 DATETIME 型別的一半。對於只需要精確到某一天的資料型別,建議使用DATE型別,因為他的儲存空間只需要3個位元組,比TIMESTAMP還少。不建議通過INT型別類儲存一個unix timestamp 的值,因為這太不直觀,會給維護帶來不必要的麻煩,同時還不會帶來任何好處。
4.ENUM & SET:對於狀態欄位,可以嘗試使用 ENUM 來存放,因為可以極大的降低儲存空間,而且即使需要增加新的型別,只要增加於末尾,修改結構也不需要重建表資料。如果是存放可預先定義的屬性資料呢?可以嘗試使用SET型別,即使存在多種屬性,同樣可以遊刃有餘,同時還可以節省不小的儲存空間。
5.LOB型別:強烈反對在資料庫中存放 LOB 型別資料,雖然資料庫提供了這樣的功能,但這不是他所擅長的,我們更應該讓合適的工具做他擅長的事情,才能將其發揮到極致。在資料庫中儲存 LOB 資料就像讓一個多年前在學校學過一點Java的營銷專業人員來寫 Java 程式碼一樣。
二、字元編碼
字符集直接決定了資料在MySQL中的儲存編碼方式,由於同樣的內容使用不同字符集表示所佔用的空間大小會有較大的差異,所以通過使用合適的字符集,可以幫助我們儘可能減少資料量,進而減少IO操作次數。
1.純拉丁字元能表示的內容,沒必要選擇 latin1 之外的其他字元編碼,因為這會節省大量的儲存空間。
2.如果我們可以確定不需要存放多種語言,就沒必要非得使用UTF8或者其他UNICODE字元型別,這回造成大量的儲存空間浪費。
3.MySQL的資料型別可以精確到欄位,所以當我們需要大型資料庫中存放多位元組資料的時候,可以通過對不同表不同欄位使用不同的資料型別來較大程度減小資料儲存量,進而降低 IO 操作次數並提高快取命中率。
三、適當拆分
有些時候,我們可能會希望將一個完整的物件對應於一張資料庫表,這對於應用程式開發來說是很有好的,但是有些時候可能會在效能上帶來較大的問題。
當我們的表中存在類似於 TEXT 或者是很大的 VARCHAR型別的大欄位的時候,如果我們大部分訪問這張表的時候都不需要這個欄位,我們就該義無反顧的將其拆分到另外的獨立表中,以減少常用資料所佔用的儲存空間。這樣做的一個明顯好處就是每個資料塊中可以儲存的資料條數可以大大增加,既減少物理 IO 次數,也能大大提高記憶體中的快取命中率。
上面幾點的優化都是為了減少每條記錄的儲存空間大小,讓每個資料庫中能夠儲存更多的記錄條數,以達到減少 IO 操作次數,提高快取命中率。下面這個優化建議可能很多開發人員都會覺得不太理解,因為這是典型的反正規化設計,而且也和上面的幾點優化建議的目標相違背。
四、適度冗餘
為什麼我們要冗餘?這不是增加了每條資料的大小,減少了每個資料塊可存放記錄條數嗎?
確實,這樣做是會增大每條記錄的大小,降低每條記錄中可存放資料的條數,但是在有些場景下我們仍然還是不得不這樣做:
1.被頻繁引用且只能通過 Join 2張(或者更多)大表的方式才能得到的獨立小欄位。
2.這樣的場景由於每次Join僅僅只是為了取得某個小欄位的值,Join到的記錄又大,會造成大量不必要的 IO,完全可以通過空間換取時間的方式來優化。不過,冗餘的同時需要確保資料的一致性不會遭到破壞,確保更新的同時冗餘欄位也被更新。
五、儘量使用 NOT NULL
NULL 型別比較特殊,SQL 難優化。雖然 MySQL NULL型別和 Oracle 的NULL 有差異,會進入索引中,但如果是一個組合索引,那麼這個NULL 型別的欄位會極大影響整個索引的效率。此外,NULL 在索引中的處理也是特殊的,也會佔用額外的存放空間。
很多人覺得 NULL 會節省一些空間,所以儘量讓NULL來達到節省IO的目的,但是大部分時候這會適得其反,雖然空間上可能確實有一定節省,倒是帶來了很多其他的優化問題,不但沒有將IO量省下來,反而加大了SQL的IO量。所以儘量確保 DEFAULT 值不是 NULL,也是一個很好的表結構設計優化習慣。
主從配置 讀寫分離
https://www.cnblogs.com/luckcs/articles/2543607.html
MySQL主從複製(Master-Slave)與讀寫分離(MySQL-Proxy)實踐
Mysql作為目前世界上使用最廣泛的免費資料庫,相信所有從事系統運維的工程師都一定接觸過。但在實際的生產環境中,由單臺Mysql作為獨立的資料庫是完全不能滿足實際需求的,無論是在安全性,高可用性以及高併發等各個方面。
因此,一般來說都是通過 主從複製(Master-Slave)的方式來同步資料,再通過讀寫分離(MySQL-Proxy)來提升資料庫的併發負載能力 這樣的方案來進行部署與實施的。
如下圖所示:
下面是我在實際工作過程中所整理的筆記,在此分享出來,以供大家參考。
一、MySQL的安裝與配置
具體的安裝過程,建議參考我的這一篇文章:http://heylinux.com/archives/993.html
值得一提的是,我的安裝過程都是原始碼包編譯安裝的,並且所有的配置與資料等都統一規劃到了/opt/mysql目錄中,因此在一臺伺服器上安裝完成以後,可以將整個mysql目錄打包,然後傳到其它伺服器上解包,便可立即使用。
二、MySQL主從複製
場景描述:
主資料庫伺服器:192.168.10.130,MySQL已經安裝,並且無應用資料。
從資料庫伺服器:192.168.10.131,MySQL已經安裝,並且無應用資料。
2.1 主伺服器上進行的操作
啟動mysql服務
/opt/mysql/init.d/mysql start
通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
授權給從資料庫伺服器192.168.10.131
mysql> GRANT REPLICATION SLAVE ON . to ‘rep1’@‘192.168.10.131’ identified by ‘password’;
查詢主資料庫狀態
Mysql> show master status;
±-----------------±---------±-------------±-----------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
±-----------------±---------±-------------±-----------------+
| mysql-bin.000005 | 261 | | |
±-----------------±---------±-------------±-----------------+
記錄下 FILE 及 Position 的值,在後面進行從伺服器操作的時候需要用到。
2.2 配置從伺服器
修改從伺服器的配置檔案/opt/mysql/etc/my.cnf
將 server-id = 1修改為 server-id = 10,並確保這個ID沒有被別的MySQL服務所使用。
啟動mysql服務
/opt/mysql/init.d/mysql start
通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
執行同步SQL語句
mysql> change master to
master_host=’192.168.10.130’,
master_user=’rep1’,
master_password=’password’,
master_log_file=’mysql-bin.000005’,
master_log_pos=261;
正確執行後啟動Slave同步程式
mysql> start slave;
主從同步檢查
mysql> show slave status\G
**************** 1. row *******************
Slave_IO_State:
Master_Host: 192.168.10.130
Master_User: rep1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 415
Relay_Log_File: localhost-relay-bin.000008
Relay_Log_Pos: 561
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: YES
Slave_SQL_Running: YES
Replicate_Do_DB:
……………省略若干……………
Master_Server_Id: 1
1 row in set (0.01 sec)
其中Slave_IO_Running 與 Slave_SQL_Running 的值都必須為YES,才表明狀態正常。
如果主伺服器已經存在應用資料,則在進行主從複製時,需要做以下處理:
(1)主資料庫進行鎖表操作,不讓資料再進行寫入動作
mysql> FLUSH TABLES WITH READ LOCK;
(2)檢視主資料庫狀態
mysql> show master status;
(3)記錄下 FILE 及 Position 的值。
將主伺服器的資料檔案(整個/opt/mysql/data目錄)複製到從伺服器,建議通過tar歸檔壓縮後再傳到從伺服器解壓。
(4)取消主資料庫鎖定
mysql> UNLOCK TABLES;
2.3 驗證主從複製效果
主伺服器上的操作
在主伺服器上建立資料庫first_db
mysql> create database first_db;
Query Ok, 1 row affected (0.01 sec)
在主伺服器上建立表first_tb
mysql> create table first_tb(id int(3),name char(10));
Query Ok, 1 row affected (0.00 sec)
在主伺服器上的表first_tb中插入記錄
mysql> insert into first_tb values (001,’myself’);
Query Ok, 1 row affected (0.00 sec)
在從伺服器上檢視
mysql> show databases;
±-------------------+
| Database |
±-------------------+
| information_schema |
| first_db |
| mysql |
| performance_schema |
| test |
±-------------------+
5 rows in set (0.01 sec)
資料庫first_db已經自動生成
mysql> use first_db
Database chaged
mysql> show tables;
±-------------------+
| Tables_in_first_db |
±-------------------+
| first_tb |
±-------------------+
1 row in set (0.02 sec)
資料庫表first_tb也已經自動建立
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
1 rows in set (0.00 sec)
記錄也已經存在
由此,整個MySQL主從複製的過程就完成了,接下來,我們進行MySQL讀寫分離的安裝與配置。
三、MySQL讀寫分離
場景描述:
資料庫Master主伺服器:192.168.10.130
資料庫Slave從伺服器:192.168.10.131
MySQL-Proxy排程伺服器:192.168.10.132
以下操作,均是在192.168.10.132即MySQL-Proxy排程伺服器 上進行的。
3.1 MySQL的安裝與配置
具體的安裝過程與上文相同。
3.2 檢查系統所需軟體包
通過 rpm -qa | grep name 的方式驗證以下軟體包是否已全部安裝。
gcc* gcc-c++* autoconf* automake* zlib* libxml* ncurses-devel* libmcrypt* libtool* flex* pkgconfig*
libevent* glib*
若缺少相關的軟體包,可通過yum -y install方式線上安裝,或直接從系統安裝光碟中找到並通過rpm -ivh方式安裝。
3.3 編譯安裝lua
MySQL-Proxy的讀寫分離主要是通過rw-splitting.lua指令碼實現的,因此需要安裝lua。
lua可通過以下方式獲得
從http://www.lua.org/download.html下載原始碼包
從rpm.pbone.net搜尋相關的rpm包
download.fedora.redhat.com/pub/fedora/epel/5/i386/lua-5.1.4-4.el5.i386.rpm
download.fedora.redhat.com/pub/fedora/epel/5/x86_64/lua-5.1.4-4.el5.x86_64.rpm
這裡我們建議採用原始碼包進行安裝
cd /opt/install
wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
tar zvfx lua-5.1.4.tar.gz
cd lua-5.1.4
vi src/Makefile
在 CFLAGS= -O2 -Wall
(MYCFLAGS)這一行記錄里加上−fPIC,更改為CFLAGS=−O2−Wall−fPIC
(MYCFLAGS)這一行記錄里加上−fPIC,更改為CFLAGS=−O2−Wall−fPIC
(MYCFLAGS) 來避免編譯過程中出現錯誤。
make linux
make install
cp etc/lua.pc /usr/lib/pkgconfig/
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig
3.4 安裝配置MySQL-Proxy
MySQL-Proxy可通過以下網址獲得:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/
推薦採用已經編譯好的二進位制版本,因為採用原始碼包進行編譯時,最新版的MySQL-Proxy對automake,glib以及libevent的版本都有很高的要求,而這些軟體包都是系統的基礎套件,不建議強行進行更新。
並且這些已經編譯好的二進位制版本在解壓後都在統一的目錄內,因此建議選擇以下版本:
32位RHEL5平臺:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
64位RHEL5平臺:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-64bit.tar.gz
測試平臺為RHEL5 32位,因此選擇32位的軟體包
wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
tar xzvf mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
mv mysql-proxy-0.8.1-linux-rhel5-x86-32bit /opt/mysql-proxy
建立mysql-proxy服務管理指令碼
mkdir /opt/mysql-proxy/init.d/
vim mysql-proxy
01
#!/bin/sh
02
03
mysql-proxy This script starts and stops the mysql-proxy daemon
04
05
chkconfig: - 78 30
06
processname: mysql-proxy
07
description: mysql-proxy is a proxy daemon to mysql
08
09
Source function library.
10
. /etc/rc.d/init.d/functions
11
12
#PROXY_PATH=/usr/local/bin
13
PROXY_PATH=/opt/mysql-proxy/bin
14
15
prog=“mysql-proxy”
16
17
Source networking configuration.
18
. /etc/sysconfig/network
19
20
Check that networking is up.
21
[ ${NETWORKING} = “no” ] && exit 0
22
23
Set default mysql-proxy configuration.
24
#PROXY_OPTIONS="–daemon"
25
PROXY_OPTIONS="–admin-username=root --admin-password=password --proxy-read-only-backend-addresses=192.168.10.131:3306 --proxy-backend-addresses=192.168.10.130:3306 --admin-lua-script=/opt/mysql-proxy/lib/mysql-proxy/lua/admin.lua --proxy-lua-script=/opt/mysql-proxy/scripts/rw-splitting.lua"
26
PROXY_PID=/opt/mysql-proxy/run/mysql-proxy.pid
27
28
Source mysql-proxy configuration.
29
if [ -f /etc/sysconfig/mysql-proxy ]; then
30
. /etc/sysconfig/mysql-proxy
31
fi
32
33
PATH=
P
A
T
H
:
/
u
s
r
/
b
i
n
:
/
u
s
r
/
l
o
c
a
l
/
b
i
n
:
PATH:/usr/bin:/usr/local/bin:
PATH:/usr/bin:/usr/local/bin:PROXY_PATH
34
35
By default it’s all good
36
RETVAL=0
37
38
See how we were called.
39
case “$1” in
40
start)
41
# Start daemon.
42
echo -n $"Starting $prog: "
43
NICELEVEL
NICELEVEL
PROXY_PATH/mysql-proxy
P
R
O
X
Y
O
P
T
I
O
N
S
−
−
d
a
e
m
o
n
−
−
p
i
d
−
f
i
l
e
=
PROXY_OPTIONS --daemon --pid-file=
PROXYOPTIONS−−daemon−−pid−file=PROXY_PID --user=mysql --log-level=warning --log-file=/opt/mysql-proxy/log/mysql-proxy.log
44
RETVAL=$?
45
echo
46
if [ $RETVAL = 0 ]; then
47
touch /var/lock/subsys/mysql-proxy
48
fi
49
;;
50
stop)
51
# Stop daemons.
52
echo -n $"Stopping $prog: "
53
killproc
p
r
o
g
54
R
E
T
V
A
L
=
prog 54 RETVAL=
prog54RETVAL=?
55
echo
56
if [ $RETVAL = 0 ]; then
57
rm -f /var/lock/subsys/mysql-proxy
58
rm -f $PROXY_PID
59
fi
60
;;
61
restart)
62
$0 stop
63
sleep 3
64
$0 start
65
;;
66
condrestart)
67
[ -e /var/lock/subsys/mysql-proxy ] &&
0
r
e
s
t
a
r
t
68
;
;
69
s
t
a
t
u
s
)
70
s
t
a
t
u
s
m
y
s
q
l
−
p
r
o
x
y
71
R
E
T
V
A
L
=
0 restart 68 ;; 69 status) 70 status mysql-proxy 71 RETVAL=
0restart68;;69status)70statusmysql−proxy71RETVAL=?
72
;;
73
*)
74
echo “Usage: $0 {start|stop|restart|status|condrestart}”
75
RETVAL=1
76
;;
77
esac
78
79
exit $RETVAL
指令碼引數詳解:
PROXY_PATH=/opt/mysql-proxy/bin //定義mysql-proxy服務二進位制檔案路徑
PROXY_OPTIONS="–admin-username=root \ //定義內部管理伺服器賬號
–admin-password=password \ //定義內部管理伺服器密碼
–proxy-read-only-backend-addresses=192.168.10.131:3306 \ //定義後端只讀從伺服器地址
–proxy-backend-addresses=192.168.10.130:3306 \ //定義後端主伺服器地址
–admin-lua-script=/opt/mysql-proxy/lib/mysql-proxy/lua/admin.lua \ //定義lua管理指令碼路徑
–proxy-lua-script=/opt/mysql-proxy/scripts/rw-splitting.lua" \ //定義lua讀寫分離指令碼路徑
PROXY_PID=/opt/mysql-proxy/run/mysql-proxy.pid //定義mysql-proxy PID檔案路徑
NICELEVEL
NICELEVEL
PROXY_PATH/mysql-proxy
PROX
Y
O
PTIONS −−daemon //定義以守護程式模式啟動−−keepalive //使程式在異常關閉後能夠自動恢復−−pid−file=
PROXYOPTIONS −−daemon //定義以守護程式模式啟動−−keepalive //使程式在異常關閉後能夠自動恢復−−pid−file=
PROXY_PID \ //定義mysql-proxy PID檔案路徑
–user=mysql \ //以mysql使用者身份啟動服務
–log-level=warning \ //定義log日誌級別,由高到低分別有(error|warning|info|message|debug)
–log-file=/opt/mysql-proxy/log/mysql-proxy.log //定義log日誌檔案路徑
cp mysql-proxy /opt/mysql-proxy/init.d/
chmod +x /opt/mysql-proxy/init.d/mysql-proxy
mkdir /opt/mysql-proxy/run
mkdir /opt/mysql-proxy/log
mkdir /opt/mysql-proxy/scripts
配置並使用rw-splitting.lua讀寫分離指令碼
最新的指令碼我們可以從最新的mysql-proxy原始碼包中獲取
cd /opt/install
wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1.tar.gz
tar xzvf mysql-proxy-0.8.1.tar.gz
cd mysql-proxy-0.8.1
cp lib/rw-splitting.lua /opt/mysql-proxy/scripts
修改讀寫分離指令碼rw-splitting.lua
修改預設連線,進行快速測試,不修改的話要達到連線數為4時才啟用讀寫分離
vim /opt/mysql-proxy/scripts/rw-splitting.lua
– connection pool
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1, //預設為4
max_idle_connections = 1, //預設為8
is_debug = false
}
end
修改完成後,啟動mysql-proxy
/opt/mysql-proxy/init.d/mysql-proxy start
3.5 測試讀寫分離效果
建立用於讀寫分離的資料庫連線使用者
登陸主資料庫伺服器192.168.10.130,通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
mysql> GRANT ALL ON . TO ‘proxy1’@‘192.168.10.132’ IDENTIFIED BY ‘password’;
由於我們配置了主從複製功能,因此從資料庫伺服器192.168.10.131上已經同步了此操作。
為了清晰的看到讀寫分離的效果,需要暫時關閉MySQL主從複製功能
登陸從資料庫伺服器192.168.10.131,通過命令列登入管理MySQL伺服器
/opt/mysql/bin/mysql -uroot -p’new-password’
關閉Slave同步程式
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
連線MySQL-Proxy
/opt/mysql/bin/mysql -uproxy1 -p’password’ -P4040 -h192.168.10.132
登陸成功後,在first_db資料的first_tb表中插入兩條記錄
mysql> use first_db;
Database changed
mysql> insert into first_tb values (007,’first’);
Query Ok, 1 row affected (0.00 sec)
mysql> insert into first_tb values (110,’second’);
Query Ok, 1 row affected (0.00 sec)
查詢記錄
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
1 rows in set (0.00 sec)
通過讀操作並沒有看到新記錄
mysql> quit
退出MySQL-Proxy
下面,分別登陸到主從資料庫伺服器,對比記錄資訊
首先,檢查主資料庫伺服器
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
| 007 | first |
±-----±-----+
| 110 | second |
±-----±-----+
3 rows in set (0.00 sec)
兩條新記錄都已經存在
然後,檢查從資料庫伺服器
mysql> select * from first_tb;
±-----±-----+
| id | name |
±-----±-----+
| 1 | myself |
±-----±-----+
1 rows in set (0.00 sec)
沒有新記錄存在
由此驗證,我們已經實現了MySQL讀寫分離,目前所有的寫操作都全部在Master主伺服器上,用來避免資料的不同步;
另外,所有的讀操作都分攤給了其它各個Slave從伺服器上,用來分擔資料庫壓力。
經驗分享:
1.當MySQL主從複製在 show slave status\G 時出現Slave_IO_Running或Slave_SQL_Running 的值不為YES時,需要首先通過 stop slave 來停止從伺服器,然後再執行一次本文 2.1與2.2 章節中的步驟即可恢復,但如果想盡可能的同步更多的資料,可以在Slave上將master_log_pos節點的值在之前同步失效的值的基礎上增大一些,然後反覆測試,直到同步OK。因為MySQL主從複製的原理其實就是從伺服器讀取主伺服器的binlog,然後根據binlog的記錄來更新資料庫。
2.MySQL-Proxy的rw-splitting.lua指令碼在網上有很多版本,但是最準確無誤的版本仍然是原始碼包中所附帶的lib/rw-splitting.lua指令碼,如果有lua指令碼程式設計基礎的話,可以在這個指令碼的基礎上再進行優化;
3.MySQL-Proxy實際上非常不穩定,在高併發或有錯誤連線的情況下,程式很容易自動關閉,因此開啟–keepalive引數讓程式自動恢復是個比較好的辦法,但還是不能從根本上解決問題,因此通常最穩妥的做法是在每個從伺服器上安裝一個MySQL-Proxy供自身使用,雖然比較低效但卻能保證穩定性;
4.一主多從的架構並不是最好的架構,通常比較優的做法是通過程式程式碼和中介軟體等方面,來規劃,比如設定對錶資料的自增id值差異增長等方式來實現兩個或多個主伺服器,但一定要注意保證好這些主伺服器資料的完整性,否則效果會比多個一主多從的架構還要差;
5.MySQL-Cluster 的穩定性也不是太好;
6.Amoeba for MySQL 是一款優秀的中介軟體軟體,同樣可以實現讀寫分離,負載均衡等功能,並且穩定性要大大超過MySQL-Proxy,建議大家用來替代MySQL-Proxy,甚至MySQL-Cluster。
三、 從資料庫層面增強效能:優化SQL語句,合理使用欄位索引
四、 從程式碼層面增強效能:使用快取和NoSQL資料庫方式儲存,如MongoDB/Memcached/Redis來緩解高併發下資料庫查詢的壓力。
五、 減少資料庫操作次數,儘量使用資料庫訪問驅動的批處理方法。
六、 不常使用的資料遷移備份,避免每次都在海量資料中去檢索。
七、 提升資料庫伺服器硬體配置,或者搭建資料庫叢集。
八、 程式設計手段防止SQL隱碼攻擊:使用JDBC PreparedStatement按位插入或查詢;正規表示式過濾(非法字串過濾)
1.對查詢進行優化,要儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
最好不要給資料庫留NULL,儘可能的使用 NOT NULL填充資料庫.
備註、描述、評論之類的可以設定為 NULL,其他的,最好不要使用NULL。
不要以為 NULL 不需要空間,比如:char(100) 型,在欄位建立時,空間就固定了, 不管是否插入值(NULL也包含在內),都是佔用 100個字元的空間的,如果是varchar這樣的變長欄位, null 不佔用空間。
可以在num上設定預設值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num = 0
3.應儘量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。
4.應儘量避免在 where 子句中使用 or 來連線條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or Name = ‘admin’
可以這樣查詢:
select id from t where num = 10
union all
select id from t where Name = ‘admin’
5.in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
6.下面的查詢也將導致全表掃描:
select id from t where name like ‘%abc%’
若要提高效率,可以考慮全文檢索。
7.如果在 where 子句中使用引數,也會導致全表掃描。因為SQL只有在執行時才會解析區域性變數,但優化程式不能將訪問計劃的選擇推遲到執行時;它必須在編譯時進行選擇。然 而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num = @num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num = @num
.應儘量避免在 where 子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2 = 100
應改為:
select id from t where num = 100*2
9.應儘量避免在where子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3) = ’abc’ -–name以abc開頭的id
select id from t where datediff(day,createdate,’2005-11-30′) = 0 -–‘2005-11-30’ --生成的id
應改為:
select id from t where name like ‘abc%’
select id from t where createdate >= ‘2005-11-30’ and createdate < ‘2005-12-1’
10.不要在 where 子句中的“=”左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。
11.在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。
12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類程式碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(…)
13.Update 語句,如果只更改1、2個欄位,不要Update全部欄位,否則頻繁呼叫會引起明顯的效能消耗,同時帶來大量日誌。
14.對於多張大資料量(這裡幾百條就算大了)的表JOIN,要先分頁再JOIN,否則邏輯讀會很高,效能很差。
15.select count(*) from table;這樣不帶任何條件的count會引起全表掃描,並且沒有任何業務意義,是一定要杜絕的。
16.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。
17.應儘可能的避免更新 clustered 索引資料列,因為 clustered 索引資料列的順序就是表記錄的物理儲存順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引資料列,那麼需要考慮是否應將該索引建為 clustered 索引。
18.儘量使用數字型欄位,若只含數值資訊的欄位儘量不要設計為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連 接時會逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。
19.儘可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長欄位儲存空間小,可以節省儲存空間,其次對於查詢來說,在一個相對較小的欄位內搜尋效率顯然要高些。
20.任何地方都不要使用 select * from t ,用具體的欄位列表代替“*”,不要返回用不到的任何欄位。
21.儘量使用表變數來代替臨時表。如果表變數包含大量資料,請注意索引非常有限(只有主鍵索引)。
- 避免頻繁建立和刪除臨時表,以減少系統表資源的消耗。臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個資料集時。但是,對於一次性事件, 最好使用匯出表。
23.在新建臨時表時,如果一次性插入資料量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果資料量不大,為了緩和系統表的資源,應先create table,然後insert。
24.如果使用到了臨時表,在儲存過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。
25.儘量避免使用遊標,因為遊標的效率較差,如果遊標操作的資料超過1萬行,那麼就應該考慮改寫。
26.使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
27.與臨時表一樣,遊標並不是不可使用。對小型資料集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的資料時。在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時 間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的儲存過程和觸發器的開始處設定 SET NOCOUNT ON ,在結束時設定 SET NOCOUNT OFF 。無需在執行儲存過程和觸發器的每個語句後向客戶端傳送 DONE_IN_PROC 訊息。
29.儘量避免大事務操作,提高系統併發能力。
30.儘量避免向客戶端返回大資料量,若資料量過大,應該考慮相應需求是否合理。
實際案例分析:拆分大的 DELETE 或INSERT 語句,批量提交SQL語句
如果你需要在一個線上的網站上去執行一個大的 DELETE 或 INSERT 查詢,你需要非常小心,要避免你的操作讓你的整個網站停止相應。因為這兩個操作是會鎖表的,表一鎖住了,別的操作都進不來了。
Apache 會有很多的子程式或執行緒。所以,其工作起來相當有效率,而我們的伺服器也不希望有太多的子程式,執行緒和資料庫連結,這是極大的佔伺服器資源的事情,尤其是記憶體。
如果你把你的表鎖上一段時間,比如30秒鐘,那麼對於一個有很高訪問量的站點來說,這30秒所積累的訪問程式/執行緒,資料庫連結,開啟的檔案數,可能不僅僅會讓你的WEB服務崩潰,還可能會讓你的整臺伺服器馬上掛了。
所以,如果你有一個大的處理,你一定把其拆分,使用 LIMIT oracle(rownum),sqlserver(top)條件是一個好的方法。下面是一個mysql示例:
spring的4種事務特性,5種隔離級別,7種傳播行為?
spring事務:
什麼是事務:
事務邏輯上的一組操作,組成這組操作的各個邏輯單元,要麼一起成功,要麼一起失敗.
事務特性(4種):
原子性 (atomicity):強調事務的不可分割.
一致性 (consistency):事務的執行的前後資料的完整性保持一致.
隔離性 (isolation):一個事務執行的過程中,不應該受到其他事務的干擾
永續性(durability) :事務一旦結束,資料就持久到資料庫
如果不考慮隔離性引發安全性問題:
髒讀 :一個事務讀到了另一個事務的未提交的資料
不可重複讀 :一個事務讀到了另一個事務已經提交的 update 的資料導致多次查詢結果不一致.
虛幻讀 :一個事務讀到了另一個事務已經提交的 insert 的資料導致多次查詢結果不一致.
解決讀問題: 設定事務隔離級別(5種)
DEFAULT 這是一個PlatfromTransactionManager預設的隔離級別,使用資料庫預設的事務隔離級別.
未提交讀 (read uncommited) :髒讀,不可重複讀,虛讀都有可能發生
已提交讀 (read commited):避免髒讀。但是不可重複讀和虛讀有可能發生
可重複讀 (repeatable read) :避免髒讀和不可重複讀.但是虛讀有可能發生.
序列化的 (serializable) :避免以上所有讀問題.
Mysql 預設:可重複讀
Oracle 預設:讀已提交
read uncommited:是最低的事務隔離級別,它允許另外一個事務可以看到這個事務未提交的資料。
read commited:保證一個事物提交後才能被另外一個事務讀取。另外一個事務不能讀取該事物未提交的資料。
repeatable read:這種事務隔離級別可以防止髒讀,不可重複讀。但是可能會出現幻象讀。它除了保證一個事務不能被另外一個事務讀取未提交的資料之外還避免了以下情況產生(不可重複讀)。
serializable:這是花費最高代價但最可靠的事務隔離級別。事務被處理為順序執行。除了防止髒讀,不可重複讀之外,還避免了幻象讀(避免三種)。
事務的傳播行為: 7種
propagion_XXX :事務的傳播行為
*保證同一個事務中
propagion_required: 支援當前事務,如果不存在 就新建一個(預設)
propagion_supports: 支援當前事務,如果不存在,就不使用事務
propagion_mandatory: 支援當前事務,如果不存在,丟擲異常
*保證沒有在同一個事務中
propagion_requires_new: 如果有事務存在,掛起當前事務,建立一個新的事務
propagion_not_supported: 以非事務方式執行,如果有事務存在,掛起當前事務
propagion_never: 以非事務方式執行,如果有事務存在,丟擲異常
propagion_nested: 如果當前事務存在,則巢狀事務執行
分散式事務怎麼解決的,底層原理,以及具體的業務場景
概述:
簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的伺服器上,且屬於不同的應用,
分散式事務需要保證這些小操作要麼全部成功,要麼全部失敗。
分散式事務底層原理:
分散式事務框架本身並不建立事務,只是將同一個業務邏輯的多個事務進行統一管理,從而達到事務的一致性.
核心步驟:
1、建立事務組
事務發起方在一開始就呼叫框架建立事務組,然後拿到groupId
2、新增事務至事務組
當一個模組執行完後,將事務結果新增至事務組
3、關閉事務組
當最後一個模組提交完後,事務組對結果進行判斷,分別通知所有模組最終的事務結果(提交或回滾)
分散式事務的應用場景:
事務必須滿足傳統事務的特性,即原子性,一致性,分離性和永續性。但是分散式事務處理過程中,
1. 當資料庫單表一年產生的資料超過1000W,那麼就要考慮分庫分表,具體分庫分表的原理在此不做解釋,以後有空詳細說,
簡單的說就是原來的一個資料庫變成了多個資料庫。這時候,如果一個操作既訪問01庫,又訪問02庫,而且要保證資料的一致性,那麼就要用到分散式事務。
2. 所謂的SOA化,就是業務的服務化。比如原來單機支撐了整個電商網站,現在對整個網站進行拆解,分離出了訂單中心、使用者中心、
庫存中心。對於訂單中心,有 專門的資料庫儲存訂單資訊,使用者中心也有專門的資料庫儲存使用者資訊,庫存中心也會有專門的資料庫儲存庫存資訊。這時候如果要同時對訂單和庫存進行操作,那 麼就會涉及到訂單資料庫和庫存資料庫,為了保證資料一致性,就需要用到分散式事務。
另外還比如:
某些場地比如在電商系統中,當有使用者下單後,除了在訂單表插入一條記錄外,對應商品表的這個商品數量必須減1吧,怎麼保證?
在搜尋廣告系統中,當使用者點選某廣告後,除了在點選事件表中增加一條記錄外
事務的ACID特性
事務必須滿足傳統事務的特性,即原子性,一致性,分離性和永續性。
1. 所謂的原子性就是說,在整個事務中的所有操作,要麼全部完成,要麼全部不做,沒有中間狀態。對於事務在執行中發生錯誤,所有的操作都會被回滾,整個
事務就像從沒被執行過一樣。
2. 事務的執行必須保證系統的一致性,就拿轉賬為例,A有500元,B有300元,如果在一個事務裡A成功轉給B50元,那麼不管併發多少,不管發生什麼,只要事
務執行成功了,那麼最後A賬戶一定是450元,B賬戶一定是350元。
3. 所謂的隔離性就是說,事務與事務之間不會互相影響,一個事務的中間狀態不會被其他事務感知。
4. 所謂的永續性,就是說一單事務完成了,那麼事務對資料所做的變更就完全儲存在了資料庫中,即使發生停電,系統當機也是如此。
常見解決方案:
1. 基於XA協議的兩階段提交
分散式事務通常採用2PC協議,全稱Two Phase Commitment Protocol。該協議主要為了解決在分散式資料庫場景下,所有節點間資料一致性的問題。分散式事務通過2PC協議將提交分成兩個階段:
1. prepare;
2. commit/rollback
階段一為準備(prepare)階段。即所有的參與者準備執行事務並鎖住需要的資源。參與者ready時,向transaction manager報告已準備就緒。
階段二為提交階段(commit)。當transaction manager確認所有參與者都ready後,向所有參與者傳送commit命令。
2. 訊息事務+最終一致性
所謂的訊息事務就是基於訊息中介軟體的兩階段提交,本質上是對訊息中介軟體的一種特殊利用,它是將本地事務和發訊息放在了一個分散式事務裡,保證要麼本地操作成功成功並且對外發訊息成功,要麼兩者都失敗.
專案上線流程:
早/晚會彙報情況
基本每天早上或晚上都會開早會討論以下問題 昨天的內容,今天的計劃,需要解決的問題三個維度出發
1.開發組每個人講自己負責模組的專案情況。 (專案負責人小彙總)
2.各個測試組人員講述自己測試情況。(測試負責人小彙總)
3.如果所有的專案模組測試都Ok,開發組leader將專案整合到master上,開展迴歸測試,如果迴歸測試沒有問題就可以準備上線了。
迴歸測試流程:
1.配置引數和環境
2.迴歸主要的流程
3.將以前提的bug再次迴歸
4.迴歸主要的異常流程
注意:如果需要跟第三方系統聯測的情況,那麼程式碼整合到master時,需要設計測試用例場景覆蓋需求與第三方系統測試人員聯測。有時候在迴歸測試也會進行聯測。主要以正向流程為主,目的是檢查業務流程是否完整,介面是否聯通、資料是否正確等幾個方面。
4.上線前的準備
第一步:確定上線策略
1.上線順序 特別是微服務專案(具體看專案-多系統上線)
註冊中心---provider----consumer---zull.....
2.修復資料策略
如果功能上線後出現bug,應該怎麼處理?
一般我們會設定一個開關,當新功能一旦出現問題,將開關開啟,走原來的老流程。
第二步:寫上線申請郵件
上線之前,專案測試負責人要寫上線申請郵件,郵件內容包括有:
1.資料配置
有沒有開關?有就需要配置。
資料庫有沒有修改?有新增表,需要事先增表,有修改表結構,需要改表結構。
有沒有外部介面?有就需要配置介面URL,否則流程不能跑通,回撥也不能通。
等等,根據實際情況來寫。
2.上線注意點
可以寫本次專案上線後,會引起的風險,哪些地方可能容易出現問題?需不需要加上監控等?又或者上線之後,需要人為地去監控資料。
3.在郵件中寫清楚上線策略
(第一步中考慮到的上線策略)
第三步:配置線上環境資料
根據測試人員編寫的上線申請郵件,在上線之前線上上環境中配置好資料,根據郵件來配置,所以在編寫郵件的時候需要將配置寫全,這些配置可以根據開發人員提測時的轉測郵件來寫,或者測試過程中的補充配置,謹記配置要寫完整。
完全以上步驟之後,就可以擇良辰開始上線了,一般上線的許可權只有幾個人有,所以上線的人員是固定的,上程式碼時需要先將線上環境的job停掉,我們也是用jenkins進行自動化部署,只是需要人為的打版號、標籤,部署版本,停Djob任務,上線完全之後,啟動Djob任務等。
04
上線之後
對於測試人員來說,並不是你測試完全,專案上到線上(生產)環境上就OK了,就不關你的事了,而實則專案上線之後才是真正對測試人員的考驗,測試人員經常疑或為什麼總有一些BUG是線上上環境中才會被發現?
王豆豆總結了幾點:
1.線上環境資料的複雜度是測試環境不能比擬的。
2.業務操作的不可控性
3.實際場景的複雜性
基於以上三點,這也就是為什麼線上環境總是出現一些測試環境不能發現的BUG,排除測試人員漏測的情況。
故,上線之後,測試人員需要做好以下二件事:
第一,灰度測試
專案上線之後,首先是測試人員開始做灰度測試。
灰度測試時,可以設定由業務開關或者白名單之類做控制,只要少量資料或新增在白名單上的資料可以走新業務流程。
灰度測試完全之後,也就是將所有業務流程走完,檢查各項資料的正確性、流程是否通、流程是否完整等等檢查點。
確定無問題時,再將開關開啟,再開放少量真實使用者資料。
第二,監控線上資料
灰度測試時就已經在監控線上資料和檢查線上資料,但因為灰度測試時資料量比較少,有時並不足以引發新問題,所以測試人員需要繼續觀察線上資料。
測試人員需要在專案上線之後的幾個小時內,重點監控線上資料的流向,一旦資料有異常,立即採取措施,回滾程式碼又或者重新開啟開關等,儘量將線上bug引起的損失降到最低,接下來就開始修改bug和修復資料。
在這個時候,測試人員對資料的敏感性特別就要發揮出來,有時似錯非錯的資料正是BUG的前兆,千萬不要掉以輕心。
整個專案上線前後的流程就大致如此,不管是上線前的準備還是上線之後資料的觀察都是一環扣一環,這些步驟有息息相關,前面的準備工作做得足,那麼後面監控資料就會相對輕鬆,因為不容易出現問題。
系統A場景:
1、 上游10個系統,每日凌晨2:00跑批處理完成,每個系統會生成約50G(約500萬行)的文字資料檔案,以固定長度或豎線分割,其中每一個系統都有自己的介面規則;
2、 檔案要求傳輸到系統A,要求保證檔案傳輸過程的完整性、安全性;
3、 解析檔案,逐行校驗資料,將正確的資料入庫,錯誤的資料記錄入失敗庫;
4、 完成後,系統A統計正確的行數和錯誤的行數通知到每一個檔案對應的上游系統;
要求:
1、 對系統A進行比較充分的設計,在上述場景應當重點注意哪些環節?
1) 檔案傳輸過程中,可能會因為網路抖動丟包,甚至被人惡意篡改。需要傳送接收雙方制定檔案校驗規則,如總筆數、總金額校驗,對檔案進行簽名驗籤,加密傳輸等手段保證檔案完整;
2) 傳輸檔案可以用NFS、NAS等交換檔案,也可以用SFTP交換,為了保證檔案傳輸速度,可以對單個檔案拆分,多執行緒傳輸;
3) 檔案傳輸會大量消耗網路頻寬,需要提前對頻寬升級並進行壓力測試;
4) 所有檔案傳輸都需要嚴格的記錄,避免夾帶;
5) 檔案傳輸完成,解析檔案的時候要用buffer增量讀取(百度上有很多);
6) 適當增加JVM堆記憶體,並對GC進行調優,否則會因為堆記憶體過大GC不及時導致CPU暴漲當機;
7) 資料校驗如果邏輯複雜,需要對不同的校驗規則編寫不同的服務,加以抽象微服務化;
8) 資料入庫的方法有很多種,可以用dmp,可以用mybatis框架批量提交,批量提交的時候要注意效能,通過不斷的測試一定能找到效能最佳的點(1000行一批或者500行一批);
9) 長時間高頻讀寫資料庫,需要用到mysql讀寫分離;
10) 如果不考慮事務,可以用myisam引擎(innodb支援事務和myisam不支援事務 的區別自己百度);
11) MQ訊息佇列 (高併發請求);
12) Jconsole對JVM進行監控;
1、 每日超過5千萬行的資料處理,mysql應當如何優化?
1) mysql資料庫的橫向、縱向分庫、分割槽、分表;
2) 深入瞭解mycat;
2、 根據您的經驗充分設計,預估完成10個檔案處理需要多長時間?
1) 上下游伺服器、資料庫伺服器是否在同一個網段(同一個機房)?
2)
3、 上游系統可能會增加,介面規則可能會變動,如何設計保證其靈活性?
1) 首先將介面規則儲存下來(資料庫或檔案),如豎線分割,每一位是什麼資料型別,代表什麼;如定長,需要考慮ISO-8859-1轉碼,否則中文會錯位;
2) 抽象一個介面卡,讀取介面規則,將每一行資料文字繫結一個class,class實現的時候,通過反射getter、setter方法將每一個欄位的值讀取出來,生成一個一個物件(工廠模式);
4、 上述場景可能需要用到哪些設計模式?
1) 資料轉化為物件:工廠模式;
2) 檔案傳輸:觀察者模式
3) 介面卡:單例模式
5、 容錯和災備如何設計?
1) 資料重跑、斷點續傳;
2) MQ和分散式事務;
3) Redis鎖;
4) 檔案歸檔,資料備份
MYSQL需要準備:
https://www.jianshu.com/p/10a2381225cf(MySQL簡書第一章地址)
https://www.jianshu.com/p/10a2381225cf(二,MySQL體系結構和管理)
https://www.jianshu.com/p/f6413bf7f455(三,SQL基礎及後設資料獲取)
https://www.jianshu.com/p/31801e78885f(四,索引以及執行計劃管理)
https://www.jianshu.com/p/0b9b45e50a4f(五,儲存引擎innodb)
https://www.jianshu.com/p/b7f6675a8479(六,MySQL日誌管理)
https://www.jianshu.com/p/74fdb73c3af8(七,MySQL備份恢復)
相關文章
- 2020年的最新的Java面試題Java面試題
- 2020年最新整理-Java面試題大全Java面試題
- 【Java面試】Java基礎知識面試題—2020最新版!Java面試題
- JAVA最新面試題分享Java面試題
- MySQL資料庫面試題(2020最新版)MySql資料庫面試題
- 最新阿里Java面試題,這些面試題你會嗎?阿里Java面試題
- 最新精選Java面試題,附答案!Java面試題
- 杭州ZoomVideo iOS面試題OOMIDEiOS面試題
- Linux面試題(2020最新版)Linux面試題
- Java開發工程師最新面試題庫系列——集合部分(附答案)Java工程師面試題
- Spring Boot面試題(2020最新版)Spring Boot面試題
- HTML最新面試題(筆試面試題)HTML面試題筆試
- Java開發工程師最新面試題庫系列——Mybatis框架部分(附答案)Java工程師面試題MyBatis框架
- Java_資料庫面試題Java資料庫面試題
- Java面試專屬視訊 最新Java阿里京東美團滴滴面試題及答案教程Java阿里面試題
- 2018年最新Java面試題及答案Java面試題
- 2018最新《BAT Java必考面試題集》BATJava面試題
- Java高頻面試題(2023最新整理)Java面試題
- 面試題總結-最新面試題
- 常用JAVA面試題庫(附答案)一Java面試題
- 最新前端面試題攻略前端面試題
- 2019年最新Java面試題及答案整理(上)Java面試題
- JAVA程式設計師面試題庫分享Java程式設計師面試題
- 2021年Java面試題目最新總結【90%面試會踩的坑】Java面試題
- 微軟最新面試題10.30微軟面試題
- 2018年Java程式設計師最新BAT面試題Java程式設計師BAT面試題
- 面試題庫面試題
- 求職面試 跳槽漲薪?看完記住立漲3k ! 2020最新Java常見面試題合集+答案詳解(十二)求職Java面試題
- Java面試300題(2020年版,3-5年面試題重點突破)Java面試題
- Java面試題總結(基礎面試題完結版,2020-10-13)Java面試題
- java面試題Java面試題
- 2020年開春最新面試!今日頭條 Android 面試題及答案 (已拿到 offer)Android面試題
- 在杭州的iOS面試(二)iOS面試
- 【Java面試】Java常見IO面試題!Java面試題
- 【Java面試】Java設計模式面試題!Java設計模式面試題
- 2020年Go語言那些不得不看的最新面試題Go面試題
- 2020版拼多多和快手前端程式設計師最新面試題前端程式設計師面試題
- JAVA面試題 java部分Java面試題