功能 -> 性能? -> 智能
可靠性:可擴展性、服務降級、負載均衡、灰度
性能:緩存、并發(fā)、池化、異步
一、可靠性
1、應用擴展
- 垂直擴展(scala up)
方式:提升機器硬件
缺點:成本昂貴,擴展能力有限

- 水平擴展(scala out)
方式:增加節(jié)點(增加機器數(shù)量)
優(yōu)點:升級過程平滑透明,硬件成本低,理論上可無限擴展
缺點:會增加系統(tǒng)的復雜度,維護成本高,服務須無狀態(tài)(比如多臺機器無法使用Session),可分布式的

2、數(shù)據(jù)庫擴展
- 垂直拆分
原先:一個庫數(shù)據(jù)量太大,將業(yè)務緊密,表間關聯(lián)密切的表劃分在一起
分庫:將數(shù)據(jù)表拆分,可以提高性能、隔離故障

-
水平拆分
一個表的數(shù)據(jù)量太大,一表拆多表,根據(jù)查詢使用情況確定拆分規(guī)則;
MySQL單表最大記錄數(shù)不要超過5000W;
帶來的問題:
(1)如何從多張表中定位到數(shù)據(jù)所在的表?
自定義映射規(guī)則
為某個字段計算hash從而對應到相應的表中例子: 用戶聊天信息表拆分為message_00,message_01,message_02..........message_98,message_99, 然后根據(jù)用戶的ID來判斷這個用戶的聊天信息放到哪張表里面,可以用hash的方式來獲得, 可以用求余的方式來獲得,方法很多

(2)如何使代碼優(yōu)雅(代碼層不牽扯數(shù)據(jù)庫分表)
Spring動態(tài)數(shù)據(jù)源 -->> 連接不同的庫
分表組件:如TSharding,是一個簡易 sharding 組件,也是一個 Mybatis 分庫分表組件。
Mybatis 分庫分表組件 TSharding-Client
- 數(shù)據(jù)庫擴展考慮點
- 數(shù)據(jù)量:現(xiàn)有/未來數(shù)據(jù)量會有多大?
- 增長速度:增長速度影響數(shù)據(jù)量,提前考慮分表(如何評估?周期不要超過半年,不可靠)
- QPS:每秒查詢量
- 切分規(guī)則:根據(jù)具體業(yè)務、表內容、需求等進行合理分片
3、負載均衡
方案
Nginx反向代理服務器(推薦): 用戶請求到達Nginx服務器,按照一定策略http轉發(fā)到具體的機器
HTTP重定向: 302
DNS輪詢解析
LVS: 網(wǎng)絡4層,內核協(xié)議棧
HAProxy: 4/7層
分發(fā)策略
Random:隨機分發(fā)(請求次數(shù)公平)
RoundRobin:RR,輪詢分發(fā)(請求次數(shù)公平)
LeastActive:最少活躍,根據(jù)服務器當前處理請求的能力(處理能力公平)
Hash:如根據(jù)ip做hash、根據(jù)內容(請求內容)做hash
健康檢查
將空的健康檢查文件HealthyCheck.html放在各個服務器上,以供Nginx等服務器檢查應用服務器的運行狀態(tài)。
4、服務降級
- 服務分級
對提供的服務進行分級,核心服務具有更高的優(yōu)先級,頻率低、不重要的服務級別低 - 功能開關
- 全流程開關
- config

二、性能
1、并發(fā)
Servlet非線程安全

多線程環(huán)境下,需要使用線程安全的集合、共享資源加鎖等。
并發(fā)鎖
synchronized/ReentrantLock
可重入鎖:
互斥:同一時刻只能有一個線程持有(相對的是共享鎖)
讀寫鎖
ReadWriterLock:有timeout機制,超時不等待
讀鎖:是共享鎖
寫鎖:是排它鎖,互斥
鎖不能升級(讀鎖->寫鎖),只能降級(寫鎖->讀鎖);
寫鎖要等待所有的讀鎖釋放樂觀鎖
樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設認為數(shù)據(jù)一般情況下不會造成沖突,所以在數(shù)據(jù)進行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進行檢測,如果發(fā)現(xiàn)沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。
悲觀鎖
正如其名,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當前的其他事務,以及來自外部系統(tǒng)的事務處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機制(也只有數(shù)據(jù)庫層提供的鎖機制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實現(xiàn)了加鎖機制,也無法保證外部系 統(tǒng)不會修改數(shù)據(jù))。
2、緩存

-
本地緩存
HashMap
ConcurrentHashMap(并發(fā)環(huán)境)
Guava Cache
-
memcached
Key-Value
username_zhangsan -> {"username":zhangsan,"nickname":"張全蛋"}LRU
Least Recently Used近期最少使用分布式
一致性Hash
client實現(xiàn)-
Client
xmemcached
spymemcached
[memcached](https://www.baidu.com/link?url=h3veG-DxMyBf86uSyo-ASq3Yg81BQXgBZ7q4cXQS4omKnRCBpEwaTXQYW-gNQsEsQuDKk7PpNkF4OkNmZL1Dc0d2Bp61s4eGZUMipAYrSpq&wd=&eqid=891a485f0000a2be0000000358d4d91e) 是一個高性能的分布式內存對象緩存系統(tǒng),用于動態(tài)Web應用以減輕數(shù)據(jù)庫負載。它通過在內存中緩存數(shù)據(jù)和對象來減少讀取數(shù)據(jù)庫的次數(shù),從而提高動態(tài)、數(shù)據(jù)庫驅動網(wǎng)站的速度。Memcached基于一個存儲鍵/值對的[hashmap](http://baike.baidu.com/item/hashmap)。其[守護進程](http://baike.baidu.com/item/%E5%AE%88%E6%8A%A4%E8%BF%9B%E7%A8%8B)(daemon )是用[C](http://baike.baidu.com/item/C/7252092)寫的,但是客戶端可以用任何語言來編寫,并通過memcached協(xié)議與守護進程通信。 -
redis
數(shù)據(jù)結構豐富
Hash
List
Set
...操作豐富
可持久化:定期將內存數(shù)據(jù)保存到磁盤,關機后可load到內存
單線程、多實例

3、序列化

概念
將對象的狀態(tài)信息轉換為可以存儲或傳輸形式的過程
方式
- Json:將對象信息轉換為json數(shù)據(jù)
- Java serialization
java序列化一定要應該注意**的6個事項
1、如果子類實現(xiàn)Serializable接口而父類未實現(xiàn)時,父類不會被序列化,但此時父類必須有個無參構造方法,否則會拋InvalidClassException異常。
2、靜態(tài)變量不會被序列化,那是類的“菜”,不是對象的。
3、transient關鍵字修飾變量可以限制序列化。
4、虛擬機是否允許反序列化,不僅取決于類路徑和功能代碼是否一致,一個非常重要的一點是兩個類的序列化ID是否一致,就是 private static final long serialVersionUID = 1L。
5、Java 序列化機制為了節(jié)省磁盤空間,具有特定的存儲規(guī)則,當寫入文件的為同一對象時,并不會再將對象的內容進行存儲,而只是再次存儲一份引用。反序列化時,恢復引用關系。
6、序列化到同一個文件時,如第二次修改了相同對象屬性值再次保存時候,虛擬機根據(jù)引用關系知道已經(jīng)有一個相同對象已經(jīng)寫入文件,因此只保存第二次寫的引用,所以讀取時,都是第一次保存的對象。讀者在使用一個文件多次 writeObject 需要特別注意這個問題(基于第5點)。
- Hessian
- Protobuf
- Kryo
4、池化技術
場景
- 可復用資源
- 創(chuàng)建代價大
類型
- 線程池
- Executor

- 連接池
- tomcat-jdbc
- dbpc
- c3p0

- 對象池
- Spring Bean 管理
5、異步
前端輪詢、后端異步
- Futrue/CountDownLatch
消息隊列
- QMQ/Kafka/AMQ/rabbitmq
HTTP
- async-http-client
- Apache HttpComponents
Dubbo
- 異步調用、參數(shù)回調

