2023-07-04 11:10:44來源:今日頭條
隨著信息技術(shù)和互聯(lián)網(wǎng)的發(fā)展,票務(wù)系統(tǒng)也在不斷升級(jí),比如實(shí)現(xiàn)了移動(dòng)支付、電子票據(jù)、實(shí)時(shí)數(shù)據(jù)分析等先進(jìn)功能。此外,許多票務(wù)系統(tǒng)還引入了人工智能和大數(shù)據(jù)技術(shù),用于精準(zhǔn)營(yíng)銷、個(gè)性化推薦和風(fēng)險(xiǎn)管理。
然而,票務(wù)系統(tǒng)也存在一些挑戰(zhàn),如如何保護(hù)用戶隱私,如何防止票務(wù)欺詐,以及如何提供更好的用戶體驗(yàn)等。因此,票務(wù)系統(tǒng)的開發(fā)和運(yùn)營(yíng)需要考慮到這些問題,并持續(xù)改進(jìn)和升級(jí)。
項(xiàng)目簡(jiǎn)介:大麥網(wǎng)是中國(guó)的領(lǐng)先在線票務(wù)平臺(tái),提供多樣化的活動(dòng)票務(wù),如音樂會(huì)、戲劇和體育賽事等。主要功能包括活動(dòng)搜索、在線購(gòu)票、電子票務(wù)、實(shí)時(shí)座位選擇、退換票服務(wù)以及支付接口。其智能推薦系統(tǒng)可以根據(jù)用戶興趣推送相關(guān)活動(dòng),為用戶提供方便、快捷的一站式購(gòu)票體驗(yàn)。
(資料圖片僅供參考)
類似的產(chǎn)品有:貓眼娛樂、永樂票務(wù)、bookmyshow.com、ticketmaster.com
難度級(jí)別:困難
1、什么是在線電影票預(yù)訂系統(tǒng)電影票預(yù)訂系統(tǒng)為其客戶提供在線購(gòu)買影院座位的能力。電子票務(wù)系統(tǒng)允許客戶瀏覽當(dāng)前正在上映的電影,并在任何地方任何時(shí)候預(yù)訂座位。
2、系統(tǒng)的需求和目標(biāo)我們的票務(wù)預(yù)訂服務(wù)應(yīng)滿足以下需求:
功能需求:
我們的票務(wù)預(yù)訂服務(wù)應(yīng)能列出其聯(lián)盟影院所在的不同城市。用戶選擇城市后,服務(wù)應(yīng)顯示該特定城市已經(jīng)上映的電影。用戶選擇電影后,服務(wù)應(yīng)顯示正在放映該電影的影院及其可用的放映時(shí)間。用戶應(yīng)能選擇在特定影院的一場(chǎng)放映并預(yù)訂他們的票。服務(wù)應(yīng)能向用戶展示影院大廳的座位布局。用戶應(yīng)能根據(jù)他們的喜好選擇多個(gè)座位。用戶應(yīng)能從已預(yù)訂的座位中區(qū)分出可用的座位。用戶應(yīng)能在付款以完成預(yù)訂之前,將座位保留五分鐘。如果有可能座位會(huì)變得可用,例如,當(dāng)其他用戶的保留到期時(shí),用戶應(yīng)能等待。等待的客戶應(yīng)以公平的、先到先得的方式服務(wù)。非功能性需求:
系統(tǒng)需要具有高度并發(fā)性。在任何特定時(shí)間點(diǎn),都會(huì)有多個(gè)對(duì)同一座位的預(yù)訂請(qǐng)求。服務(wù)應(yīng)能優(yōu)雅且公平地處理這一情況。服務(wù)的核心是票務(wù)預(yù)訂,也就意味著涉及到財(cái)務(wù)交易。這意味著系統(tǒng)應(yīng)具有安全性,并且數(shù)據(jù)庫(kù)應(yīng)遵守ACID(原子性、一致性、隔離性、持久性)原則。3、一些設(shè)計(jì)考慮為了簡(jiǎn)便,我們假設(shè)我們的服務(wù)不需要任何用戶認(rèn)證。系統(tǒng)將不處理部分票務(wù)訂單。用戶要么獲得他們想要的所有票,要么一張也得不到。 系統(tǒng)必須公平。為了阻止系統(tǒng)被濫用,我們可以限制用戶一次預(yù)訂不超過十個(gè)座位。我們可以假設(shè)在熱門/備受期待的電影上映時(shí),流量會(huì)激增,座位會(huì)很快被預(yù)訂完。系統(tǒng)應(yīng)具有可擴(kuò)展性和高可用性,以應(yīng)對(duì)流量激增。4、容量估計(jì)流量估計(jì):我們假設(shè)我們的服務(wù)每月有30億次頁(yè)面瀏覽,每月售出1000萬(wàn)張電影票。
存儲(chǔ)估計(jì):假設(shè)我們有500個(gè)城市,平均每個(gè)城市有10家影院。如果每個(gè)影院有2000個(gè)座位,平均每天有兩場(chǎng)放映。
我們假設(shè)每個(gè)座位預(yù)訂需要50字節(jié)(ID、NumberOfSeats、ShowID、MovieID、SeatNumbers、SeatStatus、Timestamp 等)存儲(chǔ)在數(shù)據(jù)庫(kù)中。我們還需要存儲(chǔ)關(guān)于電影和影院的信息;我們假設(shè)它會(huì)需要50字節(jié)。所以,要存儲(chǔ)所有城市的所有影院的所有放映的所有數(shù)據(jù)一天:
500個(gè)城市 * 10家影院 * 2000個(gè)座位 * 2場(chǎng)放映 * (50+50) 字節(jié) = 2GB / 天
要存儲(chǔ)五年的這些數(shù)據(jù),我們大約需要3.6TB。
5、系統(tǒng)API我們可以有SOAP或REST API來公開我們服務(wù)的功能。以下可能是搜索電影放映和預(yù)訂座位的API的定義。
SearchMovies(api_dev_key, keyword, city, lat_long, radius, start_datetime, end_datetime, postal_code, includeSpellcheck, results_per_page, sorting_order)
參數(shù):
api_dev_key (string):注冊(cè)賬戶的API開發(fā)者密鑰。這將用于包括限制用戶基于其分配的配額等在內(nèi)的事情。keyword (string):要搜索的關(guān)鍵詞。city (string):用于篩選電影的城市。lat_long (string):用于篩選的緯度和經(jīng)度。radius (number):我們想要搜索活動(dòng)的區(qū)域的半徑。start_datetime (string):用開始日期時(shí)間篩選電影。end_datetime (string):用結(jié)束日期時(shí)間篩選電影。postal_code (string):用郵政編碼/郵編篩選電影。includeSpellcheck (Enum: "yes" or "no"):是否在響應(yīng)中包含拼寫檢查建議。results_per_page (number):每頁(yè)返回的結(jié)果數(shù)。最大為30。sorting_order (string):搜索結(jié)果的排序順序。一些可允許的值:"name,asc","name,desc","date,asc","date,desc","distance,asc","name,date,asc","name,date,desc","date,name,asc","date,name,desc"。返回:(JSON) 以下是電影及其放映的示例列表:
{ "MovieID": 1, "ShowID": 1, "Title": "Cars 2", "Description": "About cars", "Duration": 120, "Genre": "Animation", "Language": "English", "ReleaseDate": "8th Oct. 2014", "Country": USA, "StartTime": "14:00", "EndTime": "16:00", "Seats": [ { "Type": "Regular" "Price": 14.99 "Status: "Almost Full" }, { "Type": "Premium" "Price": 24.99 "Status: "Available" } ]},{ "MovieID": 1, "ShowID": 2, "Title": "Cars 2", "Description": "About cars", "Duration": 120, "Genre": "Animation", "Language": "English", "ReleaseDate": "8th Oct. 2014", "Country": USA, "StartTime": "16:30", "EndTime": "18:30", "Seats": [ { "Type": "Regular" "Price": 14.99 "Status: "Full" }, { "Type": "Premium" "Price": 24.99 "Status: "Almost Full" } ]}
ReserveSeats(api_dev_key, session_id, movie_id, show_id, seats_to_reserve[])
參數(shù):
api_dev_key (string):與上面相同session_id (string):用戶的會(huì)話ID,用于跟蹤此預(yù)訂。一旦預(yù)訂時(shí)間到期,將使用此ID在服務(wù)器上刪除用戶的預(yù)訂。movie_id (string):預(yù)訂的電影。show_id (string):預(yù)訂的放映。seats_to_reserve (number):包含要預(yù)訂的座位ID的數(shù)組。返回:(JSON)
返回預(yù)訂的狀態(tài),其中包括以下之一:
1) "預(yù)訂成功"2) "預(yù)訂失敗 - 放映已滿",3) "預(yù)訂失敗 - 請(qǐng)重試,因?yàn)槠渌脩粽诒A纛A(yù)訂座位"。6、數(shù)據(jù)庫(kù)設(shè)計(jì)以下是我們即將存儲(chǔ)的數(shù)據(jù)的一些觀察:
每個(gè)城市可以有多個(gè)影院。每個(gè)影院將有多個(gè)影廳。每部電影將有多場(chǎng)放映,每場(chǎng)放映將有多次預(yù)訂。一個(gè)用戶可以有多次預(yù)訂。7、頂層設(shè)計(jì)在頂層面上,我們的web服務(wù)器將管理用戶的會(huì)話,應(yīng)用服務(wù)器將處理所有的票務(wù)管理,將數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫(kù)中,以及與緩存服務(wù)器一起處理預(yù)訂。
8、組件設(shè)計(jì)首先,我們?cè)囍⒎?wù),假設(shè)它是由一個(gè)單一的服務(wù)器提供的。
票務(wù)預(yù)訂流程:以下將是典型的票務(wù)預(yù)訂流程:
用戶搜索一部電影。用戶選擇一部電影。向用戶顯示該電影的可用場(chǎng)次。用戶選擇一場(chǎng)放映。用戶選擇要預(yù)訂的座位數(shù)量。如果需要的座位數(shù)可用,用戶將看到一個(gè)劇院的地圖以選擇座位。如果不是,用戶將進(jìn)入下面的“步驟8”。一旦用戶選擇了座位,系統(tǒng)將嘗試預(yù)訂這些選定的座位。如果無法預(yù)訂座位,我們有以下選項(xiàng):放映已滿;向用戶顯示錯(cuò)誤消息。用戶想預(yù)訂的座位已經(jīng)沒有了,但是還有其他座位可用,所以用戶被帶回到劇院地圖頁(yè)面以選擇不同的座位。沒有可預(yù)訂的座位,但所有座位都還沒有被預(yù)訂,因?yàn)橛行┳槐黄渌脩粼陬A(yù)訂池中保留并且還沒有預(yù)訂。用戶將被帶到一個(gè)等待頁(yè)面,在那里他們可以等待直到需要的座位從預(yù)訂池中釋放。這個(gè)等待可能會(huì)導(dǎo)致以下選項(xiàng):如果需要的座位數(shù)變得可用,用戶將被帶到劇院地圖頁(yè)面,他們可以選擇座位。在等待過程中,如果所有座位都被預(yù)訂了,或者預(yù)訂池中的座位數(shù)少于用戶打算預(yù)訂的座位數(shù),用戶將被顯示錯(cuò)誤消息。用戶取消等待,返回到電影搜索頁(yè)面。最多,用戶可以等待一個(gè)小時(shí),之后用戶的會(huì)話將過期,用戶將被帶回到電影搜索頁(yè)面。如果成功預(yù)訂了座位,用戶有五分鐘的時(shí)間支付預(yù)訂。付款后,預(yù)訂標(biāo)記為完成。如果用戶不能在五分鐘內(nèi)支付,他們所有的預(yù)訂座位都將被釋放,以供其他用戶使用。服務(wù)器如何跟蹤所有尚未預(yù)訂的活動(dòng)預(yù)訂?服務(wù)器又如何跟蹤所有等待的客戶? 我們需要兩個(gè)守護(hù)服務(wù),一個(gè)用來跟蹤所有活動(dòng)的預(yù)訂并從系統(tǒng)中移除任何過期的預(yù)訂;我們稱之為ActiveReservationService。另一個(gè)服務(wù)將跟蹤所有等待的用戶請(qǐng)求,一旦需要的座位數(shù)變得可用,它將通知(等待時(shí)間最長(zhǎng)的)用戶選擇座位;我們稱之為WaitingUserService。
A. ActiveReservationsService(活動(dòng)預(yù)訂服務(wù))我們可以在內(nèi)存中保留一個(gè)與Linked HashMap或TreeMap相似的數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)一場(chǎng)“演出”的所有預(yù)訂,除了在數(shù)據(jù)庫(kù)中保留所有數(shù)據(jù)。我們需要一種Linked HashMap類型的數(shù)據(jù)結(jié)構(gòu),它允許我們?cè)陬A(yù)訂完成時(shí)跳轉(zhuǎn)到任何預(yù)訂以移除它。此外,由于我們將有與每個(gè)預(yù)訂關(guān)聯(lián)的到期時(shí)間,HashMap的頭部將始終指向最舊的預(yù)訂記錄,以便在達(dá)到超時(shí)時(shí)過期預(yù)訂。
為了存儲(chǔ)每場(chǎng)演出的每個(gè)預(yù)訂,我們可以有一個(gè)HashTable,其中"key"是"ShowID","value"是包含"BookingID"和創(chuàng)建"Timestamp"的Linked HashMap。
在數(shù)據(jù)庫(kù)中,我們將在"Booking"表中存儲(chǔ)預(yù)訂,到期時(shí)間將在Timestamp列中。"Status"字段將有一個(gè)值為"Reserved (1)"的值,一旦預(yù)訂完成,系統(tǒng)將更新"Status"為"Booked (2)"并從相關(guān)演出的Linked HashMap中刪除預(yù)訂記錄。當(dāng)預(yù)訂過期時(shí),我們可以從Booking表中移除它,或者將其標(biāo)記為"Expired (3)",除此之外還要從內(nèi)存中移除。
ActiveReservationsService也將與外部金融服務(wù)一起處理用戶支付。每當(dāng)預(yù)訂完成或預(yù)訂過期時(shí),WaitingUsersService都會(huì)收到一個(gè)信號(hào),以便可以為任何等待的客戶提供服務(wù)。
B. WaitingUsersService(等待用戶服務(wù))就像ActiveReservationsService一樣,我們可以將一個(gè)演出的所有等待用戶存儲(chǔ)在Linked HashMap或TreeMap的內(nèi)存中。我們需要一個(gè)類似于Linked HashMap的數(shù)據(jù)結(jié)構(gòu),以便我們可以在用戶取消請(qǐng)求時(shí)跳轉(zhuǎn)到任何用戶以從HashMap中移除他們。此外,由于我們是以先到先得的方式服務(wù),Linked HashMap的頭部總是指向等待時(shí)間最長(zhǎng)的用戶,因此每當(dāng)座位變得可用時(shí),我們都可以以公平的方式為用戶提供服務(wù)。
我們將有一個(gè)HashTable用來存儲(chǔ)每個(gè)Show的所有等待用戶。"key"將是"ShowID","value"將是包含"UserIDs"和他們的等待開始時(shí)間的Linked HashMap。
客戶端可以使用Long Polling來保持自己的預(yù)訂狀態(tài)更新。每當(dāng)座位變得可用時(shí),服務(wù)器可以使用這個(gè)請(qǐng)求來通知用戶。
預(yù)訂過期
在服務(wù)器上,ActiveReservationsService跟蹤活動(dòng)預(yù)訂的過期時(shí)間(基于預(yù)訂時(shí)間)。由于客戶端將顯示一個(gè)計(jì)時(shí)器(用于過期時(shí)間),這可能與服務(wù)器稍微不同步,我們可以在服務(wù)器上添加五秒鐘的緩沖區(qū)以防止破碎的體驗(yàn),從而確??蛻舳嗽诜?wù)器超時(shí)后永不超時(shí),防止成功購(gòu)買。
9、并發(fā)性如何處理并發(fā)性,以便沒有兩個(gè)用戶能夠預(yù)訂同一座位。我們可以在SQL數(shù)據(jù)庫(kù)中使用事務(wù)來避免任何沖突。例如,如果我們使用的是SQL服務(wù)器,我們可以利用事務(wù)隔離級(jí)別來鎖定行,然后再更新它們。下面是樣本代碼:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;BEGIN TRANSACTION; -- Suppose we intend to reserve three seats (IDs: 54, 55, 56) for ShowID=99 Select * From Show_Seat where ShowID=99 && ShowSeatID in (54, 55, 56) && Status=0 -- free -- if the number of rows returned by the above statement is three, we can update to -- return success otherwise return failure to the user. update Show_Seat ... update Booking ...COMMIT TRANSACTION;
"Serializable" 是最高的隔離級(jí)別,可以保證免受臟讀、不可重復(fù)讀和幻讀的影響。這里要注意一點(diǎn);在一個(gè)事務(wù)中,如果我們讀取了行,我們會(huì)在這些行上加寫鎖,以防止它們被任何其他人更新。
一旦上述數(shù)據(jù)庫(kù)事務(wù)成功,我們就可以開始在ActiveReservationService中跟蹤預(yù)訂情況。
10、容錯(cuò)性當(dāng)ActiveReservationsService或WaitingUsersService崩潰時(shí)會(huì)發(fā)生什么? 每當(dāng)ActiveReservationsService崩潰時(shí),我們可以從‘Booking’表中讀取所有的活動(dòng)預(yù)訂。請(qǐng)記住,直到預(yù)訂完成,我們都將“Status”列保持為“Reserved (1)”。另一個(gè)選擇是擁有主-次配置,這樣,當(dāng)主服務(wù)崩潰時(shí),次服務(wù)可以接管。我們沒有將等待的用戶存儲(chǔ)在數(shù)據(jù)庫(kù)中,所以,當(dāng)WaitingUsersService崩潰時(shí),除非我們有主次設(shè)置,否則我們沒有任何方式恢復(fù)那些數(shù)據(jù)。
同樣,我們會(huì)為數(shù)據(jù)庫(kù)設(shè)置主次配置,以使其具有容錯(cuò)性。
11、數(shù)據(jù)分區(qū)數(shù)據(jù)庫(kù)分區(qū):如果我們按‘MovieID’進(jìn)行分區(qū),那么一部電影的所有場(chǎng)次都會(huì)在同一個(gè)服務(wù)器上。對(duì)于熱門電影來說,這可能會(huì)給那臺(tái)服務(wù)器帶來大量負(fù)載。更好的方法是根據(jù)ShowID進(jìn)行分區(qū);這樣,負(fù)載就可以分散到不同的服務(wù)器上。
ActiveReservationService和WaitingUserService分區(qū):我們的Web服務(wù)器將管理所有活動(dòng)用戶的會(huì)話,并處理與用戶的所有通信。我們可以使用一致性哈希算法來根據(jù)‘ShowID’為ActiveReservationService和WaitingUserService分配應(yīng)用服務(wù)器。這樣,特定場(chǎng)次的所有預(yù)訂和等待用戶將由某一組服務(wù)器處理。假設(shè)為了負(fù)載平衡,我們的"一致性哈希"為任何場(chǎng)次分配了三個(gè)服務(wù)器,那么每當(dāng)一個(gè)預(yù)訂過期時(shí),持有該預(yù)訂的服務(wù)器將執(zhí)行以下操作:
更新數(shù)據(jù)庫(kù)以移除預(yù)訂(或標(biāo)記為過期)并更新‘Show_Seats’表中座位的狀態(tài)。從Linked HashMap中移除預(yù)訂。通知用戶他們的預(yù)訂已過期。向所有持有該場(chǎng)次等待用戶的WaitingUserService服務(wù)器廣播消息,以找出等待時(shí)間最長(zhǎng)的用戶。一致性哈希方案將告訴我們哪些服務(wù)器持有這些用戶。如果所需的座位已經(jīng)變?yōu)榭捎?,就向持有最長(zhǎng)等待用戶的WaitingUserService服務(wù)器發(fā)送消息以處理他們的請(qǐng)求。每當(dāng)一個(gè)預(yù)訂成功時(shí),將發(fā)生以下事情:
持有該預(yù)訂的服務(wù)器向所有持有該場(chǎng)次等待用戶的服務(wù)器發(fā)送消息,以便這些服務(wù)器可以使所有需要的座位數(shù)多于可用座位數(shù)的等待用戶過期。收到上述消息后,所有持有等待用戶的服務(wù)器將查詢數(shù)據(jù)庫(kù),以查找現(xiàn)在有多少個(gè)空閑座位。此處的數(shù)據(jù)庫(kù)緩存將大大有助于只運(yùn)行一次這個(gè)查詢。使所有希望預(yù)訂的座位數(shù)多于可用座位數(shù)的等待用戶過期。為此,WaitingUserService必須遍歷所有等待用戶的Linked HashMap。關(guān)鍵詞:
隨著信息技術(shù)和互聯(lián)網(wǎng)的發(fā)展,票務(wù)系統(tǒng)也在不斷升級(jí),比如實(shí)現(xiàn)了移動(dòng)支
一、解決大圖內(nèi)存 計(jì)算問題的三個(gè)范式在兩年前做的tutorial里面,我們
大型語(yǔ)言模型(LLM)已經(jīng)很強(qiáng)了,但還可以更強(qiáng)。通過結(jié)合知識(shí)圖譜,LLM
每個(gè)企業(yè)中都有一些問題員工,但是管理IT領(lǐng)域的員工有一系列特定的挑戰(zhàn)
在貴州榕江縣進(jìn)行的“和美鄉(xiāng)村足球超級(jí)聯(lián)賽”持續(xù)火爆網(wǎng)絡(luò),目前,“村
慧算賬隸屬于北京公瑾科技有限公司,成立于2015年4月,是中國(guó)起步較早
珠海提出以工業(yè)化思維發(fā)展預(yù)制菜工程,建立生態(tài)聯(lián)盟,打造預(yù)制菜“燈塔
Redis是一種開源的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),它支持五種基本數(shù)據(jù)類型:字
7月4日消息,MetaGPT是一個(gè)著重于代碼生成的AI模型,雖然名字類似,但
靜態(tài)測(cè)試簡(jiǎn)介靜態(tài)測(cè)試包括代碼檢查、靜態(tài)結(jié)構(gòu)分析、代碼質(zhì)量度量等。它
7月4日消息,社交媒體平臺(tái)Instagram母公司Meta開發(fā)的推特競(jìng)品Threads已
2023年初,由OpenAI開發(fā)的ChatGPT的橫空出世打破了互聯(lián)網(wǎng)行業(yè)微妙的平
在今天的NBA猶他夏聯(lián)中,76人92-94不敵灰熊。與76人簽下雙向合同的落選
近日,國(guó)家醫(yī)保局公布《2023年國(guó)家基本醫(yī)療保險(xiǎn)、工傷保險(xiǎn)和生育保險(xiǎn)藥
科技日?qǐng)?bào)北京7月3日電(記者張夢(mèng)然)發(fā)表在最新一期《柳葉刀》雜志的新