闲语杂谈 | 公交卡的工作原理

这个问题困扰了我很久了——公交卡是怎么工作的,或者说在使用公交卡的过程中数据是怎么流动的?根据数据存储位置来看,无非是分为卡内存储和中心服务器存储,公交卡的实现究竟是哪一种呢?

正常角度来考虑,卡中的余额肯定是存储在中心服务器的,但根据现实情况来看,无论公交车行驶到多么偏僻的地方,也无论刷卡人数的多少,刷卡过程都是瞬间完成的,全市有这么多公交车,中心服务器能无视物理环境而提供如此顺畅的服务吗?更何况还有更复杂的单点操作,比如当两辆公交车相会于站牌时,一乘客在短时间内从一辆车换乘到另一辆车,并迅速刷卡的处理逻辑,这种事务性问题对于中心服务器来说也会比较头疼。

以北京市为例,根据北京交通发展研究院的数据显示[1],北京市无轨交通日均客运量为一千万人次左右,按照一天运营10小时来算,平均每秒钟的客运量为接近300人,也就是说所谓的中心服务器需要承载300QPS的请求并且做到瞬时响应,如果严格来考虑的话,其实乘客的时间大部分是用在了乘坐,用在刷卡这个行为上的时间会更短,这样一来QPS肯定更高,更不要说还有BUG级别的早晚高峰了。换句话说,如果公交系统真的是实时连接了一个中心服务器的话,那么这个服务器相当于需要撑起一个千万日活的应用,而公交系统已经存续了很多年,远早于移动互联网的时代,这么看来数据存储在中心服务器似乎不太可能。

那么数据单纯存储在卡中是否可行呢?似乎可以解释刷卡响应速度和事务性问题了,但是这样一来,肯定有人尝试修改数据薅点社会主义羊毛,也不能真正投入使用。肯定还是需要一个中心服务器,或者需要一个去中心化的公交车互联系统(这条区块链的Idea值500个亿,加智能合约值1000个亿)。如果使用反证法的话,假设数据只存储在卡片中,那么北京交通发展研究院就无从得知全市公交车的日均客运量,那么上一段就写不下去,也就不会写到这一段,既然写到了这一段,说明假设不成立,即数据不可能单纯存储在公交卡中。

如果想实现公交车刷卡系统的话,可能需要权宜之计,即把中心服务器分为两层,外层是将近三万个[1]计算节点(公交车以及用于充值的地铁站),内层是真正的中心服务器(这条边缘计算的Idea值500个亿,加上云计算值1000个亿)。乘客在刷卡的时候只和当前公交车进行数据交换,同时数据也存储在卡中。公交车等待网络良好的时段或者定时与中心服务器进行数据交换,以此保证乘客数据的可靠性。在这个系统中,如果乘客单方面修改了卡片中的数据,那么等合账的时候肯定能发现没有这笔交易记录,直接把钱扣掉即可,这样也就没办法薅羊毛了。

公交卡信息系统架构设想
(图1:公交卡信息系统架构设想)

这个系统似乎已经可以解决上述的问题了,那么回头再来考虑公交车刷卡的场景,有一种非常常见的情况:下车不刷卡。对于下车不刷卡的情况,车上的广播会说“下车不刷卡,下次刷卡时将扣除最远里程无折扣票价”,其实这个提示已经告诉我们原理了,下次刷卡时扣除,说明此时下车后并未发生扣费,如果以后再也不刷卡,可能也就永远不会发生扣费。这种情况不可能是中心服务器来管控的,一来公交车与中心服务器的通信做不到实时,那么下车后迅速跑到另一辆车上刷卡就无法做到“扣除最远里程无折扣票价”了,二来如果真的是中心服务器来控制,也不需要等到下次刷卡时才扣费。如果要解决这个问题,另一个猜想是公交卡中不止存放余额信息,还存放着若干标志位,这种情况下需要一个“休想薅羊毛”标志位,上车置1,下车置0,此外还存储本趟车的最高票价,如果上车刷卡时发现“休想薅羊毛”标志位是1,那么就先扣完上一辆车的钱,再开始本辆车的扣款流程。

还有另外一种情况,从比较大的时间粒度来看,余额信息肯定是以中心服务器为准的,那么如果卡内信息出现了错误,无论是薅羊毛还是被薅羊毛,中心服务器的数据是在何时写入卡中的呢?上车刷卡时肯定是以卡内数据为准的,因为公交车不能知道是哪张卡要上车而提前从服务器获取数据,就算能提前获取,也不能保证此次数据获取之后到乘客上车之前没有发生后续余额变动。那么是不是下车刷卡时写入的呢?也不是,如果乘客只在车上呆很短的时间,公交车也不能保证在这段时间内完成和中心服务器的数据交换。那么是不是在充值的时候呢?这样也不行,如果羊毛收割者修改公交卡余额到2147483647元,那么往后余生也没有充值的必要了,服务器只能干瞪眼干着急就是没办法。这种情况我想不到有什么好的解释,暂时留白。

在翻找数据的时候,发现银行中也存在类似公交卡的脱机消费,银行卡的安全性肯定比公交卡更高,其中应该是涉及了比以上假设解释复杂得多的过程,需要翻翻论文才能找到正经的解释了。关于IC卡的安全和脱机消费的真正原理就暂时不挖掘了,留个坑下次再写。

参考文献

[1]. 北京交通发展研究院. 2018年北京交通发展年报[EB/OL]. http://www.bjtrc.org.cn/InfoCenter/NewsAttach/2018%E5%B9%B4%E5%8C%97%E4%BA%AC%E4%BA%A4%E9%80%9A%E5%8F%91%E5%B1%95%E5%B9%B4%E6%8A%A5.pdf. 2019/2019-03-27