对于广告投放系统,有如下模块:

  • 落地页:用户点击广告位进入的广告展示页面。
  • 蜂巢系统:用户提交的数据进行存储的模块。
  • CRM系统:客户关系系统,用于后台业务人员联系、分析用户的模块。
  • 同步系统:蜂巢系统与CRM系统进行同步数据的模块。

有如下业务逻辑:

用户点击广告进入广告落地页,用户在落地页填写个人信息后点击提交按钮,用户信息和广告唯一APPKEY被发送至蜂巢系统,蜂巢系统将用户数据进行存储。此后,同步系统将蜂巢系统获取的用户数据同步至到CRM系统。现需要设计一个完善的同步系统。同时,CRM系统有多种,要进行多系统适配。

系统需求

蜂巢系统与CRM系统数据的同步

系统要求

  • 高可用性

  • 一致性

  • 可恢复性

设计思路

考虑到蜂巢系统对于可用性的要求可能较高,CRM系统对一致性要求较低,因此对于CAP理论,优先满足可用性(A)和分区容错性(P),允许最终一致性。此种策略虽然会影响CRM系统使用体验,但没达到造成用户流失的程度。

因此同步系统采用轮询机制。即同步系统根据策略定时向蜂巢系统进行数据拉取。

同时以备数据丢失,将同步操作唯一ID以及同步数据存入Redis。

数据同步流程

  1. 轮询服务器按照轮询策略发出请求,创建同步操作唯一ID
  2. 增量查询服务对蜂巢系统数据库进行查询,按照查询方案确定需要更新的数据
  3. 将同步操作唯一ID和同步数据存入Redis
  4. 将获取的更新数据发送给数据分发服务器
  5. 数据分发服务器将数据发送至主线队列,数据等待被处理
  6. 数据处理层根据队列中已经注册的数据同步请求,按顺序处理更新数据
  7. 数据处理层将更新数据更新至CRM系统中
  8. 记录操作日志

增量查询规则

为蜂巢中的数据表添加UpdateTime字段。即对于蜂巢系统中,新增加一条记录时或者修改一条记录时,UpdateTime字段都会更新为当前的时间戳。

则对于InsertUpdate操作的数据,增量查询服务器策略如下:

  • 初次同步时,记录一下最大的 UpdateTime 时间戳,保存到一个记录表中。
  • 后续同步时,用记录表中的时间戳与蜂巢源表里的 UpdateTime 相比较,比时间戳大的说明是新添加的或者修改的数据。
  • 当整个同步成功之后,更新最大的 UpdateTime 到记录表中。

对于蜂巢中的删除操作,则可以在数据表中添加IsDelete字段,执行删除时,将IsDelete字段设置为1,同时更新UpdateTime,此时就相当于简单的Update数据。

队列处理

对于数据处理的性能问题,可以通过消息队列来一组一组处理订单数据,数据处理层前的等候队列划分为如下三层:主线队列、重试队列、死亡队列,处理流程为:

  1. 把数据先放入主线队列,如果放置失败,将当前消息记录至恢复日志
  2. 监听主线队列,获取队列数据并进行处理,处理失败放入重试队列
  3. 监听重试队列,过几秒获取队列数据并重新进行处理,若三次处理失败则放入死亡队列,不再进行重试,记录恢复日志,等待人工处理

恢复和监控

日志源

  • 恢复日志
  • 其他异常情况下的日志记录,如网络无法连接、服务不可用等

数据恢复

  • 对于恢复日志记录的数据进行人工操作
  • 对于其他异常造成的数据丢失,使用Redis内存储的数据进行恢复

应用监控

大概需要下面几个监控的指标:

  • 监控队列个数以及每个队列的状态
  • 任务错误数
  • 目标CRM系统负载
  • Redis监控

操作日志数据结构

{
	"id": 111,
	"data": ["insert into customer (APPKEY,uid,phone,UpdateTime) values ('ASDAD',12345,15888888888,65711321800)"],
	"start_at": 65711321800,
    "end_at": 65711321801,
	"result": 1
}
参数名说明
id同步操作唯一ID
data同步数据
start_at操作开始时间
end_at操作完成时间
result操作结果

UML说明

说明

类名说明
Poll轮询服务器
Increment增量查询服务器
DistributerCenter数据分发中心
DataHandler数据处理层
Queue队列抽象类
MainQueue、RetryQuene、DeadQueue主线队列、重试队列、死亡队列
CRMAdaperCRM适配器接口
FirstCRMAdaper、SecendCRMAdapter两种类型的CRM系统实现类
HTTP请求类

图中蓝色线除抽象队列类和三个子类之间的代表实现关系外,其余代表依赖关系

白线代表泛化关系