posts - 12, comments - 8, trackbacks - 0, articles - 5
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

数据同步系统设计

Posted on 2011-04-06 15:50 杨罗罗 阅读(3581) 评论(3)  编辑  收藏

一. 应用场景

在大型分布式应用中,我们经常碰到在多数据库之间的数据同步问题,比如说一款游戏,在玩家注册后,可以马上登陆进入服务器,数据在一个IDC更新,其它IDC立即可见。为了简化思路,我们这里称玩家注册的数据库(数据来源库)为中心库,同步目的地的数据库为分站库。

在分布式领域有个CAP理论,是说Consistency(一致性), Availability(可用性), Partition tolerance(分区和容错) 三部分在系统实现只可同时满足二点,法三者兼顾。

能做的

· 数据快速搬运到指定的IDC节点

· 数据传递过程中失败时,重新传递

· 监控数据传递流程

· 故障转移

· 数据版本控制

· 分配全局唯一的ID

不能做的

· 不参与业务行为,业务操作只能通过注册的方式集成

· 不保存业务数据,不提供传递的业务的查询

二.系统要求

1.数据快速同步:除去网络原因,正常情况下从来源库同步到接收库的时间不超过300m2.高并发:单个应用每秒同步2000条记录
3.可伸缩性,在资源达到上限时能通过增加应用分散处理后期增长的压力
4.数据完整性要求,在数据同步过程中保证数据不丢失和数据安全
5.故障转移和数据恢复功能

三.设计思路

系统优化,最常用的就是进行业务切割,将总任务切割为许多子任务,分区块分析系统中可能存在的性能瓶颈并有针对性地进行优化,在本系统中,主要业务包含以下内容:
1.Syncer:外部接口,接收同步数据请求,初始化同步系统的一些必要数据
2.Delivery:将同步数据按照业务或优先级进行分发,并记录分发结果
3.Batch:分站库收到同步数据后,根据不同的业务类型调用相应的业务逻辑处理数据
基于以上三块业务功能,我们可以把整个数据同步流程切割为3个应用,具体如下图显示。在Syncer端应用中,我们需要将原始同步数据和分发的分站进行存储,以备失败恢复,此时如果采用数据库进行存储,势必会受限于数据库性能影响,因此我们采用了高效的key-value风格存储的redis服务来记录数据,同时在不同应用之间采用队列(Httpsqs服务)的方式来进行通讯,同时也保证的数据通讯的顺序性,为之后的顺序同步做好基础。
Httpsqs提供了http风格的数据操作模式,业务编码非常简单,同时也提供了web形式的队列处理情况查询,这是选择它做队列服务很大一部分原因:方便业务操作和性能监控。

四.数据流转 

绿色-正常流程、红色-异常流程

队列处理

根据业务划分队列名称,每个队列再划分为三个关联队列:正常队列(Normal)、重试队列(Retry)、死亡队列(Death),处理流程为:

【进程A】把数据先放入正常队列,如果放置失败写恢复日志

【进程B】监听正常队列,获取队列数据并进行业务处理,处理失败放入重试队列

【进程C】监听重试队列,过几秒获取队列数据并重新进行业务处理,处理失败放入死亡队列

【进程D】监听死亡队列,获取队列数据并重新进行业务处理,处理失败重新放入死亡队列尾部,等待下一次轮回

业务处理失败如果无法再次放入队列,记录恢复日志

数据同步流程

1发送数据,支持Http POST:curl -d "经过URL编码的文本消息",如"http://host:port/sync_all/register"
或者Http GET:curl "http://host:port/sync_all/register?data=经过URL编码的文本消息"

sync-syncer接收到同步数据请求,创建sid并分解出需要同步的节点个数,把原始数据和子任务写入redis中,sid写入httpsqs中

sync-delivery监听中心httpsqs队列,根据sid从redis获取到原始数据和需要同步的节点地址,往其他节点发送数据,流程如按"队列处理流程"进行

sync-batch监听分节点的httpsqs队列,调用已经注册的处理器处理队列数据,流程如按"队列处理流程"进行

三. 恢复和监控

恢复数据源

· httpsqs中的死亡队列 - 业务处理暂时处理不了的数据

· recovery日志文件 - 其它异常情况下的数据,例如网络无法连接、内部服务不可用

数据恢复

独立的应用来处理正常流程中没有完成的任务,主要功能有:

· 监听死亡队列,进行业务重做,再次执行失败时将执行次数+1,最大执行次数为5(默认),超出上限则记录到恢复日志中

· 读取恢复日志,重新放入死亡队列

应用监控

· 使用scribe日志框架服务业务日志的采集和监控

· 收集重要的业务操作日志

· 动态的开启/关闭某类业务日志

· 对redis进行监控

· 对httpsps,监控队列个数,每个队列的状态

四. 数据结构

{"sid":111,"type":"reg","v":1,"data":"hello world","ctime":65711321800,"exec":1}

· sid(sync id) - 全局唯一id

· v(version) - 版本号

· data - 业务数据

· ctime(create time) - 创建时间(毫秒)

· exec - 可选,执行次数

类别

key格式

value格式

备注

redis原始数据

sync:<业务类型>:<sid>

{"ctime":65711321800,"v":1,"data":"hello world"}

分站没有此项

redis业务附加任务

sync:<业务类型>:<sid>:sub

set类型,保存需要同步的节点id,例如[1,3,5]

分发确认Set数据结构 

httpsqs队列

sync:<业务类型> 
sync:<业务类型>:retry 
sync:<业务类型>:death

{"sid":111,"type":"pp_register","exec":1} 

中心队列内容,key中<业务类型>是可选项 

httpsqs队列

sync:<业务类型> 
sync:<业务类型>:retry 
sync:<业务类型>:death

{"sid":111,"v":1,"data":"hello world","ctime":65711321800,"exec":1} 

分站队列内容,包含业务数据 

所有的key都小写,以 ':' 作为分隔符

五.编码及测试结果

经过编码和测试,在内网环境下,在无数据库限制的情况下,单应用可以传递1500条/秒,基本满足业务需求。如果需进一步扩展,采用集群式布署可使得吞吐量成倍的增长。


评论

# re: 数据同步系统设计  回复  更多评论   

2013-07-29 16:02 by adf
asdfasdfadsf

# re: 数据同步系统设计[未登录]  回复  更多评论   

2013-11-06 17:23 by 鱼中鱼
要是有个示例就好了。

# re: 数据同步系统设计  回复  更多评论   

2013-12-26 16:41 by bolo
太慢了吧,才2000条/s,我做的可以7000条/s

只有注册用户登录后才能发表评论。


网站导航: