Redis打包事務,分批提交

一、需求背景

??????接手一個老項目,在項目啟動的時候,需要將xxx省整個省的所有區域數據數據、以及系統字典配置逐條保存在Redis緩存里面,這樣查詢的時候會更快;
??????區域數據+字典數據一共大概20000多條,,前同事直接使用 list.forEach()逐條寫入Redis,如下:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
/*** @author xxx* @version 1.0* @date 2022/7/21 15:29* @Description: 項目啟動成功后初始化區域數據到redis*/
@Component
@Slf4j
public class AreasInitialComponent implements ApplicationRunner {@AutowiredprivateAreaMapper areaMapper;private static boolean isStart = false;/*** 項目啟動后,初始化字典到緩存*/@Overridepublic void run(ApplicationArguments args) throws Exception {if (isStart) {return;}try {log.info("Start*******************項目啟動后,初始化字典到緩存*******************");QueryWrapper<Area> wrapper = new QueryWrapper<>();wrapper.eq("del", "0");List<Area> areas = areaMapper.selectList(wrapper);if (!CollectionUtils.isEmpty(areas )) {RedisCache redisCache = SpringUtils.getBean(RedisCache.class);//先將區域集合整體做個緩存log.info("*******************先將區域集合整體做個緩存*******************");AreaUtil.setAreaListCache(redisCache, areas);//再將每一條區域進行緩存areas.stream().forEach(a -> {AreaUtil.setAreaCache(redisCache, a.getId(), a);});}isStart = true;log.info("End*******************項目啟動后,初始化字典到緩存*******************");}catch (Exception e) {e.printStackTrace();}}
}

image.png

導致項目啟動速度巨慢,再加上需要使用代理軟件才能連接公司的數據庫,每次啟動項目都需要10幾分鐘,當真是苦不堪言;由于受不了這樣的啟動速度,因此決定自己動手優化。

二、解決思路

??????聯想到MySQL的事務打包方式,于是自己動手嘗試通過Redis打包事務+分批提交的方式來提高啟動速度,具體實現如下:

三、實現方法

  1. 實現方法
   @Autowiredpublic RedisTemplate redisTemplate;  /*** 逐條設置區域緩存** @param areas* @throws InterruptedException*/public void setAreaCacheItemByItem(List<Area> areas) throws InterruptedException {MoreThreadCallBack<Area> callBack = new MoreThreadCallBack<>();callBack.setThreadCount(10);callBack.setLimitCount(50);callBack.setTitle("設置區域緩存批量任務");callBack.setAllList(areas);callBack.call((list, threadNum) -> {//使用自定義線程回調工具分攤任務redisTemplate.execute(new SessionCallback<Object>() {@Overridepublic Object execute(RedisOperations operations) throws DataAccessException {//開啟redis事務operations.multi();list.forEach(item -> {operations.opsForValue().set(item.getId(), item);});// 提交事務operations.exec();return null;}});});}
  1. 線程回調工具MoreThreadCallBack()
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;@Data
@Slf4j
public class MoreThreadCallBack<P> {public int limitCount = 1000;private int threadCount = 10;private List<P> allList;private AtomicInteger errorCheck;private String title;public interface CallBack<P> {void call(List<P> list, Integer threadNum);}public boolean call(CallBack<P> callBack) throws InterruptedException, RuntimeException {if (allList.isEmpty()) {return false;}// 線程池ExecutorService exec = Executors.newCachedThreadPool();// 根據大小判斷線程數量if (allList.size() <= limitCount) {threadCount = 1;}// 等待結果類final CountDownLatch countDownLatch = new CountDownLatch(threadCount);// 分攤多份List<List<P>> llist = Lists.newArrayList();for (int i = 0; i < threadCount; i++) {llist.add(Lists.newArrayList());}int index = 0;for (P p : allList) {llist.get(index).add(p);index = index == (threadCount - 1) ? 0 : index + 1;}// 異常記錄errorCheck = new AtomicInteger(0);// 執行for (int i = 0; i < llist.size(); i++) {List<P> list = llist.get(i);final Integer threadNum = i;exec.execute(() -> {long startTime = System.currentTimeMillis();//拋出異常 自身不處理log.info("標題:{}-{}號線程開始回調執行 數量:{}", this.getTitle(), threadNum, list.size());callBack.call(list, threadNum);long endTime = System.currentTimeMillis();log.info("標題:{}-{}號線程回調執行完畢 耗時:{}", this.getTitle(), threadNum, +(endTime - startTime));countDownLatch.countDown();});}// 等待處理完畢countDownLatch.await();// 關閉線程池exec.shutdown();return errorCheck.get() <= 0;}public boolean next() {// 檢測是否有線程提前結束if (errorCheck.get() > 0) {return false;}return true;}public void error() {errorCheck.incrementAndGet();}public String getTitle() {return title == null ? "" : title;}
}
  1. 經過如上處理以后,項目啟動速度大大提升,由原本的10幾分鐘縮短至1分鐘左右,成果如下:
    image.png

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

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

相關文章

Windows安裝MongoDB

1、下載MongoDB的zip&#xff0c;解壓 2、創建目錄 mkdir D:\JavaSoftware\Database\MongoDB\mongodb-win32-x86_64-windows-5.0.8\data\db mkdir D:\JavaSoftware\Database\MongoDB\mongodb-win32-x86_64-windows-5.0.8\data\log 3、創建一個配置文件mongod.cfg&#xff0c…

使用一個接口的結果作為第二個接口的參數并將兩者的數據放置成下拉框的格式

背景 我使用下拉框實現選擇id 但是只有兩個接口 一個是所有的id 另一個是id對應的具體信息 我想把id傳入另一個接口并且獲取其name然后寫成類似這樣的數組 [ { value: 1, label: ‘名稱1’ }&#xff0c; { value: 2, label: ‘名稱2’ } { value: 3, label: ‘名稱3’ } ] 然…

【PPspliT】ppt轉pdf-保留過渡動畫

網址 http://www.maxonthenet.altervista.org/ppsplit.php 下載安裝 使用 再次打開ppt&#xff0c;就能在上方的選項欄里頭看到了&#xff1a;

GEE生物量碳儲量——利用紅和近紅外波段和OTSU大津法提取純凈森林面積

簡介: 如何利用紅和近紅外波段和OTSU大津法提取純凈森林面積?本文的主要邏輯是利用特定時期的遙感影像的波段,提取指定范圍的內的DN值,然后分別統計發生閾值變化的峰值區域,從而作為篩選森林的臨界點,如果研究區較大的話則需要先進行影像分割,分割成為相同大小的區域,…

前端開發Java學習

注釋&#xff1a; 單行注釋 // 多行注釋 /* */ 文件注釋 /** */ 1 關鍵字 &#xff08;關鍵字一定是小寫&#xff09; 2 常量 字符串常量"HelloWord","你好世界"整數常量12&#xff0c;-33小數常量3.14&#xff0c;22.1字符常量A&#xff0c;a &…

不是默認進入Linux|總是自動進入windows系統

問題描述 不是默認進入Linux系統無法主動出現boot引導自動進入windows系統 嘗試無效 修復引導無效重裝Grub無效重裝系統無效 環境 Ubuntu 22.04 LST微星主板 解決方案 修改引導順序&#xff1a; 開機狂按Del鍵&#xff0c;進入BIOS系統&#xff0c;左側Settings 設置&…

src和href的區別

前言 持續學習總結輸出中&#xff0c;src和href都是HTML中特定元素的屬性&#xff0c;都可以用來引入外部的資源。兩者區別如下&#xff1a; 1、作用 href 用于在當前文檔和引用資源之間確立聯系。 src 用于替換當前內容。 2、范圍用途 src&#xff08;source&#xff09…

RabbitMQ基礎教程

1.什么是消息隊列 消息隊列&#xff08;Message Queue&#xff09;&#xff0c;我們一般簡稱為MQ。消息隊列中間件是分布式系統中重要的組件&#xff0c;具有異步性、松耦合、分布式、可靠性等特點。用于實現高性能、高可用、可伸縮和最終一致性架構。是大型分布式系統不可缺少…

Angular11 MSAL B2C登錄實例 (一)

前言 因為項目需求&#xff0c;需要把Angular 11項目中登錄方式改成B2C登錄&#xff0c;所以在參考了一系列文檔后&#xff0c;成功通過MSAL將項目的登錄方式改成B2C登錄。下面介紹了詳細步驟及一些注意事項。 步驟&#xff1a; 1. 安裝MSAL 在項目中安裝msal npm i azure/…

BUUCTF [WUSTCTF2020]find_me 1

BUUCTF:https://buuoj.cn/challenges 題目描述&#xff1a; 得到的 flag 請包上 flag{} 提交。 感謝 Iven Huang 師傅供題。 比賽平臺&#xff1a;https://ctfgame.w-ais.cn/ 密文&#xff1a; 下載附件&#xff0c;得到一個.jpg圖片。 解題思路&#xff1a; 1、得到一張圖…

vue中頁面(路由)跳轉及傳值的幾種方式 router-link + query + params

vue中頁面(路由)跳轉及傳值的幾種方式 知道query 和 params 是什么 參考文案:https://www.php.cn/js-tutorial-382859.html 跳轉的幾種方式與傳值 1、router-link 1.1 根據路由路徑(無參數與有參數) <router-link to = "/page">跳轉到page頁面</…

Java WebSocket 客戶端接收大量數據

介紹 WebSocket 是一種基于 TCP 協議的全雙工通信協議&#xff0c;它能夠在客戶端和服務器之間建立一個持久連接&#xff0c;實現實時的雙向數據傳輸。在實際應用中&#xff0c;有時候我們需要處理大量的數據&#xff0c;例如實時監控系統或者實時股票行情等。本文將介紹如何使…

Matlab三角剖分插值問題分析

目錄 前言 一、問題引入 二、一個例子 1.生成散點圖 2.對數據進行剖分 3.點法式分析 三、最后結果 前言 上一篇文章感覺對三角剖分問題沒有說清楚&#xff0c;這次專門對三角剖分問題再仔細說說。 一、問題引入 實際上這個問題是用來解決二維曲面插值問題的。 二維插值問題&…

外部中斷為什么會誤觸發?

今天在寫外部中斷的程序的時候&#xff0c;發現中斷特別容易受到干擾&#xff0c;我把手放在對應的中斷引腳上&#xff0c;中斷就一直觸發&#xff0c;沒有停過。經過一天的學習&#xff0c;找到了幾個解決方法&#xff0c;所以寫了這篇筆記。如果你的中斷也時不時會誤觸發&…

數 組

數組格式 普通數組下標是數字 關聯數組下標是字符串 例子&#xff1a; a&#xff08;10 20 30 40 50&#xff09; a[0] 10 數組的分類(普通數組和關聯數組) 普通數組 可以不需要手動聲明&#xff0c;直接使用 declare -a 數組名 關聯數組 一定要手動聲明 adeclare …

通過Spring整合MyBatis實現持久層操作

文章目錄 為什么要整合Spring和MyBatis&#xff1f;步驟一&#xff1a;添加依賴步驟二&#xff1a;配置數據源步驟三&#xff1a;配置MyBatis步驟四&#xff1a;創建Mapper接口和XML文件步驟五&#xff1a;使用Mapper接口拓展&#xff1a;事務管理 &#x1f389;通過Spring整合…

Leetcode173. 二叉搜索樹迭代器

Every day a Leetcode 題目來源&#xff1a;173. 二叉搜索樹迭代器 解法1&#xff1a;中序遍歷 我們可以直接對二叉搜索樹做一次完全的遞歸遍歷&#xff0c;獲取中序遍歷的全部結果并保存在數組中。隨后&#xff0c;我們利用得到的數組本身來實現迭代器。 代碼&#xff1a…

競賽 : 題目:基于深度學習的水果識別 設計 開題 技術

1 前言 Hi&#xff0c;大家好&#xff0c;這里是丹成學長&#xff0c;今天做一個 基于深度學習的水果識別demo 這是一個較為新穎的競賽課題方向&#xff0c;學長非常推薦&#xff01; &#x1f9ff; 更多資料, 項目分享&#xff1a; https://gitee.com/dancheng-senior/pos…

Spark-06:共享變量

目錄 1.廣播變量&#xff08;broadcast variables&#xff09; 2.累加器&#xff08;accumulators&#xff09; 在分布式計算中&#xff0c;當在集群的多個節點上并行運行函數時&#xff0c;默認情況下&#xff0c;每個任務都會獲得函數中使用到的變量的一個副本。如果變量很…