面試官:說說你項目有什么亮點?
在當前嚴峻的就業(yè)形勢下,項目如果沒什么亮點,可能連面試的機會都沒有,但實際工作中,大部分人所做的事就是 CRUD(增刪改查),那怎么才能即很好的體現(xiàn)我們的技術(shù)實力?又不會被面試官識破呢?
所以,今天我這個給大家提供一些通用的項目亮點,你學(xué)會之后可以應(yīng)用到自己的項目中,這樣這個棘手的問題就可以搞定了。因為內(nèi)容比較長,所以咱們就分為上、下兩篇來寫。不過大家記得:先點贊再觀看,以后再看找的見哦。
亮點1:并發(fā)編程+任務(wù)編排
1.1 并發(fā)編程
并發(fā)編程通常用在處理大量數(shù)據(jù)或者執(zhí)行多個獨立任務(wù)時,可以創(chuàng)建多個線程來并行處理,以提高效率和響應(yīng)速度。
并發(fā)編程常見案例:例如 BI(Business Intelligence,商業(yè)智能系統(tǒng))系統(tǒng),一種集成了數(shù)據(jù)倉庫、查詢報表、數(shù)據(jù)分析、數(shù)據(jù)挖掘、數(shù)據(jù)可視化等多種功能的軟件工具,用于幫助企業(yè)從大量數(shù)據(jù)中提取有價值的商業(yè)信息,以支持決策制定。BI 系統(tǒng)通常需要從多個(微服務(wù))數(shù)據(jù)源并行導(dǎo)入大量數(shù)據(jù),這樣我們就可以利用多線程同時導(dǎo)入數(shù)據(jù),這樣可以顯著減少總的導(dǎo)入時間。
多線程具體實現(xiàn):在 Spring Boot 中定義全局線程池,實現(xiàn)代碼如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
publicclass ThreadPoolConfig {
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(100000); // 任務(wù)隊列:10w
taskExecutor.setThreadNamePrefix("my-threadpool-");
// 自定義拒絕策略【1.記錄錯誤信息。2.通知消息系統(tǒng),發(fā)送告警信息】
taskExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 1.記錄錯誤信息
// 2.通知消息系統(tǒng),發(fā)送告警信息
}
});
taskExecutor.initialize();
return taskExecutor;
}
}
多線程使用代碼示例:
@Resource
private ThreadPoolTaskExecutor taskExecutor;
1.2 任務(wù)編排
任務(wù)編排常見案例和具體實現(xiàn):以上 BI 系統(tǒng)再抽取多個數(shù)據(jù)源之后,需要對數(shù)據(jù)進行整合、處理和入庫,在這種場景下就需要使用 CompletableFuture 來進行任務(wù)編排。
任務(wù)編排具體實現(xiàn):使用 CompletableFuture,它是 JDK 8 提供的線程編排工具,它的常用方法有以下幾個:
圖片
例如,我們現(xiàn)在實現(xiàn)一個這樣的場景:
圖片
任務(wù)描述:任務(wù)一執(zhí)行完之后執(zhí)行任務(wù)二,任務(wù)三和任務(wù)一和任務(wù)二一起執(zhí)行,所有任務(wù)都有返回值,等任務(wù)二和任務(wù)三執(zhí)行完成之后,再執(zhí)行任務(wù)四,它的實現(xiàn)代碼如下:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
publicclass CompletableFutureExample {
public static void main(String[] args) {
// 任務(wù)一:返回 "Task 1 result"
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
try {
// 模擬耗時操作
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
thrownew RuntimeException(e);
}
return"Task 1 result";
});
// 任務(wù)二:依賴任務(wù)一,返回 "Task 2 result" + 任務(wù)一的結(jié)果
CompletableFuture<String> task2 = task1.handle((result1, throwable) -> {
try {
// 模擬耗時操作
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
thrownew RuntimeException(e);
}
return"Task 2 result " + result1;
});
// 任務(wù)三:和任務(wù)一、任務(wù)二并行執(zhí)行,返回 "Task 3 result"
CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> {
try {
// 模擬耗時操作
Thread.sleep(800); // 任務(wù)三可能比任務(wù)二先完成
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
thrownew RuntimeException(e);
}
return"Task 3 result";
});
// 任務(wù)四:依賴任務(wù)二和任務(wù)三,等待它們都完成后執(zhí)行,返回 "Task 4 result" + 任務(wù)二和任務(wù)三的結(jié)果
CompletableFuture<String> task4 = CompletableFuture.allOf(task2, task3).handle((res, throwable) -> {
try {
// 這里不需要顯式等待,因為 allOf 已經(jīng)保證了它們完成
return"Task 4 result with " + task2.get() + " and " + task3.get();
} catch (InterruptedException | ExecutionException e) {
thrownew RuntimeException(e);
}
});
// 獲取任務(wù)四的結(jié)果并打印
String finalResult = task4.join();
System.out.println(finalResult);
}
}
亮點2:多級緩存
“
定義:多級緩存是指在系統(tǒng)中設(shè)置多個層次的緩存,每個層次的緩存具有不同的特性,它們協(xié)同工作來滿足系統(tǒng)對數(shù)據(jù)訪問速度和存儲容量等多方面的需求。
圖片
使用多級緩存可以從離用戶請求最近的地方優(yōu)先獲取緩存信息,從而保證了更高的查詢效率,多級緩存包括以下這些:
- 分布式緩存:例如,Redis、MemCached 等。
- 本地緩存:例如,Caffeine、Google Guava Cache、Spring Cache、Ehcache 等。
- Nginx 緩存:在 Nginx 中配置并開啟緩存功能。
- CDN 緩存:是一種通過在離用戶更近的位置存儲數(shù)據(jù)副本,以提供更快速、高效地內(nèi)容交付的技術(shù)。CDN緩存使用分布式網(wǎng)絡(luò)和邊緣節(jié)點來緩存和分發(fā)靜態(tài)和動態(tài)內(nèi)容,以減少用戶請求的響應(yīng)時間和帶寬消耗。
- 瀏覽器緩存:它的實現(xiàn)主要依靠 HTTP 協(xié)議中的緩存機制,當瀏覽器第一次請求一個資源時,服務(wù)器會將該資源的相關(guān)緩存規(guī)則(如 Cache-Control、Expires 等)一同返回給客戶端,瀏覽器會根據(jù)這些規(guī)則來判斷是否需要緩存該資源以及該資源的有效期。
亮點3:緩存和數(shù)據(jù)庫一致性問題解決
項目中使用緩存時會有 4 大經(jīng)典的問題(雪崩、穿透、擊穿、數(shù)據(jù)一致性),其中一個就是【緩存和數(shù)據(jù)庫一致性問題】,所以在實際工作中解決了這個經(jīng)典問題,也是一大亮點。
緩存和數(shù)據(jù)庫一致性問題的常見解決方案有兩個:
- 使用延遲雙刪+MQ。
- Canal 監(jiān)聽 MySQL Binlog 保證數(shù)據(jù)一致性:Canal 監(jiān)聽 binlog,再將數(shù)據(jù)庫更新到 MQ(如 Kafka)中,再通過監(jiān)聽消息更新 Redis 緩存,Canal 執(zhí)行流程如下:
圖片
亮點4:自定義注解解決冪等性問題
使用了自定義注解實現(xiàn)了一些通用功能,例如,使用自定義注解實現(xiàn)冪等性處理、使用自定義注解實現(xiàn)了統(tǒng)一數(shù)據(jù)權(quán)限的驗證等。
亮點5:分庫分表技術(shù)
如項目中使用了分庫分表技術(shù)增加數(shù)據(jù)庫的并發(fā)處理性能,典型的技術(shù)實現(xiàn)有 MyCat 和 ShardingSphere。
分庫分表技術(shù)介紹
首先來說,“分庫分表”不是一個技術(shù),而是多個技術(shù)實現(xiàn):
- 分庫
- 垂直分庫
- 水平分庫
- 分表
- 垂直分表
- 水平分表
① 垂直分庫
垂直分庫是按照業(yè)務(wù)將不同的表拆分到不同的數(shù)據(jù)庫中。例如,在一個電商數(shù)據(jù)庫中的用戶表和訂單表分別存放到不同的數(shù)據(jù)庫中,如下圖所示:
圖片
② 水平分庫
水平分庫是將數(shù)據(jù)按照一定的規(guī)則(如用戶 ID 取模、哈希等)分布到不同的數(shù)據(jù)庫中。比如,根據(jù)用戶 ID 對 10 取模,將用戶數(shù)據(jù)分布到 10 個不同的數(shù)據(jù)庫中,每個數(shù)據(jù)庫都保存著完整的數(shù)據(jù)表結(jié)構(gòu),如下圖所示:
圖片
③ 垂直分表
分表:
圖片
垂直分表:垂直分表是將一張表按照列的相關(guān)性拆分成多張表。例如,將一個包含大量字段的用戶表,拆分為用戶基本信息表和用戶擴展信息表,如下圖所示:
圖片
④ 水平分表
水平分表是將一張表的數(shù)據(jù)按照行進行拆分。例如按照用戶 ID 的范圍或者哈希值將數(shù)據(jù)拆分到不同的表中。
圖片
在實際業(yè)務(wù)中,各種分庫分表技術(shù)可以混合使用。
MyCat VS Sharding Sphere
分庫分表的主流實現(xiàn)技術(shù)有以下兩種:
- MyCat
- Apache Sharding Sphere
Sharding Sphere 相比于 MyCat 來說,它的優(yōu)勢是:
- 功能更多:除了讀寫分離和分庫分表之外,還提供了數(shù)據(jù)加密、流量質(zhì)量、數(shù)據(jù)遷移等功能。
- 社區(qū)更活躍度和生態(tài)更好:Sharding Sphere 擁有活躍的社區(qū)和豐富的文檔,生態(tài)系統(tǒng)較為完善,有更多的用戶和開發(fā)者參與。
- 靈活性和擴展性:Sharding Sphere 靈活性更高,擴展性也更好,它可以方便地與其他技術(shù)集成,這方便 MyCat 支持的比較有限。
亮點6:項目中使用多種設(shè)計模式
例如以下這些設(shè)計模式:
- 責任鏈模式:在請求進入后端項目之后,會經(jīng)過多個責任鏈攔截器(或過濾器),先鑒權(quán)、黑白名單效驗、參數(shù)效驗、敏感詞過濾等操作之后,才能進行后續(xù)的訪問和操作。
- 策略模式:支付功能會根據(jù)用戶不同的選擇,使用對應(yīng)的支付代碼實現(xiàn)支付功能。
- 模版方法模式:支付功能實現(xiàn)上,首先在接口中定義支付的基本流程,而具體的支付方式(如信用卡支付、三方平臺支付等)則由子類實現(xiàn)。
- 裝飾器模式:在不更改原功能的基礎(chǔ)上,添加新的功能。例如,項目中方法的統(tǒng)計,不更改原來的方法執(zhí)行,在方法執(zhí)行前后添加了執(zhí)行統(tǒng)計記錄功能。
- 代理模式:日志代理功能的實現(xiàn),在執(zhí)行目標對象的方法前后記錄日志,用于監(jiān)控和調(diào)試。
- 生產(chǎn)者消費者模式:使用 MQ 實現(xiàn)生產(chǎn)者和消費者模式,處理異步任務(wù)。
- 建造者模式:實現(xiàn)類對象的創(chuàng)建和初始化。
- 單例模式:項目中的數(shù)據(jù)源、線程池等都使用了單例模式保證了資源的高效使用。
小結(jié)
因為亮點內(nèi)容比較長,所以咱們就分為上、下兩篇來寫,各位老鐵點贊、收藏先。