日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

高效的并發(fā)管理:房間預訂 API 的樂觀鎖和消息隊列

來源: 責編: 時間:2023-11-09 17:14:06 251觀看
導讀想象一下這樣一個場景:多名旅行者同時嘗試預訂熱門目的地的最后一個可用房間。如果沒有適當?shù)牟l(fā)控制機制,這種情況很快就會變成競爭狀態(tài),導致房間超額預訂和客戶沮喪。我們將深入研究用于應對這些挑戰(zhàn)的兩種關鍵策略的

想象一下這樣一個場景:多名旅行者同時嘗試預訂熱門目的地的最后一個可用房間。如果沒有適當?shù)牟l(fā)控制機制,這種情況很快就會變成競爭狀態(tài),導致房間超額預訂和客戶沮喪。k9928資訊網——每日最新資訊28at.com

k9928資訊網——每日最新資訊28at.com

我們將深入研究用于應對這些挑戰(zhàn)的兩種關鍵策略的復雜性:樂觀鎖定和消息隊列。k9928資訊網——每日最新資訊28at.com

想象一下您正在使用一個在線酒店預訂平臺,類似于 Booking.com 或 Expedia 等知名平臺。以下是同步和異步流程如何發(fā)揮作用:k9928資訊網——每日最新資訊28at.com

同步流程:

預訂房間(同步):

  • 您訪問酒店預訂網站并選擇您的目的地、入住和退房日期以及其他偏好。
  • 您點擊“立即預訂”按鈕即可預訂房間。
  • 該網站使用基于 HTTP 的同步協(xié)議(如 REST 或 SOAP)將您的請求發(fā)送到酒店的預訂系統(tǒng)。
  • 酒店的系統(tǒng)會立即同步處理您的請求。它檢查房間可用性,為您預訂房間,并生成預訂號碼。
  • 預訂號碼將發(fā)送回您的瀏覽器,并在幾秒鐘內顯示在網站上。
  • 您可以立即獲得預訂號碼,然后可以放心地繼續(xù)您的旅行計劃。

k9928資訊網——每日最新資訊28at.com

創(chuàng)建房間實體

import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;@Entitypublic class Room {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    private String roomType;    private boolean isAvailable;    // getters and setters}

創(chuàng)建房間存儲庫

import org.springframework.data.jpa.repository.JpaRepository;public interface RoomRepository extends JpaRepository<Room, Long> {    Room findByRoomType(String roomType);}

創(chuàng)建客房預訂請求 DTO

import java.time.LocalDate;public class RoomBookingRequest {    private String roomType;    private LocalDate checkInDate;    private LocalDate checkOutDate;    // getters and setters}

創(chuàng)建客房預訂響應 DTO

public class RoomBookingResponse {    private String reservationNumber;    // getters and setters}

創(chuàng)建客房服務

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.UUID;@Servicepublic class RoomService {    @Autowired    private RoomRepository roomRepository;    public RoomBookingResponse bookRoom(RoomBookingRequest bookingRequest) {        String roomType = bookingRequest.getRoomType();        LocalDate checkInDate = bookingRequest.getCheckInDate();        LocalDate checkOutDate = bookingRequest.getCheckOutDate();        Room room = roomRepository.findByRoomType(roomType);        if (room != null && room.isAvailable()) {            // Add validation to check availability based on check-in and check-out dates here.            // For simplicity, we'll assume the room is available.            room.setAvailable(false);            roomRepository.save(room);            // Generate a reservation number (you can implement your logic here).            String reservationNumber = generateReservationNumber();            return new RoomBookingResponse(reservationNumber);        } else {            throw new RoomNotAvailableException();        }    }    private String generateReservationNumber() {        // Generate a unique reservation number (you can implement your logic here).        return UUID.randomUUID().toString();    }}

創(chuàng)建房間控制器

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping("/api/rooms")public class RoomController {    @Autowired    private RoomService roomService;    // Book a room    @PostMapping("/book")    public RoomBookingResponse bookRoom(@RequestBody RoomBookingRequest bookingRequest) {        return roomService.bookRoom(bookingRequest);    }}

定義自定義異常

import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.ResponseStatus;@ResponseStatus(HttpStatus.BAD_REQUEST)public class RoomNotAvailableException extends RuntimeException {    public RoomNotAvailableException() {        super("The requested room is not available.");    }}

測試API

您可以使用 Postman 或 cURL 等工具來測試您的 API。要預訂房間,請http://localhost:8080/api/rooms/book使用包含房間類型、入住日期和退房日期的 JSON 正文發(fā)出 POST 請求:k9928資訊網——每日最新資訊28at.com

{   "roomType" :  "Standard" ,   "checkInDate" :  "2023-10-01" ,   "checkOutDate" :  "2023-10-05" }

如果房間可用,API 將返回帶有預訂編號的 JSON 響應。您可以根據(jù)您的課堂需求自定義預訂邏輯和預訂號碼生成RoomService。k9928資訊網——每日最新資訊28at.com

異步流程

當多個用戶同時調用Booking API時

當多個并發(fā)呼叫在系統(tǒng)中搜索同一房間時,可能存在潛在的缺點和挑戰(zhàn):k9928資訊網——每日最新資訊28at.com

競爭條件:當多個請求嘗試同時預訂同一房間時,可能會出現(xiàn)競爭條件。如果處理不當,這可能會導致超額預訂,即系統(tǒng)允許的預訂數(shù)量超過了可用房間的數(shù)量。k9928資訊網——每日最新資訊28at.com

k9928資訊網——每日最新資訊28at.com

如何解決并發(fā)問題?

樂觀鎖定是一種數(shù)據(jù)庫級技術,可防止多個用戶同時嘗試更新同一資源時發(fā)生數(shù)據(jù)沖突。k9928資訊網——每日最新資訊28at.com

另一方面,消息隊列是異步通信工具,可確保請求的有序、可靠處理,使其成為分布式系統(tǒng)中處理并發(fā)請求的理想選擇。k9928資訊網——每日最新資訊28at.com

方法一:實現(xiàn)消息隊列響應并發(fā)請求

消息隊列確保請求按照接收順序進行處理,從而防止競爭條件和超量預訂。k9928資訊網——每日最新資訊28at.com

  • 個客戶端向端點發(fā)出 POST 請求/api/rooms/book以同時預訂酒店房間。
  • 處理RoomController傳入的預訂請求。
  • 該roomService.bookRoom方法接收預訂請求。
  • 它使用該方法將預訂請求發(fā)送到名為“room-booking”的 RabbitMQ 消息隊列rabbitTemplate.convertAndSend。
  • 它向客戶端返回初步響應,其中包含一條消息,表明預訂請求已發(fā)送,客戶端應等待確認。
  • 預訂請求被放入“房間預訂”隊列中。消息隊列系統(tǒng)(在本例中為 RabbitMQ)確保每個預訂請求都按照收到的順序進行處理,以防止競爭情況。
  • 監(jiān)聽RoomBookingMessageConsumer“房間預訂”隊列。
  • processBookingRequest當預訂請求出隊時,將調用消費者的方法。在該方法中,您通常會實現(xiàn)以下邏輯:
  • 根據(jù)請求的房型、入住日期和退房日期檢查客房供應情況。
  • 如果房間可用,則生成預訂號碼。
  • 更新數(shù)據(jù)庫中的房間可用性,將其標記為不可用,以防止重復預訂。
  • 通過RabbitMQ向客戶端發(fā)送包含預約號的響應消息

8. 在 中RoomBookingMessageConsumer,處理預訂請求并生成預訂號碼后,您可以使用傳統(tǒng)的 HTTP 客戶端(例如RestTemplate、HttpClient)將確認響應直接發(fā)送到客戶端的回調 URL 端點(該端點在請求中發(fā)送)。k9928資訊網——每日最新資訊28at.com

執(zhí)行:

創(chuàng)建客房預訂請求和響應 DTO

import java.time.LocalDate;public class RoomBookingRequest {    private String roomType;    private LocalDate checkInDate;    private LocalDate checkOutDate;    private String clientCallbackUrl; // Added to specify the client's callback URL    // getters and setters}public class RoomBookingResponse {    private String reservationNumber;    // getters and setters}

修改控制器

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping("/api/rooms")public class RoomController {    @Autowired    private RoomService roomService;    @PostMapping("/book")    public RoomBookingResponse bookRoom(@RequestBody RoomBookingRequest bookingRequest) {        return roomService.bookRoom(bookingRequest);    }}

創(chuàng)建客房預訂服務(生產者)

import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.http.ResponseEntity;import org.springframework.web.client.RestTemplate;@Servicepublic class RoomService {    @Autowired    private RoomRepository roomRepository;    @Autowired    private RabbitTemplate rabbitTemplate;    private RestTemplate restTemplate = new RestTemplate();    public RoomBookingResponse bookRoom(RoomBookingRequest bookingRequest) {        String roomType = bookingRequest.getRoomType();        // Send the booking request to the message queue        rabbitTemplate.convertAndSend("room-booking-exchange", "room-booking", bookingRequest);        return new RoomBookingResponse("Booking request sent. Please wait for confirmation.");    }    // This method sends the response to the client's callback URL    public void sendResponseToClient(RoomBookingResponse response, String clientCallbackUrl) {        ResponseEntity<Void> result = restTemplate.postForEntity(clientCallbackUrl, response, Void.class);        if (result.getStatusCode().is2xxSuccessful()) {            // Handle a successful response sent to the client        } else {            // Handle the case when the response to the client failed        }    }}

創(chuàng)建消息消費者

import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class RoomBookingMessageConsumer {    @Autowired    private RoomService roomService;    @RabbitListener(queues = "room-booking-queue")    public void processBookingRequest(RoomBookingRequest bookingRequest) {        // Process the booking request        RoomBookingResponse response = processBookingLogic(bookingRequest);        // Send the confirmation response to the client's callback URL        roomService.sendResponseToClient(response, bookingRequest.getClientCallbackUrl());    }    private RoomBookingResponse processBookingLogic(RoomBookingRequest bookingRequest) {        // Implement your booking logic here, e.g., checking room availability and generating a reservation number        // Update room availability in the database        // Send a response message to confirm the booking or indicate unavailability        // For simplicity, we'll assume the room is available and generate a reservation number.        String reservationNumber = generateReservationNumber();        return new RoomBookingResponse(reservationNumber);    }    private String generateReservationNumber() {        // Generate a unique reservation number (you can implement your logic here).        return "RES-" + System.currentTimeMillis();    }}

方法二:實現(xiàn)樂觀鎖來處理并發(fā)請求

您可以修改代碼以使用同步方法和 JPA 樂觀鎖定。k9928資訊網——每日最新資訊28at.com

步驟1:修改Room實體:@Version向實體添加一個字段Room以啟用樂觀鎖定:k9928資訊網——每日最新資訊28at.com

import javax.persistence.*;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;@Entitypublic class Room {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    private String roomType;    private boolean isAvailable;        @Version    private Long version;    // getters and setters}
步驟2:修改客房服務對每個房間使用ReentrantLock來同步訪問房間預訂操作
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.UUID;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;@Servicepublic class RoomService {    @Autowired    private RoomRepository roomRepository;    private final ConcurrentHashMap<Long, Lock> roomLocks = new ConcurrentHashMap<>();    public RoomBookingResponse bookRoom(RoomBookingRequest bookingRequest) {        String roomType = bookingRequest.getRoomType();        LocalDate checkInDate = bookingRequest.getCheckInDate();        LocalDate checkOutDate = bookingRequest.getCheckOutDate();        Room room = roomRepository.findByRoomType(roomType);        if (room != null) {            Lock roomLock = roomLocks.computeIfAbsent(room.getId(), id -> new ReentrantLock());            roomLock.lock();            try {                if (room.isAvailable()) {                    // Add validation to check availability based on check-in and check-out dates here.                    // For simplicity, we'll assume the room is available.                    room.setAvailable(false);                    roomRepository.save(room);                    // Generate a reservation number (you can implement your logic here).                    String reservationNumber = generateReservationNumber();                    return new RoomBookingResponse(reservationNumber);                }            } finally {                roomLock.unlock();            }        }        throw new RoomNotAvailableException();    }    private String generateReservationNumber() {        // Generate a unique reservation number (you can implement your logic here).        return UUID.randomUUID().toString();    }}

詳細工作原理:

并發(fā)請求&ConcurrentHashMap:當同一房間收到多個并發(fā)預訂請求時,它們可能同時到達并可能導致競爭條件。的引入ConcurrentHashMap確保每個房間都有自己的鎖。這ConcurrentHashMap是一個線程安全的映射,可以由多個線程同時安全地訪問。k9928資訊網——每日最新資訊28at.com

通過鎖定并發(fā)更新房間可用性:如果兩個線程同時嘗試預訂同一個房間,則只有其中一個線程會使用 成功獲取鎖roomLock.lock(),而另一個線程將暫時阻塞,直到第一個線程釋放鎖。k9928資訊網——每日最新資訊28at.com

釋放鎖以供其他線程更新:一旦線程獲取了鎖并成功修改了房間的可用性,它就會使用 釋放鎖roomLock.unlock(),從而允許其他線程繼續(xù)預訂其他房間。k9928資訊網——每日最新資訊28at.com

樂觀鎖防止數(shù)據(jù)庫級別的競爭條件:在代碼中,實體中的字段啟用數(shù)據(jù)庫級別的樂觀鎖。更新房間時,JPA 在允許更新之前會根據(jù)實體中的版本字段檢查數(shù)據(jù)庫中的版本字段。@VersionRoomk9928資訊網——每日最新資訊28at.com

  • 如果兩個事務同時嘗試更新同一個房間,根據(jù)版本號的比較,只有其中一個會成功,從而防止數(shù)據(jù)庫級別的數(shù)據(jù)沖突。
  • 因此 2 個不同的事務無法同時更新數(shù)據(jù)庫中的一個房間

本文鏈接:http://www.www897cc.com/showinfo-26-18996-0.html高效的并發(fā)管理:房間預訂 API 的樂觀鎖和消息隊列

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 40 道Typescript 面試題及其答案與代碼示例

下一篇: 七個優(yōu)秀微服務跟蹤工具

標簽:
  • 熱門焦點
  • 只需五步,使用start.spring.io快速入門Spring編程

    步驟1打開https://start.spring.io/,按照屏幕截圖中的內容創(chuàng)建項目,添加 Spring Web 依賴項,并單擊“生成”按鈕下載 .zip 文件,為下一步做準備。請在進入步驟2之前進行解壓。圖
  • 使用LLM插件從命令行訪問Llama 2

    最近的一個大新聞是Meta AI推出了新的開源授權的大型語言模型Llama 2。這是一項非常重要的進展:Llama 2可免費用于研究和商業(yè)用途。(幾小時前,swyy發(fā)現(xiàn)它已從LLaMA 2更名為Lla
  • 一文掌握 Golang 模糊測試(Fuzz Testing)

    模糊測試(Fuzz Testing)模糊測試(Fuzz Testing)是通過向目標系統(tǒng)提供非預期的輸入并監(jiān)視異常結果來發(fā)現(xiàn)軟件漏洞的方法。可以用來發(fā)現(xiàn)應用程序、操作系統(tǒng)和網絡協(xié)議等中的漏洞或
  • 使用Webdriver-manager解決瀏覽器與驅動不匹配所帶來自動化無法執(zhí)行的問題

    1、前言在我們使用 Selenium 進行 UI 自動化測試時,常常會因為瀏覽器驅動與瀏覽器版本不匹配,而導致自動化測試無法執(zhí)行,需要手動去下載對應的驅動版本,并替換原有的驅動,可能還
  • 大廠卷向扁平化

    來源:新熵作者丨南枝 編輯丨月見大廠職級不香了。俗話說,兵無常勢,水無常形,互聯(lián)網企業(yè)調整職級體系并不稀奇。7月13日,淘寶天貓集團啟動了近年來最大的人力制度改革,目前已形成一
  • 年輕人的“職場羞恥感”,無處不在

    作者:馮曉亭 陶 淘 李 欣 張 琳 馬舒葉來源:燃次元&ldquo;人在職場,應該選擇什么樣的著裝?&rdquo;近日,在網絡上,一個與著裝相關的帖子引發(fā)關注,在該帖子里,一位在高級寫字樓亞洲金
  • 阿里瓴羊One推出背后,零售企業(yè)迎數(shù)字化新解

    作者:劉曠近年來隨著數(shù)字經濟的高速發(fā)展,各式各樣的SaaS應用服務更是層出不窮,但本質上SaaS大多局限于單一業(yè)務流層面,對用戶核心關切的增長問題等則沒有提供更好的解法。在Saa
  • OPPO、vivo、小米等國內廠商Q2在印度智能手機市場份額依舊高達55%

    7月20日消息,據(jù)外媒報道,研究機構的報告顯示,在全球智能手機出貨量同比仍在下滑的大背景下,印度這一有潛力的市場也未能幸免,出貨量同比也有下滑,多家廠
  • 網傳小米汽車開始篩選交付中心 建筑面積不低于3000平方米

    7月7日消息,近日有微博網友@長三角行健者爆料稱,據(jù)經銷商集團反饋,小米汽車目前已經開始了交付中心的篩選工作,要求候選場地至少有120個車位,建筑不能低
Top 主站蜘蛛池模板: 阿坝县| 龙泉市| 谢通门县| 延吉市| 阿勒泰市| 尼木县| 靖安县| 宾川县| 库伦旗| 北京市| 寿阳县| 中西区| 新干县| 普陀区| 宜春市| 诸城市| 永靖县| 沐川县| 洪泽县| 万州区| 报价| 萍乡市| 都江堰市| 濉溪县| 保康县| 横山县| 长春市| 康平县| 娄烦县| 织金县| 榕江县| 云南省| 民权县| 通城县| 大足县| 双峰县| 新密市| 利辛县| 措勤县| 赤水市| 新民市|