今天公司产品的一个需求,要在手机App上准点进行活动,于是有了下面这些想法。
需求描述与约束
假设我们要在手机App上进行一个抢购小米手机的活动,参与的用户同时开始,任何用户的误差要小于1秒。 活动一般是定在每周二上午十点开抢,但有周二可能节假日,或者要求更高,一小时前临时上活动,之后打开App的用户都可看到。
- 既然有不同时区的用户,内部存储和计算应该用全球统一的时间戳,展示时再转为北京时间。
- 用户可能修改手机时间,手机的时间一天下来可能有几秒误差,所以接近活动一段时间就要用倒计时。
- 活动快开始时要和服务器同步一次,但在线用户太多,不可能频繁地与服务器同步。
初步方案
- 和服务器同步时间步骤
- App记录当前的本地时间戳start_time,向服务器发起请求;
- Server将服务器的当前时间戳server_time和活动开始时间戳task_time返回;
- App记录收到结果的本地时间戳stop_time;
- 计算同步时间,消除App和服务器间的时间误差
- 和server_time对应的本地时间就是发出请求和收到结果的时间中间值
local_time = start_time + (stop_time - start_time) / 2
* 活动启动的本地时间是
launch_time = local_time + (task_time - server_time)
- 优化流程,减小误差,同时保证服务器承受的压力不大
- 提前一小时采取本地倒计时,倒计时开始时间
alarm_time = launch_time - 3600
* 活动开始前2、3分钟和服务器再同步一次时间,即进行一次上两步
再次同步时间,提前150秒
resync_time = launch_time - 150