日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

优惠券读服务优化

發布時間:2024/3/13 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 优惠券读服务优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

優惠券讀服務優化

前幾天成功解決了發券時的并發問題,參考這里。但是用戶領取得卡一多,讀取速度也慢了下來,用戶領取了200張卡以后,取得自己所有的卡需要5s左右。
主要業務場景,查詢用戶卡包,得到用戶所有的卡券。

- 用戶根據id分在不同的表。
- 卡券根據不同的商戶,分在不同的表。

  • 先用用戶id拿到用戶和卡的對應關系。
  • 再根據每個卡的商戶和 卡券id查詢對應的卡券,因為卡分在不同的表,不能成批拿卡,只能串行拿。
  • 拼裝卡模板相關信息返回。
  • 第一步,建立卡券的緩存系統。
    以商戶和卡券Id在添加一個字符前綴做key,把卡緩存在redis里,并在卡券狀 態變更后,作廢釣redis里對應的卡券。
    這樣做后,構建一個200張卡的卡包,第一次還是需要5秒,第二次訪問只需要1s。大并發后響應時間更長。這顯然不能滿足要求。
    第二步,建立用戶的緩存系統。
    在有了卡券的緩存后,另外以用戶id為主鍵,對每一個用戶查詢的返回結果,再做一級緩存,形成二級緩存機制。用戶卡有變動的時候,作廢緩存。
    有了二級緩存,還是200張卡,第一次訪問需要5s,第二次響應在200ms。100個并發訪問在400ms左右。
    緩存預刷機制。
    有了二級緩存之后,由于每次卡有變動,用戶訪問卡包構建cache在1s以上,會影響體驗,我又加入了預刷緩存機制,在用戶卡變動后,作廢掉用戶級別的緩存,和變動的單個卡的緩存,隨即拋出一個用戶的id進入隊列,隊列的尾端拿到用戶的主鍵后,訪問用戶卡包構建緩存,這樣當用戶再次訪問卡包的時候,響應體驗提升很大。
    第三步,并行構建卡券
    在沒有任何緩存的情況下,一次訪問200個卡券的卡包在6s以上。
    在只有卡券這一級緩存的情況下,構建用戶返回結果,也需要1s以上。
    因為取200個卡券的執行是單個串行執行的,分析下來這里是性能的瓶頸。優化方案是: 在構建200個卡券的時候,每一批卡開一個線程去構建,200個卡,可以同時開20到40個線程去構建,來縮短用戶卡多的時候,這里的時間消耗。
    這樣做后,先禁用用戶級別的緩存,來壓力測試這里的性能。
    在沒有任何cache的情況下,單次訪問200個卡的卡包,響應 時間在500ms,在有卡緩存沒有用戶緩存的情況下,單次的響應時間在200ms,構建用戶級別緩存的時間已經大大縮短了。但在高并發的情況下,會報錯,一查是因為redis的連接不夠了,每個線程需要20-40個redis連接,所以redis要擴大連接數。
    下面是多線程部分代碼,對象的名字做了處理,并除去了業務邏輯。


    /*** Created by haoli*/if (itemsList != null&& CollectionUtils.isNotEmpty(itemsList)) {int totalCount = itemsList.size();int taskNumber = (totalCount%GROUP_COUNT == 0 ? totalCount/GROUP_COUNT:totalCount/GROUP_COUNT+1);List<FutureTask<List<YourObject>>> ft = new ArrayList<FutureTask<List<YourObject >>>();for(int i=0; i<taskNumber ; i++) {int toSize = ((i+1)*GROUP_COUNT>totalCount-1 ?totalCount : (i+1)*GROUP_COUNT);List<ItemObject> tempList = itemsList.subList(i*GROUP_COUNT,toSize);SubQueryYourObjectTask task = new SubQueryYourObjectTask (tempList,this.yourService);FutureTask<List<YourObject >> ftItem = new FutureTask<List<YourObject >>(task);ft.add(ftItem);ThreadPoolExeService.execute(ftItem);}for(FutureTask<List<YourObject >> ftItem : ft){try {totals.addAll(ftItem.get());} catch (InterruptedException e) {log.error(e.toString());} catch (ExecutionException e) {log.error(e.toString());}}

    上面用到的子任務類代碼

    /*** Created by haoli*/public class SubQueryYourObjectTask implements Callable<List<YourObject >> {private List<ItemObject > parameter;private YourService yourService ;public SubQueryYourObjectTask (List<ItemObject > rlist, YourService yours){parameter = rlist;this.yourService = yours ;}@Overridepublic List<YourObject > call() throws Exception {List<YourObject > results= new ArrayList<YourObject >();for(ItemObject cbur :parameter ) {results .add(this.yourService .getXXXById(cbur ));}return results ;}}

    優化到現在,不論是第一次還是之后的訪問,都不慢了,在有二級緩存的情況下,cpu和連接資源消耗也不會太大。而且有緩存預刷機制,卡包數據更新后也不會慢了。

    總結

    以上是生活随笔為你收集整理的优惠券读服务优化的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。