对于广告投放系统,有如下模块:
- 落地页:用户点击广告位进入的广告展示页面。
- 蜂巢系统:用户提交的数据进行存储的模块。
- CRM系统:客户关系系统,用于后台业务人员联系、分析用户的模块。
- 同步系统:蜂巢系统与CRM系统进行同步数据的模块。
有如下业务逻辑:
用户点击广告进入广告落地页,用户在落地页填写个人信息后点击提交按钮,用户信息和广告唯一APPKEY被发送至蜂巢系统,蜂巢系统将用户数据进行存储。此后,同步系统将蜂巢系统获取的用户数据同步至到CRM系统。现需要设计一个完善的同步系统。同时,CRM系统有多种,要进行多系统适配。
系统需求
蜂巢系统与CRM系统数据的同步
系统要求
高可用性
一致性
可恢复性
设计思路
考虑到蜂巢系统对于可用性的要求可能较高,CRM系统对一致性要求较低,因此对于CAP理论,优先满足可用性(A)和分区容错性(P),允许最终一致性。此种策略虽然会影响CRM系统使用体验,但没达到造成用户流失的程度。
因此同步系统采用轮询机制。即同步系统根据策略定时向蜂巢系统进行数据拉取。
同时以备数据丢失,将同步操作唯一ID以及同步数据存入Redis。
数据同步流程
- 轮询服务器按照轮询策略发出请求,创建同步操作唯一ID
- 增量查询服务对蜂巢系统数据库进行查询,按照查询方案确定需要更新的数据
- 将同步操作唯一ID和同步数据存入Redis
- 将获取的更新数据发送给数据分发服务器
- 数据分发服务器将数据发送至主线队列,数据等待被处理
- 数据处理层根据队列中已经注册的数据同步请求,按顺序处理更新数据
- 数据处理层将更新数据更新至CRM系统中
- 记录操作日志
增量查询规则
为蜂巢中的数据表添加UpdateTime
字段。即对于蜂巢系统中,新增加一条记录时或者修改一条记录时,UpdateTime
字段都会更新为当前的时间戳。
则对于Insert
、Update
操作的数据,增量查询服务器策略如下:
- 初次同步时,记录一下最大的
UpdateTime
时间戳,保存到一个记录表中。 - 后续同步时,用记录表中的时间戳与蜂巢源表里的
UpdateTime
相比较,比时间戳大的说明是新添加的或者修改的数据。 - 当整个同步成功之后,更新最大的
UpdateTime
到记录表中。
对于蜂巢中的删除操作,则可以在数据表中添加IsDelete
字段,执行删除时,将IsDelete
字段设置为1,同时更新UpdateTime
,此时就相当于简单的Update数据。
队列处理
对于数据处理的性能问题,可以通过消息队列来一组一组处理订单数据,数据处理层前的等候队列划分为如下三层:主线队列、重试队列、死亡队列,处理流程为:
- 把数据先放入主线队列,如果放置失败,将当前消息记录至恢复日志
- 监听主线队列,获取队列数据并进行处理,处理失败放入重试队列
- 监听重试队列,过几秒获取队列数据并重新进行处理,若三次处理失败则放入死亡队列,不再进行重试,记录恢复日志,等待人工处理
恢复和监控
日志源
- 恢复日志
- 其他异常情况下的日志记录,如网络无法连接、服务不可用等
数据恢复
- 对于恢复日志记录的数据进行人工操作
- 对于其他异常造成的数据丢失,使用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 | 主线队列、重试队列、死亡队列 |
CRMAdaper | CRM适配器接口 |
FirstCRMAdaper、SecendCRMAdapter | 两种类型的CRM系统实现类 |
HTTP | 请求类 |
图中蓝色线除抽象队列类和三个子类之间的代表实现关系外,其余代表依赖关系
白线代表泛化关系