圖解學(xué)習(xí)網(wǎng)站:https://xiaolincoding.com
大家好,我是小林。
雷總的小米 su7 ultra 一發(fā)布,直接賣爆了,2 小時就完成了全年的銷售目標,50 多萬的價格就有 1500+馬力,這馬力可是千萬級跑車的配置了,1.98 秒破百,誰看了不心動,要不是狠自己錢包太小,我都想下手了。。
于是我就好奇,小米汽車的薪資待遇如何?
正好,我在「OfferShow」那里看到了「小米汽車-校招薪資爆料」匯總數(shù)據(jù),分享給大家看看。
城市 | 崗位 | 校招薪資爆料 |
北京 | 自動駕駛 | 39k*15 |
北京 | 軟開 | 24k*15 |
北京 | 測試 | 23k*15 |
北京 | 軟開 | 22k*15 |
上海 | 電池系統(tǒng)測試 | 18k*15 |
北京 | 服務(wù)端開發(fā)工程師 | 22*15+0.8*12 |
南京 | 機械崗 | 30w |
上海 | 動力集成測試 | 23k*15 |
上海 | 算法 | 23k*15 |
北京 | 產(chǎn)品經(jīng)理 | 16k*15 |
南京 | 熱管理 | 18.5k*16 |
關(guān)注我的同學(xué)們大部分都是程序員,我們就專注看軟開的校招薪資,小米年終獎是 3 個月,所以是 15 薪資計算:
- 22k x 15 = 33w,北京24k x 15 = 36w,北京
軟開的年包在 30-35w,是屬于大廠范疇的薪資了,雖然和互聯(lián)網(wǎng)一線大廠會有一點點差距,但是整體還是不錯的。
那小米汽車軟開崗的面試難得如何呢?
一起瞧瞧小米汽車Java軟開崗面經(jīng),這次是二面的面經(jīng)了,問了Spring、MySQL、設(shè)計模式、網(wǎng)絡(luò)協(xié)議、分布式事務(wù)這些內(nèi)容,最后還是一樣有一個算法題。
小米汽車二面
SpringBoot的啟動流程介紹一下
SpringBoot是一個服務(wù)Spring框架的框架,能夠簡化配置文件,快速構(gòu)建web應(yīng)用,內(nèi)置tomcat,無需打包部署,直接運行。 當(dāng)我們啟動一個SpringBoot應(yīng)用的時候,都會用到如下的啟動類:
@SpringBootApplication
public?class?Application?{
? ? ?public?static?void?main(String[] args)?{
? ? ? ? ?SpringApplication.run(Application.class,?args);
? ? ?}
只要加上@SpringBootApplication,然后執(zhí)行run()方法,就可以啟動一個應(yīng)用程序,啟動的流程如下:
- 首先從main找到run()方法,在執(zhí)行run()方法之前new一個SpringApplication對象進入run()方法,創(chuàng)建應(yīng)用監(jiān)聽器SpringApplicationRunListeners開始監(jiān)聽然后加載SpringBoot配置環(huán)境(ConfigurableEnvironment),然后把配置環(huán)境(Environment)加入監(jiān)聽對象中然后加載應(yīng)用上下文(ConfigurableApplicationContext),當(dāng)做run方法的返回對象最后創(chuàng)建Spring容器,refreshContext(context),實現(xiàn)starter自動化配置和bean的實例化等工作。
Spring IOC、 AOP解決了什么問題?沒有IOC之前怎么做?
Spring IOC 解決的問題,主要是解耦對象之間的依賴關(guān)系。在傳統(tǒng)的編程中,對象之間的依賴關(guān)系通常是在代碼中硬編碼實現(xiàn)的,這使得代碼的可維護性和可擴展性變差。IOC 通過將對象的創(chuàng)建和依賴關(guān)系的管理交給 Spring 容器,實現(xiàn)了對象之間的解耦。比如,一個業(yè)務(wù)邏輯類可能依賴于多個數(shù)據(jù)訪問類,使用 IOC 后,業(yè)務(wù)邏輯類不需要知道具體的數(shù)據(jù)訪問類是如何創(chuàng)建和獲取的,只需要聲明它的依賴關(guān)系,由 Spring 容器來負責(zé)注入。
也可以提高提高代碼的可維護性和可測試性。當(dāng)依賴關(guān)系被集中管理在 Spring 容器中時,如果需要更換某個依賴對象,只需要在配置文件或注解中進行修改,而不需要在大量的業(yè)務(wù)代碼中進行查找和修改。在進行單元測試時,也可以很方便地通過 IOC 容器注入模擬的依賴對象,提高了測試的靈活性和可操作性。
在沒有 IOC 框架之前,開發(fā)人員通常需要在代碼中手動創(chuàng)建對象及其依賴對象。例如,在一個 Java 項目中,如果一個?UserService
?類依賴于?UserDao
?類,那么在?UserService
?類中需要通過?new
?關(guān)鍵字來創(chuàng)建?UserDao
?的實例,如下所示:
public?class?UserService?{
? ??private?UserDao userDao =?new?UserDao();
? ??public?void?doSomething()?{
? ? ? ??// 使用userDao進行業(yè)務(wù)操作
? ? ? ? userDao.saveUser();
? ? }
}
這樣的代碼存在著嚴重的耦合問題,如果需要更換?UserDao
?的實現(xiàn)類或者對其進行一些初始化配置,就需要在?UserService
?類中進行修改,隨著項目規(guī)模的增大,維護成本會越來越高。
Spring AOP 解決的問題,主要是可以分離業(yè)務(wù)邏輯和橫切關(guān)注點,提高代碼的復(fù)用性。在企業(yè)級應(yīng)用開發(fā)中,往往存在一些橫切關(guān)注點,如日志記錄、事務(wù)管理、權(quán)限控制等,這些功能會分散在各個業(yè)務(wù)邏輯代碼中,導(dǎo)致代碼的可讀性和可維護性變差。AOP 允許將這些橫切關(guān)注點從業(yè)務(wù)邏輯中分離出來,以切面的形式進行統(tǒng)一管理和實現(xiàn)。通過 AOP,可以將通用的橫切邏輯封裝在切面中,然后在多個業(yè)務(wù)邏輯中進行復(fù)用。例如,對于日志記錄功能,可以創(chuàng)建一個日志切面,在多個不同的業(yè)務(wù)方法上都可以應(yīng)用這個切面來記錄日志,而不需要在每個業(yè)務(wù)方法中都編寫重復(fù)的日志記錄代碼。
在沒有 AOP 之前,要實現(xiàn)日志記錄、事務(wù)管理等橫切功能,通常需要在每個需要這些功能的方法中手動編寫相關(guān)代碼。以日志記錄為例,可能需要在每個業(yè)務(wù)方法的開始和結(jié)束位置都添加日志記錄代碼,如下所示:
public?class?UserService?{
? ??public?void?doSomething()?{
? ? ? ??// 記錄方法開始日志
? ? ? ? System.out.println("進入doSomething方法");
? ? ? ??// 業(yè)務(wù)邏輯代碼
? ? ? ??// 記錄方法結(jié)束日志
? ? ? ? System.out.println("離開doSomething方法");
? ? }
}
這樣不僅會導(dǎo)致代碼大量重復(fù),而且當(dāng)需要修改日志記錄的格式或策略時,需要在多個地方進行修改,容易出現(xiàn)遺漏和不一致的情況。
自己項目中有用到AOP嗎?
有,主要用在了日志記錄功能,避免在每個業(yè)務(wù)方法里重復(fù)編寫日志記錄代碼。
看你也會golang,golang和java的區(qū)別?
Golang是由Google設(shè)計的靜態(tài)類型、編譯型語言,注重簡潔和高效并發(fā)。而Java是一種面向?qū)ο蟮恼Z言,擁有成熟的生態(tài)系統(tǒng)和跨平臺能力,依賴JVM運行。
在語法方面,Golang更簡潔,沒有類和繼承,使用接口和結(jié)構(gòu)體,而Java是嚴格的面向?qū)ο?,需要更多的樣板代碼。并發(fā)模型方面,Golang有g(shù)oroutine和channel,輕量級且易于使用;Java使用線程和線程池,相對重量級,但通過并發(fā)包提供豐富的工具。
性能方面,Golang作為編譯型語言,通常啟動更快,內(nèi)存占用更低;Java雖然JIT優(yōu)化后性能強勁,但啟動和內(nèi)存開銷較大。
內(nèi)存管理方面,兩者都有垃圾回收,但Golang的GC更注重低延遲,Java的GC調(diào)優(yōu)更復(fù)雜但靈活。 錯誤處理機制也不同,Golang采用顯式錯誤返回,而Java使用異常機制。這可能影響代碼的可讀性和錯誤處理流程。
生態(tài)系統(tǒng)方面,Java有大量成熟的框架和庫,適合企業(yè)級應(yīng)用;Golang的生態(tài)在云原生和微服務(wù)領(lǐng)域發(fā)展迅速,但相對年輕。
應(yīng)用場景方面,Golang適合高并發(fā)、分布式系統(tǒng),云基礎(chǔ)設(shè)施,而Java在企業(yè)應(yīng)用、Android開發(fā)、大數(shù)據(jù)處理等方面占優(yōu)。
MySQL建表的時候有哪些優(yōu)化手段?
合理選擇數(shù)據(jù)類型:根據(jù)實際存儲的數(shù)據(jù)范圍選擇合適的數(shù)值類型,避免使用過大的數(shù)據(jù)類型造成空間浪費。例如,如果存儲的整數(shù)范圍在 0 - 255 之間,使用?TINYINT
即可,而不是?INT
。對于固定長度的字符串,使用?CHAR
類型;對于可變長度的字符串,使用?VARCHAR
類型。同時,根據(jù)實際存儲的字符串長度合理設(shè)置字段長度。
控制字段數(shù)量:避免創(chuàng)建過多不必要的字段,過多的字段會增加表的復(fù)雜度和存儲開銷,同時也會影響查詢性能??梢詫⒁恍┎怀S玫淖侄螁为毚鎯υ谄渌碇?,通過關(guān)聯(lián)查詢獲取數(shù)據(jù)。
反范式化設(shè)計:可以適當(dāng)引入一些數(shù)據(jù)冗余,將相關(guān)聯(lián)的數(shù)據(jù)存儲在同一個表中,減少表之間的關(guān)聯(lián)查詢。需要在范式化和反范式化之間找到一個平衡點。
合理創(chuàng)建索引:在經(jīng)常用于?WHERE
子句、JOIN
子句和?ORDER BY
子句的字段上創(chuàng)建索引,以提高查詢效率。避免在重復(fù)值較多的字段上創(chuàng)建索引,因為這樣的索引效果不佳。例如,在一個性別字段上創(chuàng)建索引可能沒有太大意義。當(dāng)然,過多的索引會增加存儲開銷和寫操作的性能開銷,因此要根據(jù)實際查詢需求合理創(chuàng)建索引,避免創(chuàng)建過多不必要的索引。
MySQL索引怎么建?
主鍵索引是一種特殊的唯一索引,它不允許有空值。通常在創(chuàng)建表時指定主鍵,MySQL 會自動創(chuàng)建主鍵索引。創(chuàng)建方式:
-- 在創(chuàng)建表時創(chuàng)建主鍵索引
CREATE TABLE?table_name?(
? ? column1 datatype PRIMARY KEY,
? ? column2 datatype,
? ? ...
);
-- 使用 ALTER TABLE 語句創(chuàng)建主鍵索引
ALTER TABLE table_name ADD PRIMARY?KEY?(column1, column2, ...);
創(chuàng)建普通索引的方式:
-- 在創(chuàng)建表時創(chuàng)建普通索引
CREATE TABLE?table_name?(
? ? column1 datatype,
? ? column2 datatype,
? ? ...
? ? INDEX index_name (column1, column2, ...)
);
-- 在已存在的表上創(chuàng)建普通索引
CREATE INDEX index_name ON?table_name?(column1, column2, ...);
-- 使用 ALTER TABLE 語句創(chuàng)建普通索引
ALTER TABLE table_name ADD INDEX?index_name?(column1, column2, ...);
創(chuàng)建唯一索引的方式,唯一索引要求索引列的值必須唯一,但允許有空值。
-- 在創(chuàng)建表時創(chuàng)建唯一索引
CREATE TABLE?table_name?(
? ? column1 datatype,
? ? column2 datatype,
? ? ...
? ? UNIQUE INDEX index_name (column1, column2, ...)
);
-- 在已存在的表上創(chuàng)建唯一索引
CREATE UNIQUE INDEX index_name ON?table_name?(column1, column2, ...);
-- 使用 ALTER TABLE 語句創(chuàng)建唯一索引
ALTER TABLE table_name ADD UNIQUE INDEX?index_name?(column1, column2, ...);
MySQL中的鎖機制你知道哪些?
在 MySQL 里,根據(jù)加鎖的范圍,可以分為全局鎖、表級鎖和行鎖三類。
鎖類型 | 加鎖范圍 | 加鎖語句 | 具體說明 |
---|---|---|---|
全局鎖 | 整個數(shù)據(jù)庫 | flush tables with read lock |
執(zhí)行該語句后數(shù)據(jù)庫處于只讀狀態(tài),其他線程的增刪改或表結(jié)構(gòu)修改操作都會阻塞 |
表級鎖 | 表 | lock tables |
對表加表鎖,會限制別的線程的讀寫,也會限制本線程接下來的讀寫操作 |
表級鎖(元數(shù)據(jù)鎖) | 表 | 自動加鎖 | 對表進行 CRUD 操作時加 MDL 讀鎖;對表做結(jié)構(gòu)變更操作時加 MDL 寫鎖 |
表級鎖(意向鎖) | 表 | 執(zhí)行插入、更新、刪除操作時自動加鎖 | 執(zhí)行插入、更新、刪除操作時,先對表加上「意向獨占鎖」,然后對該記錄加獨占鎖 |
行級鎖(記錄鎖) | 表中的一條記錄 | InnoDB 引擎自動加鎖 | 有 S 鎖(共享鎖)和 X 鎖(排他鎖)之分,滿足讀寫互斥,寫寫互斥 |
行級鎖(間隙鎖) | 表中的記錄間隙 | InnoDB 引擎自動加鎖,只存在于可重復(fù)讀隔離級別 | 用于解決可重復(fù)讀隔離級別下幻讀的現(xiàn)象 |
行級鎖(Next-Key Lock) | 表中的一個范圍及記錄本身 | InnoDB 引擎自動加鎖 | 是 Record Lock + Gap Lock 的組合,鎖定一個范圍,并且鎖定記錄本身 |
全局鎖:通過flush tables with read lock 語句會將整個數(shù)據(jù)庫就處于只讀狀態(tài)了,這時其他線程執(zhí)行以下操作,增刪改或者表結(jié)構(gòu)修改都會阻塞。全局鎖主要應(yīng)用于做
全庫邏輯備份,這樣在備份數(shù)據(jù)庫期間,不會因為數(shù)據(jù)或表結(jié)構(gòu)的更新,而出現(xiàn)備份文件的數(shù)據(jù)與預(yù)期的不一樣。
表級鎖:MySQL 里面表級別的鎖有這幾種:
表鎖:通過lock tables 語句可以對表加表鎖,表鎖除了會限制別的線程的讀寫外,也會限制本線程接下來的讀寫操作。元數(shù)據(jù)鎖:當(dāng)我們對數(shù)據(jù)庫表進行操作時,會自動給這個表加上 MDL,對一張表進行 CRUD 操作時,加的是?MDL 讀鎖;對一張表做結(jié)構(gòu)變更操作的時候,加的是?MDL 寫鎖;MDL 是為了保證當(dāng)用戶對表執(zhí)行 CRUD 操作時,防止其他線程對這個表結(jié)構(gòu)做了變更。意向鎖:當(dāng)執(zhí)行插入、更新、刪除操作,需要先對表加上「意向獨占鎖」,然后對該記錄加獨占鎖。
意向鎖的目的是為了快速判斷表里是否有記錄被加鎖。
行級鎖:InnoDB 引擎是支持行級鎖的,而 MyISAM 引擎并不支持行級鎖。
-
- 記錄鎖,鎖住的是一條記錄。而且記錄鎖是有 S 鎖和 X 鎖之分的,滿足讀寫互斥,寫寫互斥間隙鎖,只存在于可重復(fù)讀隔離級別,目的是為了解決可重復(fù)讀隔離級別下幻讀的現(xiàn)象。Next-Key Lock 稱為臨鍵鎖,是 Record Lock + Gap Lock 的組合,鎖定一個范圍,并且鎖定記錄本身。
最熟悉的設(shè)計模式有哪些?
單例模式、工廠模式、策略模式、裝飾器模式這些。
- 單例模式:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。工廠模式:定義一個創(chuàng)建對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類。策略模式:定義一系列的算法,把它們一個個封裝起來,并且使它們可以相互替換。該模式使得算法可以獨立于使用它的客戶而變化。裝飾器模式:動態(tài)地給一個對象添加一些額外的職責(zé)。就增加功能來說,裝飾器模式相比生成子類更為靈活。
代理模式講一下
代理模式為其他對象提供一種代理以控制對這個對象的訪問。
在代理模式中,代理對象與目標對象實現(xiàn)相同的接口,客戶端對目標對象的訪問實際上是通過代理對象來進行的,代理對象可以在調(diào)用目標對象的方法前后進行一些額外的操作,如權(quán)限驗證、緩存處理、日志記錄等。
代理模式實現(xiàn)有這些:
-
- 靜態(tài)代理:手動編寫代理類,需實現(xiàn)與目標對象相同的接口。優(yōu)點是簡單直觀,缺點是每個目標類需對應(yīng)一個代理類,代碼冗余。動態(tài)代碼:運行時動態(tài)生成代理類,無需手動編寫。JDK動態(tài)代理是基于接口,使用
java.lang.reflect.Proxy
- ,CGLIB動態(tài)代理:基于繼承,可代理無接口的類。
聊聊網(wǎng)絡(luò),交換機和路由器的區(qū)別?
交換機:主要工作在數(shù)據(jù)鏈路層。它通過學(xué)習(xí)連接到其端口的設(shè)備的 MAC 地址,構(gòu)建 MAC 地址表。當(dāng)接收到數(shù)據(jù)幀時,根據(jù)數(shù)據(jù)幀中的目的 MAC 地址在 MAC 地址表中查找對應(yīng)的端口,然后將數(shù)據(jù)幀從該端口轉(zhuǎn)發(fā)出去,實現(xiàn)本地網(wǎng)絡(luò)內(nèi)設(shè)備之間的數(shù)據(jù)交換。
路由器:主要工作在網(wǎng)絡(luò)層。它依據(jù) IP 地址進行數(shù)據(jù)轉(zhuǎn)發(fā),路由器中保存著路由表,路由表包含了網(wǎng)絡(luò)地址與下一跳地址等信息。當(dāng)路由器接收到數(shù)據(jù)包時,會根據(jù)數(shù)據(jù)包中的目的 IP 地址,在路由表中查找最佳路徑,然后將數(shù)據(jù)包沿著該路徑轉(zhuǎn)發(fā)到下一個路由器或目標設(shè)備。
現(xiàn)在我們視頻聊天,涉及到的網(wǎng)絡(luò)協(xié)議是什么?
對于實時性要求極高的視頻和音頻數(shù)據(jù),會優(yōu)先使用 UDP 進行傳輸,并通過一些額外的技術(shù)手段來彌補 UDP 的不可靠性;而對于控制信息和一些對可靠性要求較高的數(shù)據(jù),則會使用 TCP 來傳輸,以確保視頻聊天的穩(wěn)定性和正確性。
分布式事務(wù)的解決方案你知道哪些?
方案 | 一致性 | 性能 | 復(fù)雜度 | 適用場景 |
---|---|---|---|---|
2PC | 強一致性 | 低 | 中 | 傳統(tǒng)數(shù)據(jù)庫、XA協(xié)議 |
3PC | 強一致性 | 中低 | 高 | 需減少阻塞的強一致場景 |
TCC | 最終一致性 | 高 | 高 | 高并發(fā)業(yè)務(wù)(支付、庫存) |
Saga | 最終一致性 | 中 | 高 | 長事務(wù)、跨服務(wù)流程 |
消息隊列 | 最終一致性 | 高 | 中 | 事件驅(qū)動架構(gòu) |
本地消息表 | 最終一致性 | 中 | 低 | 異步通知(訂單-積分) |
- 兩階段提交協(xié)議(2PC):為準備階段和提交階段。準備階段,協(xié)調(diào)者向參與者發(fā)送準備請求,參與者執(zhí)行事務(wù)操作并反饋結(jié)果。若所有參與者準備就緒,協(xié)調(diào)者在提交階段發(fā)送提交請求,參與者執(zhí)行提交;否則發(fā)送回滾請求。實現(xiàn)簡單,能保證事務(wù)強一致性。存在單點故障,協(xié)調(diào)者故障會影響事務(wù)流程;性能低,多次消息交互增加延遲;資源鎖導(dǎo)致資源長時間占用,降低并發(fā)性能。適用于對數(shù)據(jù)一致性要求高、并發(fā)度低的場景,如金融系統(tǒng)轉(zhuǎn)賬業(yè)務(wù)。
- 三階段提交協(xié)議(3PC):在 2PC 基礎(chǔ)上,將準備階段拆分為詢問階段和準備階段,形成詢問、準備和提交三個階段。詢問階段協(xié)調(diào)者詢問參與者能否執(zhí)行事務(wù),后續(xù)階段與 2PC 類似。降低參與者阻塞時間,提高并發(fā)性能,引入超時機制一定程度解決單點故障問題。無法完全避免數(shù)據(jù)不一致,極端網(wǎng)絡(luò)情況下可能出現(xiàn)部分提交部分回滾。用于對并發(fā)性能有要求、對數(shù)據(jù)一致性要求相對較低的場景。
- TCC:將業(yè)務(wù)操作拆分為 Try、Confirm、Cancel 三個階段。Try 階段預(yù)留業(yè)務(wù)資源,Confirm 階段確認資源完成業(yè)務(wù)操作,Cancel 階段在失敗時釋放資源回滾操作??筛鶕?jù)業(yè)務(wù)場景定制開發(fā),性能較高,減少資源占用時間。開發(fā)成本高,需實現(xiàn)三個方法,要處理異常和補償邏輯,實現(xiàn)復(fù)雜度大。適用于對性能要求高、業(yè)務(wù)邏輯復(fù)雜的場景,如電商系統(tǒng)訂單處理、庫存管理。
- Saga:將長事務(wù)拆分為多個短事務(wù),每個短事務(wù)有對應(yīng)的補償事務(wù)。某個短事務(wù)失敗,按相反順序執(zhí)行補償事務(wù)回滾系統(tǒng)狀態(tài)。性能較高,短事務(wù)可并行執(zhí)行減少時間,對業(yè)務(wù)侵入性小,只需實現(xiàn)補償事務(wù)。只能保證最終一致性,部分補償事務(wù)失敗可能導(dǎo)致系統(tǒng)狀態(tài)不一致。適用于業(yè)務(wù)流程長、對數(shù)據(jù)一致性要求為最終一致性的場景,如旅游系統(tǒng)訂單、航班、酒店預(yù)訂。
- 可靠消息最終一致性方案:基于消息隊列,業(yè)務(wù)系統(tǒng)執(zhí)行本地事務(wù)時將業(yè)務(wù)操作封裝成消息發(fā)至消息隊列,下游系統(tǒng)消費消息并執(zhí)行操作,失敗則消息隊列重試。實現(xiàn)簡單,對業(yè)務(wù)代碼修改小,系統(tǒng)耦合度低,能保證數(shù)據(jù)最終一致性。消息隊列可靠性和性能影響大,可能出現(xiàn)消息丟失或延遲,需處理消息冪等性。適用于對數(shù)據(jù)一致性要求為最終一致性、系統(tǒng)耦合度低的場景,如電商訂單支付、庫存扣減。
- 本地消息表:業(yè)務(wù)與消息存儲在同一個數(shù)據(jù)庫,利用本地事務(wù)保證一致性,后臺任務(wù)輪詢消息表,通過MQ通知下游服務(wù),下游服務(wù)消費成功后確認消息,失敗則重試。簡單可靠,無外部依賴。消息可能重復(fù)消費,需冪等設(shè)計。適用場景是異步最終一致性(如訂單創(chuàng)建后通知積分服務(wù))。
阿里的seata框架了解過嗎?
Seata 是開源分布式事務(wù)解決方案,支持多種模式:
AT模式:是 Seata 默認的模式,基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫。在 AT 模式下,Seata 會自動生成回滾日志,在業(yè)務(wù) SQL 執(zhí)行前后分別記錄數(shù)據(jù)的快照。當(dāng)全局事務(wù)需要回滾時,根據(jù)回滾日志將數(shù)據(jù)恢復(fù)到事務(wù)開始前的狀態(tài)。
TCC模式:需要開發(fā)者手動編寫 Try、Confirm 和 Cancel 三個方法。Try 方法用于對業(yè)務(wù)資源進行預(yù)留,Confirm 方法用于確認資源并完成業(yè)務(wù)操作,Cancel 方法用于在業(yè)務(wù)執(zhí)行失敗時釋放預(yù)留的資源。
SAGA 模式:將一個長事務(wù)拆分為多個短事務(wù),每個短事務(wù)都有一個對應(yīng)的補償事務(wù)。當(dāng)某個短事務(wù)執(zhí)行失敗時,會按照相反的順序執(zhí)行之前所有短事務(wù)的補償事務(wù),將系統(tǒng)狀態(tài)回滾到初始狀態(tài)。
算法
- 組合總和