skynet.queue被设计为经过此队列的函数,按顺序依次执行。call被设计为服务间调用时,抛出请求的服务A需要等待被请求的服务B返回数据。得益于lua强大的协程能力,queue在执行时,如果queue中执行函数挂起的协程和当前的协程不是同一个协程时,会将当前的协程加入等待的协程队列,然后主动让出处理器,以便等上次挂起协程的代码处再次被唤醒时,处理完这个流程的逻辑,然后从等待的协程队列中按照先进先出的原则依次取出协程,唤醒协程,执行代码,这样就能保证经过queue的函数,是执行有序,返回有序。call时,也会让出处理器,等待被调用服务的返回,原理在前面有记录过。
线上服务器程序发生过这样的事情,里程碑系统刚上线,运行了几天之后,停服维护后再开时,发现任务1还在进行中,我查了线上服的日志,发现了问题。在服务器程序启动时,服务器已经满足任务1的条件,因此任务1条件达成,且任务1的设定是,条件达成时开出下一个任务,因此就开出了任务2,这个过程中,任务1的状态和任务2的状态数据都会存档,任务1在极短的时间内会做两次存档操作,第一次为刚产生任务的数据和进度修改合并为一次(做过优化),第二次为任务1结束设置为完成。当时使用的是post,没有等待存档服务的返回,我们的存档逻辑,发现表里没有这个主键的记录时会插入一条,因为两次存档的是同一条数据,主键相同,在第一次存档时,检查表里没有,执行插入的代码,第二次存档时,检查表里没有,执行插入的代码,结果因为主键冲突,第