因爲細節內容實在太多啦,因此只把部分知識點整理出來粗略的介紹,每一個小節點裏面都有更細化的內容!
接下來開始分享啦java
先後端分離:node
補充:spring
注:這個「倉庫」應該就是本地安裝maven的目錄下的Repository的文件夾
線程鎖:當某個方法或代碼使用鎖,在同一時刻僅有一個線程執行該方法或該代碼段。線程鎖只在同一JVM中有效,由於線程鎖的實如今根本上是依靠線程之間共享內存實現的。如synchronizedsql
進程鎖:爲了控制同一操做系統中多個進程訪問某個共享資源。數據庫
分佈式鎖:當多個進程不在同一個系統中,用分佈式鎖控制多個進程對資源的訪問。後端
分佈式鎖通常有三種實現方式:數組
樂觀鎖的實現:使用版本標識來肯定讀到的數據與提交時的數據是否一致。提交後修改版本標識,不一致時能夠採起丟棄和再次嘗試的策略。瀏覽器
分佈式鎖基於Redis的實現:(本系統鎖採用的)緩存
基本命令:安全
加鎖方式:
這裏的jedis是Java對Redis的集成
jedis.set(String key, String value, String nxxx, String expx, int time)
錯誤的加鎖方式1:
若是程序在執行完setnx()以後忽然崩潰,致使鎖沒有設置過時時間。那麼將會發生死鎖。
Long result = jedis.setnx(Key, value); if (result == 1) { // 若在這裏程序忽然崩潰,則沒法設置過時時間,將發生死鎖 jedis.expire(Key, expireTime); }
錯誤的加鎖方式2:
分佈式鎖採用(Key,過時時間)的方式,若是鎖存在,那麼獲取它的過時時間,若是鎖的確已通過期了,那麼得到鎖,而且設置新的過時時間
錯誤分析:不一樣的客戶端之間須要同步好時間。
//+V:BGM7756,免費領取資料long expires = System.currentTimeMillis() + expireTime; String expiresStr = String.valueOf(expires); // 若是當前鎖不存在,返回加鎖成功 if (jedis.setnx(lockKey, expiresStr) == 1) { return true; } // 若是鎖存在,獲取鎖的過時時間 String currentValueStr = jedis.get(lockKey); if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) { // 鎖已過時,獲取上一個鎖的過時時間,並設置如今鎖的過時時間 String oldValueStr = jedis.getSet(lockKey, expiresStr); if (oldValueStr != null && oldValueStr.equals(currentValueStr)) { // 考慮多線程併發的狀況,只有一個線程的設置值和當前值相同,它纔有權利加鎖 return true; } } // 其餘狀況,一概返回加鎖失敗 return false; //+V:BGM7756,免費領取資料
中場休息時間!最近整理了一份Java核心知識點。覆蓋了springboot、JVM、鎖、併發、Java反射、Spring原理、微服務、Zookeeper、數據庫、數據結構等大量知識點。
若是須要免費獲取到這個【資料】文檔的話添加微信:BGM7756
解鎖:判斷鎖的擁有者後可使用 jedis.del(lockKey) 來釋放鎖。
分佈式鎖基於Zookeeper的實現
Zookeeper簡介:Zookeeper提供一個多層級的節點命名空間(節點稱爲znode),每一個節點都用一個以斜槓(/)分隔的路徑表示,並且每一個節點都有父節點(根節點除外)。
例如,/foo/doo這個表示一個znode,它的父節點爲/foo,父父節點爲/,而/爲根節點沒有父節點。
client不論鏈接到哪一個Server,展現給它都是同一個視圖,這是zookeeper最重要的性能。
Zookeeper 的核心是原的廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫作Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步之後,恢復模式就結束了。狀態同步保證了leader和Server具備相同的系統狀態。
爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務,實現中zxid是一個64位的數字。
Zookeeper的分佈式鎖原理
獲取分佈式鎖的流程:
個人解釋:
A在Locker下建立了Node_n —>循環 ( 每次獲取Locker下的全部子節點 —> 對這些節點按節點自增號排序順序 —> 判斷本身建立的Node_n是不是第一個節點 —> 若是是則得到了分佈式鎖 —> 若是不是監聽上一個節點Node_n-1 等它釋放掉分佈式鎖。)
@ControllerAdvice處理全局異常Mybatis註解方式的使用:
@insert 用註解方式寫SQL語句
一、分佈式系統:多節點,節點發送數據交互,不共享主內存,但經過網絡發送消息合做。
分佈式:不一樣功能模塊的節點
集羣:相同功能的節點
二、Session 與token
服務端在HTTP頭裏設置SessionID而客戶端將其保存在cookie
而使用Token時須要手動在HTTP頭裏設置,服務器收到請求後取出cookie進行驗證。
都是一個用戶一個標誌
三、分佈式系統中的Session問題:
高併發:經過設計保證系統可以同時並行處理不少請求。
當高併發量的請求到達服務端的時候經過負載均衡的方式分發到集羣中的某個服務器,這樣就有可能致使同一個用戶的屢次請求被分發到集羣的不一樣服務器上,就會出現取不到session數據的狀況。
根據訪問不一樣的URL,負載到不一樣的服務器上去
三臺機器,A1部署類目,A2部署商品,A3部署單服務
通用方案:用Redis保存Session信息,服務器須要時都去找Redis要。登陸時保存好key-value,登出時讓他失效
垂直擴展:IP哈希 IP的哈希值相同的訪問同一臺服務器
session的一致性:只要用戶不重啓瀏覽器,每次http短鏈接請求,理論上服務端都能定位到session,保持會話。
高併發:經過設計保證系統可以同時並行處理不少請求。(系統學習併發知識,能夠在Java知音公衆號回覆「多線程聚合」)
同步:Java中的同步指的是經過人爲的控制和調度,保證共享資源的多線程訪問成爲線程安全。
線程的Block狀態:
a.調用join()和sleep()方法,sleep()時間結束或被打斷
b.wait(),使該線程處於等待池,直到notify()/notifyAll():不釋放資源
此外,在runnable狀態的線程是處於被調度的線程,Thread類中的yield方法可讓一個running狀態的線程轉入runnable。
Q:爲何wait,notify和notifyAll必須與synchronized一塊兒使用?Obj.wait()、Obj.notify必須在synchronized(Obj){…}語句塊內。
A:wait就是說線程在獲取對象鎖後,主動釋放對象鎖,同時本線程休眠。
Q:Synchronized:
A:Synchronized就是非公平鎖,它沒法保證等待的線程獲取鎖的順序。
公平和非公平鎖的隊列都基於鎖內部維護的一個雙向鏈表,表結點Node的值就是每個請求當前鎖的線程。公平鎖則在於每次都是依次從隊首取值。
ReentrantLock重要性:
重入鎖能夠看這兩篇文章,都比較簡單
https://www.jianshu.com/p/587...
Spring + Redis緩存的兩個重要註解:
對數據庫加鎖(樂觀鎖 與 悲觀鎖)
悲觀鎖依賴數據庫實現:
select * from account where name=」Erica」 for update
這條sql 語句鎖定了account 表中全部符合檢索條件(name=」Erica」)的記錄,使該記錄在修改期間其它線程不得佔有。
代碼層加鎖:
String hql ="from TUser as user where user.name='Erica'";Query query = session.createQuery(hql);query.setLockMode("user",LockMode.UPGRADE); //加鎖List userList = query.list();//執行查詢,獲取數據
@Data 相似於自動生成了Getter()、Setter()、ToString()等方法。
JAVA1.8的新特性StreamAPI:Collectors中提供了將流中的元素累積到匯聚結果的各類方式
List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList())
For - each 寫法:
for each語句是java5新增,在遍歷數組、集合的時候,for each擁有不錯的性能。
public static void main(String[] args) { String[] names = {"beibei", "jingjing"}; for (String name : names) { System.out.println(name); } }
for each雖然能遍歷數組或者集合,可是隻能用來遍歷,沒法在遍歷的過程當中對數組或者集合進行修改。
BindingResult:一個@Valid的參數後必須緊挨着一個BindingResult 參數,不然spring會在校驗不經過時直接拋出異常。
@Datapublic class OrderForm { @NotEmpty(message = "姓名必填") private String name;}
後臺:
//+V:BGM7756,免費領取資料@RequestMapping("save") public String save( @Valid OrderForm order,BindingResult result) { // if(result.hasErrors()){ List<ObjectError> ls=result.getAllErrors(); for (int i = 0; i < ls.size(); i++) { log.error("參數不正確,OrderForm={}", order); throw new SellException( ………… , result.getFeildError.getDefaultMessage() ) System.out.println("error:"+ls.get(i)); } } return "adduser"; } //+V:BGM7756,免費領取資料
result.getFeildError.getDefaultMessage()可拋出「姓名必填」 的異常。
四、List轉爲Map
//+V:BGM7756,免費領取資料public class Apple { private Integer id; private String name; private BigDecimal money; private Integer num; /*構造函數*/}List<Apple> appleList = new ArrayList<>();//存放apple對象集合Apple apple1 = new Apple(1,"蘋果1",new BigDecimal("3.25"),10);Apple apple12 = new Apple(1,"蘋果2",new BigDecimal("1.35"),20);Apple apple2 = new Apple(2,"香蕉",new BigDecimal("2.89"),30);Apple apple3 = new Apple(3,"荔枝",new BigDecimal("9.99"),40);appleList.add(apple1);appleList.add(apple12);appleList.add(apple2);appleList.add(apple3);Map<Integer, Apple> appleMap =appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1)); //+V:BGM7756,免費領取資料
五、Collection的子類:List、Set
List:ArrayList、LinkedList 、Vector
List:有序容器,容許null元素,容許重複元素
Set:元素是無序的,不容許元素
最流行的是基於 HashMap 實現的 HashSet,由hashCode()和equals()保證元素的惟一性。
能夠用set幫助去掉List中的重複元素,set的構造方法的參數能夠是List,構造後是一個去重的set。
HashMap的補充:它不是Collection下的
Map可使用containsKey()/containsValue()來檢查其中是否含有某個key/value。
HashMap會利用對象的hashCode來快速找到key。
插入過程:經過一個hash函數肯定Entry的插入位置index=hash(key),可是數組的長度有限,可能會發生index衝突,當發生了衝突時,會使用頭插法,即爲新來的Entry指向舊的Entry,成爲一個鏈表。
每次插入時依次遍歷它的index下的單鏈表,若是存在Key一致的節點,那麼直接替換,而且返回新的值。
可是單鏈表不會一直增長元素,當元素個數超過8個時,會嘗試將單鏈錶轉化爲紅黑樹存儲。
爲什麼加載因子默認爲0.75?(0.75開始擴容)
答:經過源碼裏的javadoc註釋看到,元素在哈希表中分佈的桶頻率服從參數爲0.5的泊松分佈。
經過上面的介紹,相信你們對springboot微信點餐開源系統方面有了進一步的認識,但願可以幫助到你們!因爲細節內容實在太多啦,因此只把部分知識點整理出來粗略的介紹
最近整理了一份Java核心知識點。覆蓋了springboot、JVM、鎖、併發、Java反射、Spring
原理、微服務、Zookeeper、數據庫、數據結構等大量知識點。