黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國(guó)咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁(yè) hot資訊 Redis隊(duì)列實(shí)現(xiàn)高并發(fā)的步驟

Redis隊(duì)列實(shí)現(xiàn)高并發(fā)的步驟

更新時(shí)間:2022-12-08 10:47:02 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1131次

Redis隊(duì)列實(shí)現(xiàn)高并發(fā)的步驟是什么?動(dòng)力節(jié)點(diǎn)小編來(lái)告訴大家。

高并發(fā)的業(yè)務(wù)場(chǎng)景:

我們做商品搶購(gòu)功能,要面臨的第一個(gè)問(wèn)題就是數(shù)據(jù)不能異常,而保證數(shù)據(jù)不異常我們的解決辦法有很多比如說(shuō)數(shù)據(jù)庫(kù)的鎖機(jī)制,或者先改后查的方式都能解決,但是第二個(gè)問(wèn)題來(lái)了如果我們用上述技術(shù)解決,數(shù)據(jù)是不會(huì)異常了,但是我們的服務(wù)器壓力就會(huì)很大了,從而使服務(wù)器宕機(jī),那么我們?nèi)绾问狗?wù)器壓力減小還能保證數(shù)據(jù)不異常呢,我們可以使用隊(duì)列的思想,下面我們介紹的是使用redis隊(duì)列解決高并發(fā)的問(wèn)題。

設(shè)計(jì)思路

用戶在下訂單之前當(dāng)然是先查詢到這個(gè)商品,在這個(gè)查詢的時(shí)候,將數(shù)據(jù)庫(kù)中商品的剩余數(shù)量存到redis中;

服務(wù)器在一瞬間接到成千上萬(wàn)的下訂單請(qǐng)求,在控制層沒(méi)有直接處理請(qǐng)求數(shù)據(jù),而是先根據(jù)redis中商品的剩余數(shù)量來(lái)判斷,如果>0,就將請(qǐng)求放到請(qǐng)求隊(duì)列中,否則直接響應(yīng)客戶端“賣完了”;

考慮到數(shù)據(jù)的一致性,隊(duì)列的容量就是商品的剩余數(shù)量,隊(duì)列采用的是線程安全的隊(duì)列LinkedBlockingQueue(單臺(tái)服務(wù)器),然后通過(guò)新的線程異步處理這些請(qǐng)求,多臺(tái)服務(wù)器的話,可以考慮使用消息隊(duì)列MQ,單獨(dú)用一臺(tái)服務(wù)器去處理消息隊(duì)列中的請(qǐng)求;

客戶端發(fā)送訂單請(qǐng)求之后,會(huì)收到響應(yīng),要么是剩余數(shù)量不足(賣完了),要么是請(qǐng)求已經(jīng)被放到隊(duì)列中,為下一步的輪詢訂單做準(zhǔn)備;

如果響應(yīng)狀態(tài)是賣完了,直接提示客戶,如果請(qǐng)求已經(jīng)放入隊(duì)列中,就可以根據(jù)用戶id和商品id去輪詢訂單了;

實(shí)現(xiàn)步驟

說(shuō)明:用java語(yǔ)言,springmvc框架+redis實(shí)現(xiàn)

準(zhǔn)備工作,查詢商品信息,將剩余數(shù)量同步到redis中

Jedis jedis = jedisPool.getResource();
BuyGood good=buyGoodService.getById(good_id);
jedis.set("residue"+good_id, good.getResidue()+"");
jedisPool.returnResource(jedis);

下訂單的方法,下面直接展示代碼,包括請(qǐng)求對(duì)象,控制層方法,請(qǐng)求處理線程類的具體實(shí)現(xiàn)

請(qǐng)求封裝對(duì)象

public class BuyRequest {
private int good_id;//商品id
private int user_id;//用戶ID
private int order_id;//訂單id
private BuyOrders buyOrders;//訂單信息
private int response_status;//0:未處理;1:正常;2:異常
public BuyOrders getBuyOrders() {
return buyOrders;
}
public void setBuyOrders(BuyOrders buyOrders) {
this.buyOrders = buyOrders;
}
public int getGood_id() {
return good_id;
}
public void setGood_id(int good_id) {
this.good_id = good_id;
}
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public int getResponse_status() {
return response_status;
}
public void setResponse_status(int response_status) {
this.response_status = response_status;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}

處理請(qǐng)求的controller

@Controller
@RequestMapping("/buy")
public class BuyController {
private static BuyQueuebuyqueue =null;//線程安全的請(qǐng)求隊(duì)列
@RequestMapping("/addOrders.do")
@ResponseBody
public Object addOrders(BuyRequest buyrequest){
Mapresults = new HashMap<>();
Jedis jedis = jedisPool.getResource();
try {
//下訂單之前,先獲取商品的剩余數(shù)量
int residue = 
Integer.valueOf(jedis.get("residue"+buyrequest.getGood_id()));
if(residue<1){//如果剩余數(shù)量不足,直接響應(yīng)客戶端“賣完了”
results.put("msg", "賣完了");
results.put("done", false);
BaseLog.info("addOrders results="+JSON.toJSONString(results));
return results;
}
//如果還有剩余商品,就準(zhǔn)備將請(qǐng)求放到請(qǐng)求隊(duì)列中
if(buyqueue==null){//第一次初始化請(qǐng)求隊(duì)列,隊(duì)列的容量為當(dāng)前的商品剩余數(shù)量
buyqueue=new BuyQueue(residue);
}
if(buyqueue.remainingCapacity()>0){//當(dāng)隊(duì)列的可用容量大于0時(shí),將請(qǐng)求放到請(qǐng)求隊(duì)列中
buyqueue.put(buyrequest);
}else{//當(dāng)請(qǐng)求隊(duì)列已滿,本次請(qǐng)求不能處理,直接響應(yīng)客戶端提示請(qǐng)求隊(duì)列已滿
results.put("msg", "搶購(gòu)隊(duì)列已滿,請(qǐng)稍候重試!");
results.put("done", false);
return results;
}
if(!DealQueueThread.excute){//如果線程類的當(dāng)前執(zhí)行標(biāo)志為未執(zhí)行,即空閑狀態(tài),通過(guò)線程池啟動(dòng)線程
DealQueueThread dealQueue = new DealQueueThread(buyqueue);
ThreadPoolUtil.pool.execute(dealQueue);
BaseLog.info("Thread.activeCount()="+Thread.activeCount());
}
//請(qǐng)求放入到隊(duì)列中,即完成下單請(qǐng)求
results.put("done", true);
results.put("msg", "下訂單成功");
} catch (Exception e) {
results.put("done", false);
results.put("msg", "下單失敗");
BaseLog.info("addOrders results="+JSON.toJSONString(results));
BaseLog.error("addOrders",e);
}finally{
jedisPool.returnResource(jedis);
}
return results;
}
}

處理請(qǐng)求的線程類

@Component
public class DealQueueThread implements Runnable {
private static DealQueueThread dealQueueThread;
@Autowired
BuyGoodService buyGoodService;
@Autowired
BuyOrdersService buyOrdersService;
@Autowired
JedisPool jedisPool;
private Jedis jedis;
private BuyQueuebuyqueue;
public static boolean excute = false;//線程的默認(rèn)執(zhí)行標(biāo)志為未執(zhí)行,即空閑狀態(tài)
public DealQueueThread() {
}
public DealQueueThread(BuyQueuebuyqueue) {
this.buyqueue = buyqueue;
jedis = dealQueueThread.jedisPool.getResource();
}
@PostConstruct
public void init() {
dealQueueThread = this;
dealQueueThread.buyGoodService = this.buyGoodService;
dealQueueThread.buyOrdersService = this.buyOrdersService;
dealQueueThread.jedisPool = this.jedisPool;
}
@Override
public void run() {
try {
excute = true;//修改線程的默認(rèn)執(zhí)行標(biāo)志為執(zhí)行狀態(tài)
//開(kāi)始處理請(qǐng)求隊(duì)列中的請(qǐng)求,按照隊(duì)列的FIFO的規(guī)則,先處理先放入到隊(duì)列中的請(qǐng)求
while (buyqueue != null && buyqueue.size() > 0) {
BuyRequest buyreq = buyqueue.take();//取出隊(duì)列中的請(qǐng)求
dealWithQueue(buyreq);//處理請(qǐng)求
}
} catch (InterruptedException e) {
BaseLog.error("DealQueueThread:", e);
} finally {
excute = false;
}
}
public synchronized void dealWithQueue(BuyRequest buyreq) {
try {
//為了盡量確保數(shù)據(jù)的一致性,處理之前先從redis中獲取當(dāng)前搶購(gòu)商品的剩余數(shù)量
int residue = Integer.valueOf(jedis.get("residue" + 
buyreq.getGood_id()));
if (residue < 1) {//如果沒(méi)有剩余商品,就直接返回
buyreq.setResponse_status(3);
return;
}
//如果有剩余商品,先在redis中將剩余數(shù)量減一,再開(kāi)始下訂單
jedis.decr("residue" + buyreq.getGood_id());
//將數(shù)據(jù)庫(kù)中將剩余數(shù)量減一,這一步處理可以在隊(duì)列處理完成之后一次性更新剩余數(shù)量
dealQueueThread.buyGoodService.minusResidue(buyreq.getGood_id());
//處理請(qǐng)求,下訂單
BuyOrders bo = new BuyOrders();
bo.setGood_id(buyreq.getGood_id());
bo.setUser_id(buyreq.getUser_id());
int order_id = dealQueueThread.buyOrdersService.insert(bo);
BuyOrders orders = dealQueueThread.buyOrdersService.getById(order_id);
buyreq.setOrder_id(order_id);//訂單id
buyreq.setBuyOrders(orders);//訂單信息
buyreq.setResponse_status(1);//處理完成狀態(tài)
} catch (Exception e) {
buyreq.setResponse_status(2);//異常狀態(tài)
BaseLog.error("DealQueueThread dealWithQueue:", e);
}
}
}

輪詢訂單

思路:查詢訂單和剩余數(shù)量,有以下三種情況:

1.查到訂單,直接跳轉(zhuǎn)到確認(rèn)訂單并支付的頁(yè)面完成支付;

2.還沒(méi)有查詢到訂單,但是剩余數(shù)量大于0,說(shuō)明請(qǐng)求還在隊(duì)列中,繼續(xù)輪詢;

3.沒(méi)有查到訂單,剩余數(shù)量等于或小于0,說(shuō)明搶購(gòu)失敗了,直接響應(yīng)客戶搶購(gòu)失敗;

以上就是關(guān)于“Redis隊(duì)列實(shí)現(xiàn)高并發(fā)的步驟”介紹,大家如果想了解更多相關(guān)知識(shí),不妨來(lái)關(guān)注一下本站的Redis教程,里面還有更豐富的知識(shí)等著大家去學(xué)習(xí),相信對(duì)大家一定會(huì)有所幫助的。

提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)

  • 全國(guó)校區(qū) 2025-05-15 搶座中
  • 全國(guó)校區(qū) 2025-06-05 搶座中
  • 全國(guó)校區(qū) 2025-06-26 搶座中
免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 中文字幕国产视频 | 18视频免费网站 | 一级a美女毛片 | xxxwww欧美性 | 一个人看的www的视频免费 | 小嫩嫩精品导航 | 日韩一级黄色大片 | 亚洲视频二 | 香港三级日本三级a视频 | 无夜精品久久久久久 | 韩国一级做a爰片性色毛片 韩国一级黄色大片 | 国产精品欧美一区二区 | 一个人看的视频在线www高清 | 深夜福利剧场 | 黄视频在线免费看 | 91精品国产高清久久久久久 | 日日射日日操 | 午夜官网| 国产第一页浮力影院-欢迎你 | 欧美三级欧美成人高清www | 深夜免费福利视频 | 奇米影视777四色米奇影院 | 天天爱添天天爱添天天爱添 | 中国黄色一级片 | 久久精品国产精品亚洲综合 | 最近中文字幕完整国语 | 日本簧片在线观看 | 欧美日韩在线一区 | 很黄很黄叫声床戏免费视频 | 国产亚洲午夜精品 | 在线视频亚洲一区 | 欧美日韩在线免费 | 亚洲四播房 | 美女视频黄8频a美女大全软 | 亚洲第二页 | 国产一级毛片午夜福 | 激情爽毛片私人影院 | 福利在线视频观看 | 成人免费观看在线视频 | 欧美日韩国产另类一区二区三区 | 中文在线最新版天堂 |