春运一票难求,候补官方抢票
最近春节火车一票难求,12306系统的候补购票是一种官方支持的抢票方式。在首日票已售罄时,立即提交候补请求,系统会优先考虑候补乘客的需求。根据成功率灵活选择是否候补购票。
当旅客在12306网站购票,输入乘车日期、发到站等信息查询没有余票时,页面会在相关车次的席别余票显示列表中出现"候补"字样,旅客可根据需求点击相应车次、席别对应的"候补"区域,系统将该需求自动加入当前候补购票需求列表。候补订单提交成功后需在30分钟内完成支付,完成候补预付款支付后,候补购票订单立即生效。候补购票订单生效后,相关候补需求不可修改,如需变更,可终止订单后重新操作。兑现时,按照候补订单生效的时间顺序,优先兑现符合条件的候补需求。预付款按该单不同组合需求中票款的最高额度计算(卧铺按下铺票价计算)。
候补订单系统该如何设计?
那么如何设计一个12306火车票候补功能的系统呢?设计一个12306火车票候补功能的系统我们需要考虑的主要模块包括乘客候补系统、车票余量监控、排队、通知机制以及支付与出票等核心环节。以下是一种简化的系统设计概述:
- 乘客候补订单模块:
-
用户提交候补请求:允许用户对已经售罄的车次座位发起候补申请,包含乘车人信息、日期、车次、席别等必要信息。
-
候补队列建立:系统将所有候补请求按照一定的优先级策略(如购票时间先后、会员等级等)排序,形成候补队列。
- 支付模块:
-
候补订单申请成功后,用户在接到通知后,应在规定时间内完成支付。
-
支付成功后需要将消息推送到候补订单模块,候补订单根据规则排序建立候补队列。
- 车票余量监控模块:
-
实时对接12306票务数据库,监控各车次的退票、改签动态,实时更新车票剩余情况。
-
当有乘客退票或者改签导致座位空缺时,触发候补队列处理机制。
- 候补处理模块:
-
根据车票余量变化,自动从候补队列中选择符合条件的候补乘客,为其生成车票。
-
成功分配车票的候补请求移除出队列,未成功分配的则继续保留等待。
- 出票模块:
- 候补订单处理后,系统立即执行出票操作,将电子客票信息更新至乘客账户,并可下载电子凭证。
通过以上模块,构建一个高效、稳定、透明的火车票候补系统,既能有效利用票源,又能提升用户体验。
那么不同的车次、订票日期、坐席、出站、候补人数组合在一起后传统的消息队列可能无法满足我们的需求了。下面拿G521列车举个例子:
这是一个开往武汉的高铁,假如我们要在2024-02-08这天要到郑州,票没有了,我们候补订单候补了3个人,那么这个队列该怎么存放呢?
我们可以简单想下一个队列能够快速的根据车次、订票日期、坐席、出站、候补人数组合等信息快速找到队列,并消费。传统数据库无法满足这种高并发的需求,REDIS的list貌似可以试下,如果我想对某个车次+日期查询队列情况(超过一定数量,提示用户不要排队了)又不太方便,这时hash+list的组合就比较合适了。下面我们看下详细设计。
如何使用redis的hash+list实现候补队列
我们使用 Redis 的 Hash 结构来实现根据车次、车站、日期、乘车人数设计一个队列。每个车次及时间作为一个 key,车站和乘车人数作为 field,对应的值是一个队列,存放候补订单。当某个车次到某个车站有票时,可以遍历这个 key 及 field,找到第一个队列进行消费。以下是具体的设计方案:
1. Redis Hash 结构
vbnet
Key: train:{train_number}:{date}
Field: {station}_{passenger_count}
Value: 候补订单队列
2. 举例
假设 G521 车次,日期为 2024-02-08,有 3 个乘客,站台为 郑州。
makefile
Key: train:G520:2024-02-08
Field: 郑州_二等座_3
Value: [候补订单1, 候补订单2, 候补订单3, ...]
3. 消费逻辑
当某个车次到达某个车站有票时,我们可以按遍历该车次在该日期下的 Hash 结构的 field,如果很多票我们选择优先消费field=郑州_二等座_3
的队列,如果只有一张票我们只能消费郑州_二等座_1
的队列。当然还需要结合候补时间判断。
总结
-
Hash 结构设计: 使用 Hash 结构来存储车次、日期、车站、乘车人数等信息,便于查询和管理。
-
队列存储候补订单: 在 Hash 结构的 field 中存储候补订单队列,便于根据车站和乘车人数索引订单。
-
消费逻辑: 当某个车次到达某个车站有票时,遍历相应的 Hash 结构,找到一个非空队列进行消费。
通过以上设计,我们可以根据车次、车站、日期、乘车人数设计一个队列,并通过 Redis 的 Hash 结构实现,保证了订单信息的管理和处理的高效性和可靠性。想想一些平台的排队功能是不是也可以这么搞?