System Design笔记:在线售票系统设计

文章目录

    • 何为在线售票系统?
    • 系统目标和要求
      • 1、功能要求
      • 2、非功能性需求
      • 3、设计注意事项
      • 4、容量估算
      • 5、系统API
        • 1.SearchMovies
        • 2.ReserveSeats
      • 6、数据库设计
      • 7、高级设计
      • 8、细节模块设计
      • 9、流程
        • 服务器如何跟踪所有尚未预订的active预订?服务器如何跟踪所有等待的客户?
        • ActiveReservationService
        • WaitingUsersService
      • 10、并发性
      • 11、容错性
      • 12、数据分区

何为在线售票系统?

电影票预订系统为其客户提供了在线购买影院座位的能力。Eticketing系统允许客户浏览当前正在播放的电影并预订座位,随时随地。

系统目标和要求

1、功能要求

功能要求:

  • 1、我们的售票服务应该能够列出其附属影院所在的不同城市。
  • 2、一旦用户选择城市,服务应显示在该特定城市发布的电影。
  • 3、一旦用户选择了一部电影,服务应显示运行该电影的电影院及其可用放映时间。
  • 4、用户应该能够在特定电影院选择一场演出并预订门票。
  • 5、服务应能向用户展示影院大厅的座位安排。用户应该能够根据自己的喜好选择多个座位。
  • 6、用户应能区分可用座位和预定座位。
  • 7、用户应能在付款完成预订之前,将座位保留五分钟。
  • 8、如果座位有可能可用,例如,当其他用户持有的座位过期时,用户应该能够等待。
  • 9、等待的客户应以公平、先到先服务的方式进行服务。

2、非功能性需求

1、系统需要高度并发。

在任何特定时间点,同一座位都会有多个预订请求。服务应该优雅而公平地处理这一问题。

2、这项服务的核心是订票,即金融交易。

这意味着系统应该是安全的,并且数据库符合ACID。

3、设计注意事项

1。为简单起见,假设我们的服务不需要任何用户身份验证。

2、系统不处理部分客票订单。要么用户得到了他们想要的所有门票,要么什么也得不到。

3、公平是制度的强制性要求。

4、为了防止系统滥用,我们可以限制用户一次预订10个以上的座位。

5、我们可以假设,在人们期待已久的热门电影上映时,流量会急剧上升,座位很快就会挤满。该系统应具有可扩展性和高可用性,以跟上流量激增的步伐。

4、容量估算

1、流量估计

假设我们的服务每月有30亿次页面浏览量,销量为10%一个月一百万张票。

2、存储量估计

假设我们有500个城市,平均每个城市有10家电影院。如果每家电影院有2000个座位,平均每天有两场演出。

假设每个座位预订需要50字节(ID、NumberOfSeats、ShowID、MovieID、SeatNumber、SeatStatus、Timestamp等)存储在数据库中。我们还需要存储关于电影和电影院的信息;假设需要50字节。所以,要存储所有关于所有城市的所有电影院一天的放映:

500 cities * 10 cinemas * 2000 seats * 2 shows * (50+50) bytes = 2GB / day

要存储五年的数据,我们需要大约3.6TB。

5、系统API

我们可以使用SOAP或RESTAPI来公开服务的功能。以下可能是用于搜索电影节目和预订座位的API的定义。

1.SearchMovies

在这里插入图片描述

api参数讲解:

api_dev_key (string): 注册账户的API开发人员密钥。这将用于根据分配的配额限制用户。keyword (string): 要搜索的关键字city (string): 筛选电影的城市lat_long (string): 用来过滤的经纬度信息radius (number): 要搜索事件的区域半径 start_datetime (string): 用来筛选的电影的开始日期end_datetime (string): 用来筛选的电影的结束日期postal_code (string): 用来筛选的邮政编码includeSpellcheck (Enum: “yes” orno): 拼写检查建议results_per_page (number): 每页返回的结果数。 Maximum is 30. sorting_order (string): 对搜索结果进行排序. 
Some allowable values : ‘name,asc, ‘name,desc,date,asc,date,desc, ‘distance,asc, ‘name,date,asc, 
‘name,date,desc,date,name,asc,date,name,desc. 

下面是电影及其节目的示例列表,后台的Returns: (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"}]},]

2.ReserveSeats

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ljkgijqY-1655134117332)(https://secure2.wostatic.cn/static/p7qSP9rcbkEe3tTxkKPC3w/image.png)]

api参数讲解:

api_dev_key (string): same as above session_id (string): 用于跟踪此预订的用户会话ID。一旦保留时间到期,将使用此删除用户在服务器上的保留
身份证件movie_id (string): 要预定的电影show_id (string): 要预定的场次eats_to_reserve (number): 包含要保留的座位ID的数组

下面是api返回值:Returns: (JSON)

Returns the status of the reservation, which would be one of the following: 
1) “Reservation Successful” 
2) “Reservation Failed - Show Full,” 
3) “Reservation Failed - Retry, as other users are holding reserved seats”. 

6、数据库设计

我们要存储的数据:

1、每个城市可以有多家电影院。

2、每家电影院将有多个大厅。

3、每部电影将有多场演出,每场演出将有多个预订。

4、一个用户可以进行多次预订。

下面是UML表单图设计

在这里插入图片描述

7、高级设计

在上层,我们的web服务器将管理用户会话,应用服务器将处理所有票证管理,将数据存储在数据库中,并与缓存服务器一起处理预订。

在这里插入图片描述

8、细节模块设计

首先,让我们尝试构建我们的服务,假设它是从单个服务器提供的。

以下是典型的售票流程:

1.用户搜索电影。

2.用户选择一部电影。

3.向用户显示电影的可用放映。

4.用户选择一个场次。

5.用户选择要预订的座位数目

6.如果有所需数量的座位,则会向用户显示要选择的剧院地图座位。如果没有,用户将进入下面的“步骤8”。

7.一旦用户选择了座位,系统将尝试预订这些选定的座位。

8.如果无法预订座位,我们有以下选择:

  • 本场次已满座,向用户显示错误消息
  • 用户想要预订的座位不再可用,但还有其他座位可用,因此用户将返回影院地图以选择不同的座位。
  • 没有可用的座位可预订,但是进入选定状态的座位有些还没有支付,也就是预订池中有一些其他用户持有的座位尚未预订。用户将进入等待页面,在那里他们可以等待,直到所需的座位从预订池中释放出来。这种等待可能会导致以下选项:
    • 如果所需的座位数量可用,用户将被带到剧院地图页面,在那里他们可以选择座位。
    • 等待期间,如果所有座位都已预订成功,或者预订池中的座位数少于用户预定的座位数,则会向用户显示错误消息。
    • 用户取消等待并返回到电影搜索页面。
    • 在用户会话过期并返回到电影搜索页面后,用户最多可以等待一个小时。

9.如果成功预订座位,用户有五分钟的时间支付预订费用。付款后,预订被标记为完成。如果用户无法在五分钟内付款,则其所有预留座位将被释放,以供其他用户使用。
整个流程如下:

在这里插入图片描述

9、流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

服务器如何跟踪所有尚未预订的active预订?服务器如何跟踪所有等待的客户?

我们需要两个守护程序服务,一个用于跟踪所有active预订并从系统中删除任何过期的预定;我们称之为ActiveReservationService。

另一项服务将跟踪所有等待的用户请求,一旦所需的座位数可用,它将通知(等待时间最长的)用户选择座位;我们叫它WaitingUserService吧。

ActiveReservationService

除了将所有数据保存在数据库中之外,我们还可以将本场次的所有预定保留在内存中,保存在类似于链接HashMap或TreeMap的数据结构中。

我们需要一个链接的HashMap类型的数据结构,允许我们跳转到任何预订,以便在预订完成后将其删除。

此外,由于我们将有与每个保留相关联的过期时间,哈希映射的头部将始终指向最旧的保留记录,以便在达到超时时可以过期保留。

为了存储每个场次的每个预订,我们可以有一个哈希表,其中“key”是“ShowID”,而“value”是包含“BookingID”和创建“Timestamp”的链接哈希表。

在数据库中,我们将预订存储在“Booking”表中,过期时间将在时间戳列中。

“Status”(状态)字段的值为“Reserved(1)”,一旦预订完成,系统会将“Status”(状态)更新为“Booked(2)”,并从相关节目的链接哈希表中删除预订记录。当预订过期时,除了从内存中删除外,我们还可以将其从预订表中删除或将其标记为“过期(3)”。

ActiveReservationsService还将与外部金融服务一起处理用户付款。无论何时预订完成,或预订过期,WaitingUsersService都会收到信号,以便为任何等待的客户提供服务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5f3G5DDs-1655134117341)(https://secure2.wostatic.cn/static/7inVUNt9VDx15YhDgmNAYZ/image.png)]

WaitingUsersService

就像ActiveReservationsService一样,我们可以将一个场次的所有等待用户保存在链接哈希映射或树映射的内存中。我们需要一个类似于链接HashMap的数据结构,这样当用户取消请求时,我们就可以跳转到任何用户,将其从HashMap中删除。此外,由于我们以先到先得的方式提供服务,链接HashMap的头部将始终指向等待时间最长的用户,因此每当有座位可用时,我们都可以以公平的方式为用户提供服务。

我们将有一个哈希表来存储每个节目的所有等待用户。“key”将是“ShowID”,“value”将是一个包含“userid”及其等待开始时间的链接HashMap。客户端可以使用长轮询来更新自己的预订状态。每当座位可用时,服务器都可以使用此请求通知用户。

在服务器上,ActiveReservationsService跟踪活动预订的到期时间(基于预订时间)。由于客户端将显示一个计时器(用于过期时间),该计时器可能与服务器有点不同步,因此我们可以在服务器上添加一个5秒的缓冲区,以防止出现中断的体验,这样客户端就不会在服务器之后超时,从而阻止成功购买。

10、并发性

如何处理并发性,以便没有两个用户能够预订同一个座位。我们可以在SQL数据库中使用事务来避免任何冲突。例如,如果我们使用的是SQL server,我们可以利用事务隔离级别锁定行,然后再更新它们。以下是示例代码:

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 and ShowSeatID in (54, 55, 56) and
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”是最高的隔离级别,可确保不受脏、不可重复和幻影读取的影响。这里要注意一件事;在一个事务中,如果我们读取行,我们会得到一个写锁,这样其他人就无法更新它们。

一旦上述数据库事务成功,我们就可以在ActiveReservationService中开始跟踪保留。

11、容错性

ActiveReservationsServiceWaitingUserService崩溃时会发生什么情况?

每当ActiveReservationsService崩溃时,我们都可以从“Booking”表中读取重新所有active预定。请记住,在预订之前,我们将“状态”列保留为“预定(1)”。

另一种选择是进行主从配置,以便在主服务器崩溃时,从服务器可以接管。

我们没有将等待的用户存储在数据库中,因此,当WaitingUsersService崩溃时,我们没有任何方法来恢复该数据,除非我们有主从设置。类似地,我们将对数据库进行主从设置,使其具有容错性。

12、数据分区

数据库分区:如果我们按“MovieID”进行分区,那么一部电影的所有放映都将在一台服务器上进行。对于非常热门的电影,这可能会在该服务器上造成大量负载。更好的方法是基于ShowID进行分区;这样,负载就可以分布在不同的服务器上。

ActiveReservationServiceWaitingUserService分区:

我们的web服务器将管理所有active用户的会话,并处理与用户的所有通信。我们可以使用一致性哈希根据“ShowID”为ActiveReservationService和WaitingUserService分配应用程序服务器

这样,特定场次的所有预订和等待用户都将由一组特定的服务器处理

让我们假设为了负载平衡,我们的一致哈希为任何场次分配三台服务器,因此每当预订过期时,持有该预订的服务器将执行以下操作:

1、更新数据库以删除预订(或将其标记为过期),并更新“Show seats”表中的座位状态。

2、从链接的HashMap中删除保留。

3、通知用户其预约已过期。

4、向所有等待该节目的等待用户的WaitingUserService服务器广播一条消息,以找出等待时间最长的用户。一致性哈希将告诉哪些服务器容纳这些用户。如果所需座位可用,则向等待时间最长的用户所在的WaitingUserService服务器发送消息,以处理其请求。

无论何时预订成功,都会发生以下情况:

1。持有该预订的服务器将向持有该节目等待用户的所有服务器发送一条消息,以便这些服务器可以终止需要比可用座位更多座位的所有等待用户。

2、在收到上述消息后,所有等待用户的服务器都会查询数据库,以确定现在有多少免费座位。在这里,数据库缓存将非常有助于只运行一次此查询。

3、让所有想预订比可用座位更多座位的等待用户过期。为此,WaitingUserService必须遍历所有等待用户的链接HashMap。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

流媒体协议初探(MPEG2-TS、RTSP、RTP、RTCP、SDP、RTMP、HLS、HDS、HSS、MPEG-DASH)

目录一、综述需求分析协议定制二、MPEG2-TS协议三、RTSP协议、RTP、RTCP、SDPRTSPRTP、RTCP、SDP四、RTMP五、HLS、HDS、HSSHLSHDS和HSS六、MPEG-DASH协议具体内容应用七、流媒体服务器流媒体服务器的功能与挑战客户端支持协议支持应用场景应用特点扩展技术广告投放录屏其他一、…

eclipse偶尔会反映迟钝,直接无视其报错

比如,你在web.xml中配置了什么东西,在有的时候不一定就会立即被eclipse察觉到,即便你的配置正确了,甚至重启了几次服务器,它仍然给你报错 比如说,刚才我在web.xml中配置了一个taglib,并且tld文件…

Qos(Quality of Service)

QOS(即Quality of Service,服务质量)主要指网络环境下服务满足用户的程度,在视频服务的语境下也可认为是Quality of Streaming,即流媒体服务的质量。通常,QOS可以由一系列指标表达,如传输的速度…

Popline:帅气的浮动 HTML5 文本编辑器工具栏

Popline 是一个基于 HTML5 实现的富文本编辑器工具栏,设计灵感来自 PopClip ,相比传统的文本编辑器工具,Popline 能够浮动在编辑的文本周围,操作起来十分方便。 您可能感兴趣的相关文章Metronic – 基于 Bootstrap 响应式后台管理…

流媒体技术优化

文章目录1、下载策略优化CDN选择策略错误处理策略码率选择策略2、协议和架构优化HTTP2TCP变种拥塞控制QUIC架构流媒体协议的选择与分发体系架构的设计对优化起着关键作用。 HLS和DASH协议在点播和OTT直播服务中已逐渐占据主流,其思想主要是将视频转为不同码率并切为…

API设计笔记:pimpl技巧

pimpl pointer to implementation:指向实现的指针,使用该技巧可以避免在头文件暴露私有细节,可以促进API接口和实现保持完全分离。 Pimpl可以将类的数据成员定义为指向某个已经声明过的类型的指针,这里的类型仅仅作为名字引入&am…

《设计模式》-责任链模式

责任链模式是一种对象的行为模式【GOF95】。在责任链模式里,很多对象由每一个对象对其下家的用而链起来形成一条链,请求在这个链上传递,直到链上的某一个对象决定处理此请求。 发出请求的客户端并不知道链上的哪一个对象终处理这个请求&#…

【机器学习】EM最大期望算法

EM, ExpectationMaximization Algorithm, 期望最大化算法。一种迭代算法,用于含有隐变量(hidden variable)的概率参数模型的最大似然估计或极大后验概率估计,其概率模型依赖于无法观测的隐变量。 经常用在ML与计算机视觉的数据聚类领域。 EM应用&#xf…

做一个给自己手机免费发送“天气预报”信息的软件

实现一个以下截图这样的功能!没错,就是你手机可以收到“免费”的天气预报短信! 一、在做之前必须了解以下四个功能: 1、WebService 2、Quartz.Net(定时任务框架) 3、SMTP:简单邮件传输协议,它是…

Android_Chronometer计时器

最近做一个项目用到Handler 和Message ,开始时不是很明白,不了解其中的内部机制,所以开发起来有点难度,之后自己找了Android 时间服务 这一节的内容,总结了一点关于时间的知识,在这里大概写一下&#xff0c…

置顶 | wolai博客

最近用wolai记录笔记较多,这里放一下我wolai的地址,当然csdn这边也会同时更文。 hanhan的博客

为你的程序添加监听器

平时在写程序时经常会遇到监听器,比如按钮的click监听器,按键监听器等等。而android中的监听器和java中的回调函数是同一个概念,都是在底层代码中定义一个接口来调用高层的代码。那么什么是回调函数呢?网上说的是“在WINDOWS中&am…

Git push 时每次都需要密码的疑惑

2015.1.13更新: 在本地搭建Git服务器时,也是有每次操作需要密码的情况。 是因为每次做推送动作时,Git需要认证你是好人。所以需要密码。 可以在 /home/username/.ssh/authorized_keys 文件里添加你的 ssh 公钥。一行一个。这样就可以在你push…

【PS】Gold words tutorials 赤金字教程

material_01material_021. White background and black words.The font of "Laker" is Teenick, and "Huang" is 中國龍粗魏碑2.Open material_01 and select a part of it.Copy and paste the part part into our workspace.You can drag and move to pa…

Android中的Handler机制

直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错 误:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.翻译过来就是&…

并行编程——内存模型之顺序一致性

1 定义 Sequential consistency , 简称 SC,定义如下 … the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individual processor appear in this sequen…

Daily Scrum 11.18

今日完成任务: 1.在提问问题的时候为问题创建索引 2.解决了修改个人资料后刷新没有更新的问题 3.初步加入了采纳功能(没完善UI设计) 遇到困难:创建索引之后,跳转到主页,需要重新登录,找了半天不…

hyper-v 用户无法再 创建外部配置存储 0x80070005

windows server 2008R2 刚安装的hyper-v 重启过。 修改配置文件到d:\Hyper-V目录下, hyper-V 创建 服务器遇到错误 操作失败 创建外部配置存储:一般性拒绝访问错误 虚拟机ID 0x80070005 d:\hyper-V 安全权限为 everyone 所有,users 所有,admi…

C++ 虚函数表解析

C 虚函数表解析 陈皓 http://blog.csdn.net/haoel 前言 C中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”&#x…

HTTP协议 (四) 缓存

HTTP协议 (四) 缓存 阅读目录 缓存的概念缓存的好处Fiddler可以方便地查看缓存的header如何判断缓存新鲜度通过最后修改时间,判断缓存新鲜度与缓存相关的headerETag浏览器不使用缓存直接使用缓存,不去服务器端验证如何设置IE不使用缓存公有缓存和私有缓存…