首页
随机
最近更改
特殊页面
社群首页
参数设置
关于WHY42
免责声明
WHY42
搜索
用户菜单
登录
欢迎来到Riguz的小站!这是一个私人wiki,用来记录一些我的笔记。
查看“︁Blog:一个数据导入的有趣问题”︁的源代码
←
Blog:一个数据导入的有趣问题
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
相比于传统的单体应用,在基于微服务架构的系统中进行数据导入的操作显得更加复杂一点。通常而言,微服务的架构中包含了多个服务,服务的技术架构也可能大相径庭,同时考虑到拓展的需要,每个服务都有可能会拓展成多个instance。最近遇到一个有趣的问题,进行了一些思考。 场景大致是这样的: * 我们有一个单独的service(以下简称SM),每天定时从一个目录读取文件(一个压缩包)。其中这个包中包括多个文件,分别对应到不同的业务数据,这些数据又影响到多个不同的service(以下简称SA,SB,SC) * 于是SM读取到文件之后,解析文件,并通过消息发送给SA,SB,SC。收到消息大小的限制,文件中的内容不能一次性发送完成,需要拆分成N个消息(比如每200条数据一个消息) * SA,SB都是增量更新,因此收到数据后,要么新增,要么更新,就可以了。很完美。 * 但是SC确每次都是全量更新。 问题来了,如果按照SA,SB的做法,SC面临的问题有两个: * 如果没有办法区分一条数据是新增还是更新,那直接有问题 * 即便可以,如何能删除多余的数据? 譬如原来有200条,现在过来150条,这150条更新了,多余的50条则没有办法删除 一个直接的办法是在SM开始的时候,先去SC删除所有的数据,然后再将数据发送过去就可以了。但是这样带来的问题就是,万一后面导入失败了,而删除已经做了,会造成以前的数据也不可用。这在我们的业务场景里面是比较致命的,应该至少保证同步失败的时候,保持上一次的数据。基于这个场景,想了一个解决方案: * 在数据表中加一个version字段标识,表示是哪一批次的数据 * 创建一个视图,根据version来查询出最新的数据 * 同步完成之后,更新视图 下面详细来说。假定我们是一个K-V类似的配置的导入,首先创建表和视图: <syntaxhighlight lang="sql"> create table t_raw_config( id int not null primary key auto_increment, `version` char(6) not null, name varchar(50) not null, value varchar(100) ); create view t_config as select id, name, value from t_raw_config; </syntaxhighlight> 在SM中,我们需要做的事情是: * 在导入开始的时候,生成一个唯一的version,简单一点,我们根据日期来,比如${\displaystyle version=20190101}$ * 假定有1001条数据,每200个拆分成1个message,则有6个${\displaystyle message=\{1, 2, 3, 4, 5, 6\}}$ * SC中,每消费完成一个message,则记录下消费的message到一个列表中,例如${\displaystyle messages20190101 = \{1, 2\}}$(例如存储在redis中) * SM中解析完成后,告知SC所有的message,即${\displaystyle message=\{1, 2, 3, 4, 5, 6\}}$ * SC收到告知后,比对${\displaystyle messages20190101}$是否与${\displaystyle message=\{1, 2, 3, 4, 5, 6\}}$匹配,如果不匹配则等待(可以利用redis的BLPOP实现,如果不匹配则不断去BLPOP) * 所有的消息都消费完成后,更新视图,将version设置为${\displaystyle version=20190101}$。如果考虑到性能问题,可以再version字段上建索引;考虑空间问题,可以在这一步以前version的数据
返回
Blog:一个数据导入的有趣问题
。