摘要: 原創出處 https://www.bysocket.com 「公衆號:泥瓦匠BYSocket 」歡迎關注和轉載,保留摘要,謝謝!java
一個優秀的工程師和一個普通的工程師的區別,不是滿天飛的架構圖,他的功底體如今所寫的每一行代碼上。
-- 畢玄sql
【書摘】類名用 UpperCamelCase 風格,好比 DO/BO/VO/PO設計模式
【書摘】方法用 lowerCamelCase 風格,儘可能是動詞服務器
小思考:例如經常使用的數據結構
【書摘】若是變量值僅在一個範圍變化,則用 enum 類型架構
小思考:例如電商中訂單狀態,用手指也能列出來。因此通常定義個 OrderSatausEnum 搞定,僞代碼以下:併發
public enum OrderSatausEnum { TO_PAY(1,"代付款"), PAID(2,"已付款") ...; private Integer orderStatus; private String orderSatausDes; OrderSatausEnum(Integer orderStatus,String orderSatausDes) { this.orderStatus = orderStatus; this.orderSatausDes = orderSatausDes; } // get set }
進一步,若是訂單某天要加個「待拼團」狀態咋辦?因此這些配置化的東西,能夠上配置中心。好比攜程出的 apollo 等socket
【書摘】Object 的 equals 方法容易拋空指針異常,應使用常量或者肯定優質的對象來調用 equals 。tcp
好比:「TO_PAY」.equals(order.getOrderStatus())。反着寫就不對了,由於 order.getOrderStatus() 可能爲 null。高併發
天然,更加推薦 java.util.Objects#equals 工具類。
【書摘】全部相同類型的包裝類對象之間的值比較,所有使用 equals 方法。
小思考:別用 == 了。equals 也要注意些事情,好比 Byte 類型的 status 對象值,用 equals 要注意以下:
getStatus().equals(0) // 反例,false getStatus().equals((byte)0) // 正例,true
還有, == 好比 Integer 在 -128 到 127 範圍比較正常,超過就不正常。緣由是 -128 到 127 範圍的對象在 IntegerCache.cache 中產生,會複用對象。因此因此,切記切記,別用 == 了,用 equals 去比較。
【書摘】不要在 for 循環中進行元素的 remove/add 操做。remove 請使用 Iterator 方法,若是有併發操做,則對 Iterator 對象加鎖。
具體 Iterator 怎麼操做集合,百度下便可。這仍是典型的 迭代器設計模式,能夠深刻源碼看看人家的簡單實現原理,又能學到一發高級知識。
【書摘】第一,線程必須經過線程池來提供,不容許顯式建立線程。第二,線程池不容許用 Executors 建立,應使用 ThreadPoolExecutor 去建立。由於
Executors 建立的幾種 ThreadPool 會有弊端:
因此,使用 ThreadPoolExecutor 的緣由是能更好地理解線程池的運行規則,規避資源耗盡,更好地貼合某個業務場景,去建立更適合的線程池。
【書摘】在高併發場景中,同步調用應該考慮鎖的性能損耗。能用無鎖數據結構,就不要用鎖;能鎖區塊,就不要鎖整個方法體;能用對象鎖,就不要用類鎖。即,加鎖的粒度越小,性能損耗越小。而且避免鎖的代碼塊中調用了 RPC 方法。
另外,同時對多個資源加鎖的時候,須要保持一致的加鎖順序。不然,一個線程加鎖順序爲 ABC,另外一個加鎖順序爲 ACB 或 BAC 等,會形成死鎖。如圖:
【書摘】金融資金相關信息,使用悲觀鎖。好比更新某個用戶的錢包餘額字段。
小思考:我之前作 P2P 的時候,就很簡單地使用了 MySQL 的行鎖。
SELECT * FROM xx WHREER xx.id=888 FOR UPDATE
具體行鎖,表鎖你們能夠自行百度瞭解。
【書摘】高併發場景,好比秒殺場景,商品扣庫存,庫存的判斷不要用「等於」來判斷商品庫存已售罄的條件。應使用大於或者小於的條件來代替。
小思考:這是典型的超賣場景。有人會問也會存在超賣幾件的問題吧?答案是是的。但若是用 等於 來判斷,超賣的件數會不少不少,好比達到 1 萬件。但超賣 1 萬件和超賣 1 件是不同等級的故障。或者是一個故障和一個不是故障的區別。
【書摘】異常不要用來作流程控制,條件控制
小思考:昨天京東小哥問我,這個能這麼搞降級嗎?以下代碼:
try { searchFromES() }catch(){ searchFromDB() }
這不算降級,這也不能這麼搞。第一,代碼這也寫就不對,異常不要用來作流程控制,條件控制。第二,這個只要實現 ES 讀取有問題,讀取不到就讀 DB。能夠考慮責任鏈設計模式去實現。僞代碼以下:
ESHandle { void handle() { try { searchFromES() }catch(){ } } } DBHandle { void handle() { try { searchFromES() }catch(){ } } } // 兩個 Handle 利用責任鏈去實現便可。
【書摘】當單錶行數超過 500 萬行或者單表容量超過 2 GB時,才推薦進行分庫分表。
若是預計三年後的數量級沒法達到這個級別,請不要在建立表時就分庫分表。
【書摘】不要使用 count(列名) 或者 count(常量) 來替代 count(*)。 由於它是 SQL92 定義的標準統計行數的預發。它會統計 NULL 的行。
【書摘】where 條件下里面的 in 能避免就避免,要注意 in 裏面的集合數量,控制在 1000 個以內。
【書摘】在代碼中寫分頁查詢,若是 count 爲 0 ,直接返回 空列表。避免執行下面的分頁語句。
【書摘】高併發服務器建議調小 TCP 協議的 time_wait 超時時間。Linux 修改 /etc/sysctl.conf 文件,代碼以下:
net.ipv4.tcp_fin_timeout = 30
【書摘】JVM 設置參數 -XX:+HeapDumpOnOutOfMemoryError。讓 JVM 碰到 OOM 的時候,輸出 dump 信息。
小思考:這個很重要。兩者得保留事故服務器現場。好比 OOM 了某個服務器,則在 VIP 或者啥摘到該機器,讓該機器再也不有請求進入。而後去查看 dump 信息,去排查 OOM 問題。
感謝小冊子《阿里巴巴 Java 開發手冊》,感受不錯。至少其中有幾點,有目共睹的。