wcs
springboot 啟動流程
1:實例化SpringApplication 對象

1.1調用initiallize方法,讀取兩個包的spring.factories。目的給SpringApplication設置初始的監聽器和初始化器;




2:調用Application.run()
2.1:調用getRunListeners()

getRunListeners()讀取spring.factories實例化EventPublishingRunListener ,包含廣播器和Application對象;

2.2:調用listeners.start();
java8
便于并行計算
lamda更符合閱讀習慣
代碼少(由于增加了Lambda表達式)
集成Stream API
1.8 HashMap put流程
1、計算key的hash值(高低位異或)
2、判斷數組是否為空,如果數組為空 則直接擴容
3、如果數組非空 則 根據hash值計算數組下標(n-1)& hash,根據下標取數組對應值,如果值為空則新建一個node,非空則轉為下一步
4、key的hash 和 equals與 下標數組的值都相同,則直接覆蓋;
5、如果不相同則 判斷下標數組的值 是否 紅黑樹實例,是紅黑樹的話 新節點直接加入紅黑樹中
6、不是紅黑樹實例就是鏈表,循環遍歷鏈表,并判斷是否為已有節點如果有則直接返回,如果沒有 則將新節點放到鏈表尾部,如果新鏈表大小超過 閾值(8-1)即>= 7,將鏈表轉為紅黑樹
7、key存儲完畢之后,并判斷 hashMap大小是否超閾值(上次map大小的2的次數),如果超過 則直接擴容,否則 put流程結束
ConcurrentHashMap cas(空節點) synchronized(存在節點)
Channels
Buffers
Selectors 1 -> Channels n
Mysql
1:內存頁16kb,單行盡量數據小。
2: b+樹一個節點16kb,能存儲1170左右的指針 二層1170 三層1170*1170個16kb的內存頁,一條數據是1kb的話??梢源鎯?000w條數據
3:mysql沒有枚舉,可使用tinyint的0,1去區分男女
4:聚簇索引,select * 無法使用覆蓋,輔助索引。
5:數據量增長,分區(日期,id)1020個最大的分區。垂直查分,單表變多表(表查詢需要考慮)。
分區,垂直拆分(單臺服務器)后還無法滿足,水平拆分:如訂單一天2000w,存儲2個服務器,用如一致性hash。注意劃分key,避免單個sql查詢多張表。
6:冷熱備份,可以將無用數據備份。
重做日志(redo log)
重做日志(redo log)的作用是確保事務的持久性,防止在發生故障的時間點,尚有臟頁未寫入磁盤。在重啟 MySQL 服務的時候,根據 redo log 進行重做,從而達到事務的持久性這一特性。
回滾日志(undo log)
保存了事務發生之前的數據的一個版本,可以用于回滾,同時可以提供多版本并發控制下的讀(MVCC),也即非鎖定讀。
二進制日志(binlog)
用于復制,在主從復制中,從庫利用主庫上的 binlog 進行重播,實現主從同步;用于數據庫基于時間點的還原。
錯誤日志(errorlog)
慢查詢日志(slow query log)
一般查詢日志(general log)
中繼日志(relay log)
Snl簡單的被驅動表會掃描多次
Inl 需要回表,隨機io
Bnl 緩存主表 一次拿多條主表數據與被驅動表比較,比較次數一樣,但減少了從表的掃描次數,存在隨機io問題
Mrr 對id進行排序,順序讀 默認開啟
Bka index 的升級版,整合bnl和mrr
jvm
.class文件的結構
Javac 編譯.Java成.class。jvm能識別的二進制文件
類加載流程:加載,鏈接,初始化。鏈接分為驗證,準備,解析,
(1)驗證階段。主要的目的是確保被加載的類(.class文件的字節流)滿足Java虛擬機規范,不會造成安全錯誤
(2)準備階段。負責為類的靜態成員分配內存,并設置默認初始值。
(3)解析階段。將類的二進制數據中的符號引用替換為直接引用。
正確的應該是:
1:java->class。
2:鏈接里驗證:驗證文件格式,class的文件結構。
3:加載把class裝換成方法區的結構
4:加載內存生成類對象作為方法區的訪問入口
5:鏈接里驗證字節碼
6:準備 初始化0值等
7:解析 符號引用驗證
9:初始化
垃圾回收流程
可達性分析:不可達,從gcRoot遍歷。三色標記的算法。被GC roots引用的對象不被GC回收
a.虛擬機棧(棧楨中的本地變量表)中的引用的對象
b.方法區中的類靜態屬性引用的對象
c.方法區中的常量引用的對象
d.本地方法棧中JNI的引用的對象,jvm內部的
e.鎖對象的持有和釋放
Young GC Old GC fullgc
cms 用的是標記清理
GC roots是啥:堆外指向堆內的引用
初始標記 標記gcroot,并發標記遞歸標記,變動的對象標記為Direty ,重新標記 處理direty ,清理,重置。

Jvm調優心得


Minor gc (新生代)頻繁(并發大)0,增大eden取得大?。ú粫斐赏nD時間過長),降低頻率。實際測試。
如果每次Minor gc頻繁容易引發fullGc,存活對象大小是否小于s1,如果大于就會造成頻繁fullGc。適當調整s1的大小。
頻繁創建大對象,大對象大于閾值會直接進入老年代。解決方式是進行代碼拆分,改大對象為小對象。調整閾值。
長時間停頓,gc真實過程;真實過程不長,線程要到達安全點才能gc。
內存泄漏oom。線程沒有remove,網絡鏈接,io,數據庫鏈接沒有釋放資源,靜態變量使用完后null
并發編程
Lock 更靈活,顯示加鎖。避免形成死鎖。超時時間。
Cas 輕量級鎖,減少鎖的狀態,使用不當會造成cpu的消耗。
Aqs 用的模板方法模式,用戶可以自己實現。有公平鎖和非公平鎖。
公平鎖:多個線程按照申請鎖的順序去獲得鎖,線程會直接進入隊列去排隊,永遠都是隊列的第一位才能得到鎖。
優點:所有的線程都能得到資源,不會餓死在隊列中。
缺點:吞吐量會下降很多,隊列里面除了第一個線程,其他的線程都會阻塞,cpu喚醒阻塞線程的開銷會很大。
非公平鎖:多個線程去獲取鎖的時候,會直接去嘗試獲取,獲取不到,再去進入等待隊列,如果能獲取到,就直接獲取到鎖。
提高單節點的并發>單個接口。
分布式是最終方案。接口無狀態。代碼異步多線程。Db查詢速度,調優,緩存。第三方調用時用多線程。帶寬用stream流。引入消息隊列,拆分數據。緩存用redis會有額外的開銷。
Sychnozided
Volitail 保證可見性。重排序(內存屏障)
- Store:將處理器緩存的數據刷新到內存中。
- Load:將內存存儲的數據拷貝到處理器的緩存中。
線程池,飽和策略,最大線程數(隊列滿了,創建的線程數小于最大線程數,可創建新的),核心的size。飽和策略:
1拋異常會附帶執行信息。存到數據庫,根據業務處理
2:丟棄(默認)
3:調用者線程執行
4:丟棄隊列里最近的一個任務,并執行當前提交的任務。
Redis 為什么快:內存v>磁盤v 采用的netty 單(多)線程放映器模型
單個線程輪詢客戶端
快照和aop速度和文件大小相關。
內存淘汰數據:保證都是熱點數據
最少使用,臨近過期,隨機,返回錯誤,最近未使用
而在 Redis 中,一個指針是占了 8 個字節
1:(默認開啟)對壓縮列表(能更大的存儲)的配置修改,一個指針6字節共計20,開啟后本身加上2字節。默認為小于512條(每一個元素的大小小于64字節)。調整2000左右。
2:代碼減少key的大小,拆分長列表
3:分片思想分長列表。
4:把數據打包成二進制位存儲,需要程序支撐。
高可用
- 合理的負載均衡,隔離,限流。降級,代碼加重試機制
- 三層限流 negix,redis分布式單個ip,用戶。令牌桶,3,重要接口限流
跳表:nlgn、
redis雪崩是指redis在某個時間大量失效,設置超時時間的時候要設置隨機
緩存穿透是指緩存和數據庫中都沒有的數據、緩存空
緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期)
設置熱點數據永不過期
加互斥鎖
淘汰策略:
1. noeviction:當內存使用超過配置的時候會返回錯誤,不會驅逐任何鍵
2. allkeys-lru:加入鍵的時候,如果過限,首先通過LRU算法驅逐最久沒有使用的鍵
3. volatile-lru:加入鍵的時候如果過限,首先從設置了過期時間的鍵集合中驅逐最久沒有使用的鍵
4. allkeys-random:加入鍵的時候如果過限,從所有key隨機刪除
5. volatile-random:加入鍵的時候如果過限,從過期鍵的集合中隨機驅逐
6. volatile-ttl:從配置了過期時間的鍵中驅逐馬上就要過期的鍵
7. volatile-lfu:從所有配置了過期時間的鍵中驅逐使用頻率最少的鍵
8. allkeys-lfu:從所有鍵中驅逐使用頻率最少的鍵
編碼風格
原型模式(Prototype Pattern)是用于創建重復的對象,同時又能保證性能。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
這種模式是實現了一個原型接口,該接口用于創建當前對象的克隆。當直接創建對象的代價比較大時,則采用這種模式。例如,一個對象需要在一個高代價的數據庫操作之后被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新數據庫,以此來減少數據庫調用。直接在內存里用拷貝二進制流的方式創建對象。
發短信,不用大量new對象。
模板方法,比較透明
高并發
長時間的維持瞬時并發量
提高單節點的并發量
分布式是最后考慮
代碼(異步),db數據庫調優緩存。第三方服務的調用時間(多線程調用)。Json占用的內存較大。無狀態接口。消息隊列。
分布式節點的緩存 redis會有網絡開銷。
結合前端和redis緩存。手動觸發,消息通知前端刷新緩存。

Nacos 中提供了兩種健康檢查機制:臨時實例的客戶端主動上報機制和永久實例的服務端反向探測機制。臨時實例每隔 5s 發送一個心跳包給 Nacos 服務器端,服務器端接收到心跳包之后再將健康狀況同步給其他注冊中心。永久實例支持 3 種探測協議,TCP、HTTP 和 MySQL,默認探測協議為 TCP,也就是通過不斷 ping 的方式來判斷實例是否健康
@AutoConfigurationPackage負責加載啟動類路徑下的@Configuration修飾的類
@Import({AutoConfigurationImportSelector.class})負責加載所有依賴包中META-INF/spring-factories里定義的EnableAutoConfiguration這個key中的類
AnnotationConfigApplicationContext
EnableAutoConfiguration
@Import 注解是由 Spring 提供的,作用是將某個類實例化并加入到 Spring IoC 容器中




浙公網安備 33010602011771號