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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

优惠券读服务优化

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

優(yōu)惠券讀服務(wù)優(yōu)化

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

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

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


    /*** 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());}}

    上面用到的子任務(wù)類代碼

    /*** 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 ;}}

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

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。