智能排班

北森 iTalent 是我们公司采购的一个人力资源管理平台,它也是我们人事数据的来源,提供了时间窗接口来让我们获取 CUD 的数据(员工、部门、职位等)。

盖雅工场是公司采购的另一个系统,用来做考勤。

因为公司的大半都是门店员工,考勤规则非常复杂,希望通过盖雅来解放算薪的人力

现在需要从北森获取到变更的数据后,再生成文件发到盖雅服务器里。

开始想把修改数据放内存中,然后直接写到对方文件里,但这样不够稳妥
决定在本地记录一份和目标一样的副本

先把数据在本地写好,再通过已有的服务来传过去,例如《一个Golang接收文件的尝试》。测试一会之后,发现不用这么麻烦,改用 PHP 项目自己解决传递,见《用SFTP传个文件》。一个是减少了影响项目,另一个是利于维护。

但背景是目前的员工数量已经达到了 7k

先把增量员工查出来,再把数据切割成 csv 格式的字符串,写入文件。会出现如下问题:

  • 频繁使用远程连接会出现失败
  • 全量时接口会超时
  • 偶发的内容拼接错误(某一行出现在上一行的中间部分,其它行正常)

第一步考虑用队列先解决数据量大的问题,先优化为:把需要同步的拆分为每 100 一批放入队列,把数据转换为 csv 的一行内容后,先写入本地文件,再把整个本地文件内容复制到远程。

但是用的队列是多个同时消费,最后的结果没有按需要的顺序,并且需要区分每一个内容是属于哪次文件,在单次文件全部结束后再传递到服务器。

改用可用性更高的数据库方式来解决:新建一张表,用来存储员工在文件中对应的一行内容,再新增一个 Listener,在员工进行 CUD 时就新增或修改到新表中,定时任务再通过时间戳去查询。

此时把内容数组存在表中的 JSON 字段时,再取出来放到文件中时,顺序会错乱,是因为 MySQL 在存储 JSON 时按照 KEY 的字段长度做了排序,以便获得更好的存储性能:see JSON比较

To make lookups more efficient, it also sorts the keys of a JSON object. You should be aware that the result of this ordering is subject to change and not guaranteed to be consistent across releases.

所以就把内容字段类型改为 TEXT,切割好了再存进去,取的时候拼个换行符就能用了。这样子就不会出现多次进行远程连接,也留下了可以排查问题的记录。

积累