這些并發編程技術你都知道嗎?

與其碌碌無為,不如興風作浪。


雖然不是所有的系統都需要很多的并發編程技術,但是掌握常見的高并發秘籍,便能讓我們的系統快起來,面對訪問量的劇增從容應對。
接下來,為我們一起來看看常見的高并發技術有哪些。總結起來,主要包括緩存、限流、熔斷降級、異步、池化、代碼優化、JVM調優、預熱、等。

緩存

主要包括本地緩存和分布式緩存。可以使用Redis和Caffeine等方式緩存數據,一般情況下分布式系統使用分布式緩存就可以了。對于高并發的系統,可以考慮多級緩存,但是要考慮內存以及數據一致性問題。
本地緩存:解決redis的熱key問題和提升性能;
分布式緩存:解決緩存容量和提升性能。

本地緩存

雖然redis號稱單節點能抗住10Wqps,但是開發過程中為了保險,會降低預期。那么如何發現這些熱點key呢?可以在開發的時候憑業務經驗估計,比如秒殺的商品信息。上線后,也可以隨時在客戶端進行收集。
Caffeine是基于java8實現的新一代緩存工具,緩存性能接近理論最優。可以看作是Guava Cache的增強版,功能上兩者類似,不同的是Caffeine采用了一種結合LRU、LFU優點的算法:W-TinyLFU,在性能上有明顯的優越性。

使用方式如下:

public class CaffeineCacheTest {public static void main(String[] args) throws Exception {//創建guava cacheCache<String, String> loadingCache = Caffeine.newBuilder()//cache的初始容量.initialCapacity(5)//cache最大緩存數.maximumSize(10)//設置寫緩存后n秒鐘過期.expireAfterWrite(17, TimeUnit.SECONDS)//設置讀寫緩存后n秒鐘過期,實際很少用到,類似于expireAfterWrite//.expireAfterAccess(17, TimeUnit.SECONDS).build();String key = "key";// 往緩存寫數據loadingCache.put(key, "value");// 獲取value的值,如果key不存在,獲取value后再返回String value = loadingCache.get(key, CaffeineCacheTest::getValueFromDB);// 刪除keyloadingCache.invalidate(key);}private static String getValueFromDB(String key) {return "value";}
}

分布式緩存

也就是引入redis中間件進行數據緩存。
image.png

使用Spring Cache進行商品類目數據緩存:

/*** 商品類目*/
@DubboService
@CacheConfig(cacheNames = CACHE_NAME_CATEGORY)
@Slf4j
public class CategoryFacadeServiceImpl implements ICategoryFacadeService {// 使用@Cacheable注解,它會將方法返回結果存儲在注解指定的緩存中@Override@Cacheablepublic List<CategoryResp> listAllCategory() throws ServiceException {log.info("查詢所有類目開始");return allCategory;}// @CacheEvict 注解來表示刪除一個、多個或所有的值,以刷新緩存@Override@Transactional(rollbackFor = Exception.class)@CacheEvict(cacheNames = CACHE_NAME_CATEGORY, allEntries = true)public Long saveAndUpdate(@NotNull CategoryReq req) throws ServiceException {log.info("新增或修改類目開始CategoryReq{}", req);return result;}@Override@Transactional(rollbackFor = Exception.class)@CacheEvict(cacheNames = CACHE_NAME_CATEGORY, allEntries = true)public boolean deleteCategory(@NotNull Long id) throws ServiceException {log.info("開始刪除類目");return flag&&mappingFlag;}
}

多級緩存

通過新增本地緩存,可用使得流量在應用層直接返回,避免進一步訪問Redis。大大提高數據讀取的效率,但是成本也是很高的。

  • 內存要求:需要在應用服務器同于數據,需要提高應用服務器的內存;
  • 數據一致性:需要保證多級緩存之間,各個本地緩存之間數據的一致性。

需要重具體的業務場景觸發,兼顧以下三個方面考慮是否需要本地緩存:

  • 并發量
  • 內存情況
  • 變更是否頻繁

image.png

限流

限流是為了保護系統的可用性而做出的一種妥協,通過減低請求成功的數量,保證重要功能的可用。需要通過壓測預估系統可承載的并發量。在系統資源緊張的情況下,保證系統的可用性。
可通過sentinel實現限流,經典算法包括令牌桶,漏桶,滑動時間窗口等。

熔斷降級

熔斷降級是分布式系統中常用的兩種保護機制,旨在提高系統的穩定性和可用性。以下是關于熔斷降級的詳細解釋:

熔斷

定義:熔斷類似于電路中的保險絲,當某個異常條件被觸發時,直接熔斷整個服務,防止系統因某個服務的故障而導致整體服務失敗。
觸發條件:熔斷的觸發條件通常與服務調用的失敗率、請求超時等有關。例如,在Spring Cloud的Hystrix組件中,如果檢測到10秒內請求的失敗率超過50%,則觸發熔斷機制。
作用:熔斷機制通過快速失敗和快速恢復,防止在復雜分布式系統中出現級聯故障,從而提高系統的整體彈性。

降級

定義:降級是指在系統壓力劇增或出現故障時,根據當前業務情況及流量,對一些服務和頁面進行有策略的降級,以此緩解服務器資源的壓力,保證核心業務的正常運行。
觸發條件:降級的觸發條件通常包括服務超時、失敗次數、故障、限流等。在Hystrix中,降級可以在方法拋出異常、方法調用超時、熔斷器開啟攔截調用、線程池或隊列或信號量已滿等情況下觸發。
目的:降級的目的是在系統出現問題時,仍能保證有限功能可用,提供一種退而求其次的解決方案。例如,在電商交易系統中,當系統負載過高時,可以開啟降級功能,優先保證支付功能可用,而其他非核心功能如評論、物流、商品介紹等可以暫時關閉。

熔斷與降級的區別

概念不同:熔斷是當服務出現故障時,直接熔斷整個服務,防止系統因某個服務的故障而導致整體服務失敗;而降級是在系統壓力劇增或出現故障時,通過關閉部分非核心功能來保證核心業務的正常運行。
觸發條件不同:熔斷的觸發條件通常與服務調用的失敗率、請求超時等有關;而降級的觸發條件則包括服務超時、失敗次數、故障、限流等。
歸屬關系不同:熔斷時可能會調用降級機制,因為熔斷是從全局出發,為了保證系統穩定性而停用服務;而降級是退而求其次,提供一種保底的解決方案。
常見的降級類型包括:大促非核心的接口降級;日志降級等。

異步

主要涉及到如何讓程序在執行某些可能耗時的操作時,不會阻塞主線程,從而提高程序的響應性和性能。主要策略包括多線程和消息隊列等。
系統解耦:對于不需要客戶感知結果的部分,可通過消息的方式完成后續處理,完成后通知客戶結果。不需要阻塞客戶一直等待。
提升性能:對于一些查詢操作,可能設置多個獨立的數據內容,這種情況可以使用CompletableFuture進行一步任務編排,提升查詢效率。
下面是通過任務編排實現商品屬性查詢的案例:

CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {System.out.println("查詢商品的圖片信息");return "hello.jpg";
});CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {System.out.println("查詢商品的屬性");return "黑色";
});CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println("查詢商品介紹");return "華為";
});// 等待全部執行完
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
//        allOf.get();// 只需要有一個執行完
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
anyOf.get();
System.out.println("main....end....." + anyOf.get());

池化技術

池化技術主要用于避免頻繁創建和銷毀昂貴資源(如數據庫連接、線程、大對象等)所帶來的性能開銷。通過預先創建一定數量的資源并維護在一個池中,當需要時從池中獲取資源使用,使用完畢后歸還到池中而不是直接銷毀,可以顯著提高應用程序的效率和響應速度。
下面是一些典型的Java池化技術實例:

  • 數據庫連接池
    • 實現庫:Apache DBCP, C3P0, HikariCP, Tomcat JDBC Pool等。
    • 作用:管理數據庫連接,避免了每次數據庫操作都新建和銷毀連接的開銷。
  • 線程池
    • 實現庫:java.util.concurrent.ExecutorService接口及其實現類,如ThreadPoolExecutor。
    • 作用:預先創建一定數量的線程,將任務提交給線程池處理,提高了并發處理能力,同時也限制了系統創建過多線程導致的資源耗盡風險。
  • 對象池
    • 實現庫:Apache Commons Pool。
    • 作用:適用于任何需要重用的對象,如大對象、網絡連接、圖形對象等,減少垃圾回收壓力和創建對象的成本。
  • 緩沖池(Buffer Pool)
    • 在某些IO密集型應用中,如NIO(非阻塞I/O)編程,通過重用緩沖區可以提升讀寫效率。

使用池化技術的關鍵在于合理配置池的大小,過大可能導致資源浪費,過小則可能因為資源爭搶而影響性能。此外,池化技術還需要考慮資源的分配與回收策略、超時處理、異常處理等機制,確保資源的有效管理和利用。

代碼優化

通過優化代碼邏輯,減少調用鏈路,減少數據庫查詢次數,提前校驗流程。

JVM調優

主要是系統根據業務情況和機器配置設置合理的JVM參數。

預熱

通過執行定時任務等方式提前將數據加載到緩存。通過預熱,能夠避免緩存剛開始沒有數據時全量請求查數據庫的行為。
如果秒殺要走正常的加入購物車流程,然后去來鎖庫存,最終去支付,這樣整個流程太慢了,在高并發系統里邊肯定會出現整個級聯崩潰的情況。我們應該先做到預熱庫存,比如現在要秒殺的商品,數量有400件,我們給 redis 里面存一個 400 的信號量,想要秒殺的人進來之后,必須要先拿到信號量,這一塊我們會對 redis 的信號量進行快速扣減,直接扣減1個數,所以無論有多少請求進來,即使有百萬請求,最終也只有 400個人能拿到這個信號量的值。然后我們會將這 400 個人放行給我們后臺的集群系統,這些請求即使走正常的下單邏輯,系統也不會出現什么問題。

如果是單臺機器,也可以使用一些簡單的辦法實現,但是不太靈活。比如:

監聽啟動事件

  • 使用ApplicationListener監聽ContextRefreshEvent或ApplicationReadyEvent等應用上下文初始化完成事件,在這些事件觸發后執行數據加載的操作。
@Component
public class CacheWarmer implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {// 執行緩存預熱業務...cacheManager.put("key", dataList);}
}
@Component
public class CacheWarmer implements ApplicationListener<ApplicationReadyEvent> {@Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {// 執行緩存預熱業務...cacheManager.put("key", dataList);}
}

PostConstuct注解

該注解是Java jdk提供的注解,而不是Spring框架提供的。該注解的功能是當依賴注入完成后用于執行初始化的方法,并且只會被執行一次

@Component
public class CachePreloader {@Autowiredprivate YourCacheManager cacheManager;// 注解@PostConstructpublic void preloadCache() {// 執行緩存預熱業務...cacheManager.put("key", dataList);}
}

實現InitializingBean接口

InitializingBean是Spring提供的拓展性接口,為bean提供了屬性初始化后的處理方法,它唯一的方法便是afterPropertiesSet,凡是實現該接口的類,在bean屬性初始化后都會執行該方法。

@Component
public class CachePreloader implements InitializingBean {@Autowiredprivate YourCacheManager cacheManager;@Overridepublic void afterPropertiesSet() throws Exception {// 執行緩存預熱業務...cacheManager.put("key", dataList);}
}

hi,你好,我是松語。985軟件工程研究生畢業,一個工作三年的程序員。

這里有:

  1. 技術分享,包括編程技巧和踩坑記錄等;
  2. 求職經驗,校招、副業、社招跳槽經驗等;
  3. 詩和遠方。

親愛的你,切莫辜負有夢想的自己,萍水相逢的感情,以及良辰美景好時光。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/38271.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/38271.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/38271.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SSH版本升級-openssh-9.7p1

SSH版本升級-openssh-9.7p1 1、查看當前版本2、安裝openssl2.1、編譯安裝ssl 3、下載新版本SSH4、備份原有的SSH配置5、上傳文件并解壓6、卸載原有的openssh包7、編譯安裝openssh7.1、在解壓后的目錄&#xff0c;初始化openssh7.2、將文件拷回7.3、修改配置文件 最終實現&#…

linux系統中給java 應用配置開機自動啟動

第一步需要一個控制java應用啟動&#xff0c;停止&#xff0c;重啟的腳本&#xff0c;腳本內容如下&#xff0c;我是springboot應用&#xff0c;其他的可以根據情況改寫. #!/bin/bashAPP_NAME/data/oa/start-2.0.jar #執行命令有誤時&#xff0c;提示使用說明參數 usage() {ec…

DDD學習筆記五

模型引力場&#xff1a;聚合 強作用力體現&#xff1a; 某個領域模型是另一些模型存在的前提&#xff0c;沒有前者&#xff0c;后者就失去了生存的意義。 一組領域模型之間存在關聯的領域邏輯&#xff0c;任何時候都不能違反。 一組領域模型必須以一個完整的、一致的狀態呈現給…

CSDN寫文章時需要上、下標字號怎么輸?

上標&#xff1a;?^^&#xff0c;符號中間加字 下標&#xff1a;~~&#xff0c;符號中間加字 前題是用MD編輯器&#xff0c;不然白搭&#xff1a; 我是感覺CSDN這個文本編輯比較拉&#xff0c;非常想吐槽。

dB分貝入門

主要參考資料&#xff1a; dB&#xff08;分貝&#xff09;定義及其應用: https://blog.csdn.net/u014162133/article/details/110388145 目錄 dB的應用一、聲音的大小二、信號強度三、增益 dB的應用 一、聲音的大小 在日常生活中&#xff0c;住宅小區告知牌上面標示噪音要低…

vue2 element ui 表單 動態增加表單項 表單項值不可重復 select多選

案例 <template><el-form :model"form" ref"form" label-width"70px"><el-form-item><el-button icon"el-icon-plus" type"primary" plain click"add">新增</el-button><el-b…

VUE3-Elementplus-form表單-筆記

1. 結構相關 el-row表示一行&#xff0c;一行分成24份 el-col表示列 (1) :span"12" 代表在一行中&#xff0c;占12份 (50%) (2) :span"6" 表示在一行中&#xff0c;占6份 (25%) (3) :offset"3" 代表在一行中&#xff0c;左側margin份數 el…

后勞動經濟學(PLE):AI時代的工作未來

引言 隨著人工智能&#xff08;AI&#xff09;和自動化技術的飛速發展&#xff0c;我們迎來了一個新的經濟范式——后勞動經濟學&#xff08;PLE&#xff09;。這一概念主要討論在AI和自動化技術超越人類能力的關鍵領域后&#xff0c;機器將不可避免地在許多經濟活動中取代人類…

如何玩單機版:QQ音速

前言 我是研究單機的老羅&#xff0c;今天教大家帶來一款懷舊游戲QQ音速 的教程。根據我的文章&#xff0c;一步一步就可以玩了。 如今市面上的資源參差不齊&#xff0c;大部分的都不能運行&#xff0c;本人親自測試&#xff0c;運行視頻如下&#xff1a; QQ音速 搭建教程 此…

python之GIL鎖詳解

目錄 1.GIL是什么以及影響 2.為什么會有GIL鎖&#xff1f; 1.GIL是什么以及影響 在Python中&#xff0c;多線程的并發性受到全局解釋器鎖&#xff08;GIL&#xff0c;Global Interpreter Lock&#xff09;的影響。GIL是CPython&#xff08;Python的官方實現&#xff09;中的…

vscode下無法識別node、npm的問題

node : 無法將“node”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱 因為node是在cmd安裝的&#xff0c;是全局安裝的&#xff0c;并不是在這個項目里安裝的。 解決方案&#xff1a; 1.在vscode的控制臺&#xff0c;針對一個項目安裝特定版本的node&#xff1b; 2.已經…

C++(Python)肥皂泡沫普拉托邊界膜曲面模型算法

&#x1f3af;要點 &#x1f3af;肥皂泡二維流體模擬 | &#x1f3af;泡沫普拉托邊界膜曲面模型算法演化厚度變化 | &#x1f3af;螺旋曲面三周期最小結構生成 &#x1f4dc;皂膜用例&#xff1a;Python計算物理粒子及拉格朗日和哈密頓動力學 | Python和MATLAB粘性力接觸力動…

SAP系統中的應收賬款(客戶主數據,日常交易,催收,爭議管理)

1. 客戶主數據 Customer Accounts (客戶賬戶&#xff09;:客戶賬戶由兩部分General Data&#xff08;通用數據&#xff09;和Company Code Data&#xff08;公司代碼段數據&#xff09;組成。通用數據是在client級別獨立于公司代碼的數據&#xff0c;例如客戶的地址&#xff0…

鴻蒙開發設備管理:【@ohos.multimodalInput.inputEventClient (注入按鍵)】

注入按鍵 InputEventClient模塊提供了注入按鍵能力。 說明&#xff1a; 本模塊首批接口從API version 8開始支持。后續版本的新增接口&#xff0c;采用上角標單獨標記接口的起始版本。本模塊接口均為系統接口&#xff0c;三方應用不支持調用。 導入模塊 import inputEventCli…

愛情再啟:莊國棟笑談“玫瑰人生”愛情覺悟

莊國棟&#xff0c;這位電視劇《玫瑰的故事》中的男主角&#xff0c; 最近在一次采訪中坦言&#xff1a;“如果給我一次重來的機會&#xff0c; 我絕對會毫不猶豫地選擇愛情&#xff01;” 聽到這話&#xff0c; 我不禁想&#xff0c;莊先生&#xff0c;您是不是被劇里的玫瑰…

Solidworke學習(裝配體3)

目錄 本節學習內容&#xff1a; 一、高級配合 &#xff08;1&#xff09;對稱配合 &#xff08;2&#xff09;寬度配合 &#xff08;3&#xff09;距離配合 二、機械配合 &#xff08;1&#xff09;凸輪配合 &#xff08;2&#xff09;槽口配合 三、快捷菜單 本節學習…

python工作目錄與文件目錄

工作目錄 文件目錄&#xff1a;文件所在的目錄 工作目錄&#xff1a;執行python命令所在的目錄 D:. | main.py | ---data | data.txt | ---model | | model.py | | train.py | | __init__.py | | | ---nlp | | | bert.py | …

計算機網絡期末復習(大題+小題)

計算機網絡期末復習 一、計算機網絡概述 Point 1 計算機網絡就是以傳輸信息為基本目的&#xff0c;用通信線路和通信設備將多個計算機連接起來的計算機系統的集合。由自治的計算機互聯起來的結合體。 Point 2 按網絡的覆蓋范圍進行分類 &#xff08;1&#xff09;局域網*…

解鎖Transformer的魯棒性:深入分析與實踐指南

&#x1f6e1;? 解鎖Transformer的魯棒性&#xff1a;深入分析與實踐指南 Transformer模型自從由Vaswani等人在2017年提出以來&#xff0c;已經成為自然語言處理&#xff08;NLP&#xff09;領域的明星模型。然而&#xff0c;模型的魯棒性——即模型在面對異常、惡意或不尋常…

人機交互新維度|碩博電子發布雙編碼器操作面板、無線操作面板等新品

6月15日&#xff0c;碩博電子召開了一場新品發布會&#xff0c;向業界展示了多項前沿技術成果&#xff0c;其中備受矚目的當屬SPM-KEYP-D08雙編碼器操作面板、SPM-KEYP-D16W無線操作面板、SPR-HT-XK12A無線手持發射端以及SPQ-WT-B01灑水車專用控制面板。這些創新產品的亮相&…