[原]增量接口的设计及实现

标签: | 发表时间:2017-03-20 16:45 | 作者:ghsau
出处:http://blog.csdn.net/ghsau

引言

在应用开发过程中,我们总会碰到这样的场景:某系统需要同步我们系统的数据去做一些业务逻辑,当数据量较小的时候,可以全量的提供,但当数据量很大时,全量提供就显得很笨重,不仅耗时而且做了很多无用功,这时我们需要一种提供增量数据的机制,只告诉对方变化的数据。提供增量数据大致可分为两种方式:MQ和接口提供,MQ的优点是及时,缺点是丢失、重复、回溯复杂等等问题(依赖于具体MQ实现),这里不过多赘述;接口提供不限于RPC或HTTP等方式,接口提供的优缺点正好和MQ反过来,及时性取决于调用周期。P.S.本文描述的数据同步区别于数据库层的同步,应用层的同步表不一定同构,或者都不落地。

Created with Raphaël 2.1.0这图真TM丑AABBsync datado something

接口设计

只需要一个version参数,其它参数根据实际业务场景添加,返回值中也加入version,调用端使用返回值中的version用于下次调用。

接口使用

  String lastVersion = getLastVersion();// 拿到上一次版本号
try {
    while(true) {
        List<Data> datas = syncData(lastVersion);// remote or local
        if (datas.isEmpty()) {
            break;
        }
        for (Data data : datas) {
            // 1. 做一些逻辑处理
            // ...............  
            // 2. 暂存version
            lastVersion = data.getVersion();
        }
    }
} finally {
    saveVersion(lastVersion);// 保存版本号
}

以上代码需要放到一个定时调度模块中,周期越短,数据延时越低。如果由于故障或BUG导致处理出现问题时,只需将版本号向前调整即可,回溯简单。

接口实现

实现要考虑以下几个方面,内存占用、version设计、数据删除。

内存占用

增量接口很可能被其它系统频繁的调用,尤其当我们系统中有一种很核心的数据,所以要对每次调用返回的数据量有一个控制,比如每次只返回1000条,后面描述都以1000条为例。我建议这个数据量控制在数据提供方,而不是调用方,即便调用方可以控制,提供方也要做一个最大限制。

version设计

假设我们的数据类似于下表:

id update_time
2 2017-03-09 23:59:59
68 2017-03-09 23:59:59
26 2017-03-09 23:59:59
71 2017-03-09 23:59:59
17 2017-03-09 23:59:59
14 2017-03-09 23:59:59
11 2017-03-09 23:59:59
8 2017-03-09 23:59:59
5 2017-03-09 23:59:59
65 2017-03-09 23:59:59
66 2017-03-09 23:59:59

version设计很多人第一时间会想到数据更新时间,SQL可能是这样:

  SELECT * FROM data 
WHERE update_time > #{version} 
ORDER BY update_time ASC LIMIT 1000;

当很多数据update_time一样时,会丢失数据。比如上一批次返回的最后一条是id=71,version是2017-03-09 23:59:59,那本次查询就会忽略后面update_time=2017-03-09 23:59:59的数据。这时可能又有人想到下面这样的方式:

  SELECT * FROM data 
WHERE update_time >= #{version} 
ORDER BY update_time ASC LIMIT 1000;

update_time加了个=,这样是不会丢数据了,但是会返回重复数据,甚至死循环。比如比如上一批次返回的最后一条是id=71,version是2017-03-09 23:59:59,id=71后面有10000条update_time=2017-03-09 23:59:59的数据,接口每次返回1000条,这时调用端永远跳不出这批数据了。鉴于上面的问题,显然version单单使用数据更新时间已经不够了,这时可以加入其它辅助项,比如自增ID。比如比如上一批次返回的最后一条是id=71,这时的version格式是这样: 2017-03-09 23:59:[email protected],SQL变成下面这样,分两步查询:

  第一步: 查询update_time = '2017-03-09 23:59:59'并且id > 71的数据;
  SELECT * FROM data 
WHERE update_time = '2017-03-09 23:59:59' AND id > 71
ORDER BY update_time ASC, id ASC LIMIT 1000;
  第二步: 查询update_time > '2017-03-09 23:59:59'的数据;
  SELECT * FROM data 
WHERE update_time > '2017-03-09 23:59:59'
ORDER BY update_time ASC, id ASC LIMIT ?;

这里有一些细节需要控制,如果第一步返回的数据量已经达到1000,则不需要执行第二步,如果小于1000,则需要执行第二步,数据量应该依据第一步返回的数据量计算。最终,version的格式: 更新时间毫秒数@数据自增id,上面为了方便说明,直接用了格式化后的时间。

数据删除

增量数据的获取是依赖更新时间,这就有一个隐含的前提,需要数据存在,如果数据真正的删除了,那也就不能获取到这条数据的变更了。所以,通过接口提供增量数据不能真删数据,而要假删(增加一个状态,表示有效或无效),这也算一个缺点吧。

作者:ghsau 发表于2017/3/20 15:26:57 原文链接
阅读:11 评论:0 查看评论

相关 [接口 设计] 推荐:

API 接口设计规范

- - 掘金后端
这篇文章分享 API 接口设计规范,目的是提供给研发人员做参考. 规范是死的,人是活的,希望自己定的规范,不要被打脸. url?后面的参数,存放请求接口的参数数据. 请求头,存放公共参数、requestId、token、加密字段等. Body 体,存放请求接口的参数数据. 调用方需向服务方申请 appKey(请求时使用) 和 secretKey(加密时使用).

接口设计评审规范 - 简书

- -
本接口设计规范,参考了restfull的部分设计理念. Restful API的核心元素,所有的操作都是针对特定资源进行的. 任何事物,只要有被引用到的必要,它就是一个资源. 资源可以是实体(例如手机号码),也可以只是一个抽象概念(例如价值). Github 可以说是这方面的典范,下面我们就拿. 资源分为单个文档和集合,尽量使用复数来表示资源,单个资源通过添加 id 或者 name 等来表示.

设计好接口的36个锦囊

- - 掘金后端本月最热
大家好,我是捡田螺的小男孩. 作为后端开发,不管是什么语言, Java、 Go还是 C++,其背后的后端思想都是类似的. 后面打算出一个后端思想的技术专栏,主要包括后端的一些设计、或者后端规范相关的,希望对大家日常工作有帮助哈. 我们做后端开发工程师,主要工作就是: 如何把一个接口设计好. 所以,今天就给大家介绍,设计好接口的36个锦囊.

API设计新思维:用流畅接口构造内部DSL

- 风子 - 酷壳 - CoolShell.cn
感谢@weidagang (Todd)向酷壳投递本文. 程序设计语言的抽象机制包含了两个最基本的方面:一是语言关注的基本元素/语义;另一个是从基本元素/语义到复合元素/语义的构造规则. 在C、C++、Java、C#、Python等通用语言中,语言的基本元素/语义往往离问题域较远,通过API库的形式进行层层抽象是降低问题难度最常用的方法.

如何正确合理的设计一个接口项目

- - CSDN博客架构设计推荐文章
首先,我这里说明接口,不是代码里的接口,而是接口项目,如果想错了就不用往下看了. 在手机广泛流行的今天,手机应用也随之越来越多,而且成长的速度也非常快. 手机应用软件开发实现方式同普通PC软件一样,也分为BS和CS方式. 而采用CS方式,在服务器端大多采用接口的形式提供数据交互(主流数据交互方式有:Json、WebService等),今天要说的就是如何设计接口.

[原]增量接口的设计及实现

- - 高爽|Coder
在应用开发过程中,我们总会碰到这样的场景:某系统需要同步我们系统的数据去做一些业务逻辑,当数据量较小的时候,可以全量的提供,但当数据量很大时,全量提供就显得很笨重,不仅耗时而且做了很多无用功,这时我们需要一种提供增量数据的机制,只告诉对方变化的数据. 提供增量数据大致可分为两种方式:MQ和接口提供,MQ的优点是及时,缺点是丢失、重复、回溯复杂等等问题(依赖于具体MQ实现),这里不过多赘述;接口提供不限于RPC或HTTP等方式,接口提供的优缺点正好和MQ反过来,及时性取决于调用周期.

从 Feign 使用注意点到 RESTFUL 接口设计规范 - ImportNew

- -
最近项目中大量使用了Spring Cloud Feign来对接http接口,踩了不少坑,也产生了一些对RESTFUL接口设计的想法,特此一篇记录下. SpringMVC的请求参数绑定机制. 了解Feign历史的朋友会知道,Feign本身是Netflix的产品,Spring Cloud Feign是在原生Feign的基础上进行了封装,引入了大量的SpringMVC注解支持,这一方面使得其更容易被广大的Spring使用者开箱即用,但也产生了不小的混淆作用.

API接口设计之token、timestamp、sign具体实现

- - 企业架构 - ITeye博客
Token:访问令牌access token, 用于接口中, 用于标识接口调用者的身份、凭证,减少用户名和密码的传输次数. 一般情况下客户端(接口调用方)需要先向服务器端申请一个接口调用的账号,服务器会给出一个appId和一个key, key用于参数签名使用,注意key保存到客户端,需要做一些安全处理,防止泄露.

API 接口设计之 token+sign 具体架构与实现

- - 小决的专栏
在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃取). 除了 https 的协议之外,能不能加上通用的一套算法以及规范来保证传输的安全性呢. Token:访问令牌 access token, 用于接口中,用于标识接口调用者的身份、凭证,减少用户名和密码的传输次数.

聊聊接口设计的36个小技巧

- - IT瘾-dev
作为后端开发,不管是什么语言, Java、 Go还是 C++,其背后的后端思想都是类似的. 后面打算出一个后端思想的技术专栏,主要包括后端的一些设计、或者后端规范相关的,希望对大家日常工作有帮助哈. 我们做后端开发工程师,主要工作就是: 如何把一个接口设计好. 所以,今天就给大家介绍,设计好接口的36个锦囊.