[原]21.app后端如何高效更新内容

标签: | 发表时间:2015-04-01 05:09 | 作者:newjueqi
出处:http://blog.csdn.net/newjueqi

         在app的主页或通知栏,经常需要通过api取最新的数据。那么,怎么在这部分上做优化,使获取内容的效率更高呢?在本文中,通过推拉和增量更新,实现了一种高效获取数据的策略。

 

1.高效更新数据策略在app中的应用场景

 


如图所示,在app首页,经常会有这种瀑布流形式的内容,具体可参考新浪微博的app。

 

这种内容有以下的特点:

1.      用户访问的频次好(首页一般都经常访问)

2.      看上去数据量很大

 

那么,怎么获取才能高效获取这种首页数据呢?

 

高效的关键是两点:

1.      降低访问的频次

2.      减少数据的传输量

 

内容的推拉和增量更新就能实现高效的关键。

 

2.什么是内容的推拉?

 

在一般的app设计中,如果需要知道首页是否有内容更新,就需要通过一个轮询机制访问api,才能知道是否有内容更新。

 

         但是,轮询的缺点也很明显:

1.      耗电

2.      耗流量

 

轮询是很典型的拉模式,每隔一段很短的时间,就从服务器上拉数据到app,不管实际上有没有数据更新。这样会耗费大量的网络流量,同时也增大了服务器的压力。

 

怎么才能减少轮询的次数。

 

答案就是通过推模式。在服务器上,每当知道有数据更新了,就通过推送系统,告诉相关的app,你有数据更新啦,快点来取啦。当app收到这个数据更新的通知后再调用api,获取相应的数据。

 

当然了,不能只用推模式,因为手机的网络环境的复杂性,不能保证数据更新的通知一定会到达app,所以也要采用轮询的方式来定期拉数据。当然了,使用推拉结合轮询的时候可以设置得比较长,因为主要是以防万一用的。

 

通过这种推拉结合的模式,就能大大减少访问的频次和更新的数据量。

 

3.什么是增量更新?

 

在新浪微博的app中,从别的页面进入主页,在没有网络的情况下,首页中的已经收到的微博还是能显示的,这显然是把相关的数据存储在app本地。

 

使用数据的app本地存储,能减少网络的流量,同时极大提高了用户的体验(想想,很多数据都能在app本地获取,显示的速度当然快)。使用了本地存储后,需要考虑的是数据的增量更新方案。

 

什么是数据的增量更新?假设,用户A的首页在数据表中是有40条数据,id1-40,app每次获取10条数据。第一次运行,app从数据表获取了id1-10条数据同时存储在本地。假设用户离开了这个页面再回到首页,这时app需要再次从数据库中获取数据,由于之前已经有10条数据(id1-10)存储在app本地了,那么现在需要从数据库中获取的10条数据就是从剩余的30条中数据获取(id11-40)后并保存在app本地。这个就是增量更新的典型例子。

 

    增量更新的原理是在数据库中,每条数据都必须有update_time这个值,记录数据最后更新的时间,当app从服务器获取了一次数据后(返回的数据必须按时间排序,update_time最近的在第一条),记录下第一条数据的update_time,当再次获取数据就只需要获取上个时间点到访问服务器这刻为止所更新的数据即可。

 

   因为分页机制的存在,这个算法实现起来是挺多需要注意的地方,下面我举一个简化的例子详细说明:

 

一些假设:

 

1. app每次请求都带4个参数

http://test/api/timeline?count=3&page=1&since=1100&max=1200

count: 每页的显示条数(默认为3)

page: 当前页码(默认为1)

since: 时间戳,若指定此参数,则返回时间戳大于等于since的结果(应该是上次获取的最新数据的update_time)

max: 时间戳,若指定此参数,则返回时间戳少于等于max的结果(应该是发送时的时间)

 

在sql的查询时,使用条件 since<=update_time<= max

 

2. api 返回的数据包含

{

   "size": 10,   //实际返回的数据量(因为分页获取的缘故,所以经常少于total值)

   "total": 284,  //应该返回的总数据量

   "page": 1,

   "count": 3,

   "max": 0, //max为获取的最后一条数据的update_time

   "since": 0

},

{ //返回的数据实体

         data:.......

}

 

3. app存储的本地数据中的update_time是指服务器中的这条数据的更新时间,不是指app中这条数据的更新时间。

 

现在开始讨论:

(1)当app安装完毕后还没启动,服务器的数据表中的数据为3条,app存储的本地数据为空

 

服务器的数据表的数据

id

update_time

1

1100

2

1101

3

1101

 

app存储的本地数据

id

update_time

 

 

(2)当app第一次运行(时间为11:05),因为是第一次运行,since为0,max为现在的时间点1105,在服务器的数据表中获取所有数据。

 

发送的请求为:http://test/api/timeline?count=3&page=1&since=0&max=1105

 

(3)从(2)中发送请求后,api的返回数据,服务器的数据表中的数据,app存储的本地数据如下:

 

api返回的数据

{

   "size": 3,   //实际返回的数据量

   "total": 3,  //应该返回的总数据量

   "page": 1,

   "count": 3,

   "max": 1101,

   "since":0

},

{ //返回的数据实体

         data:.......

}

 

服务器的数据表的数据

id

update_time

1

1100

2

1101

3

1101

 

app存储的本地数据

id

update_time

1

1100

2

1101

3

1101

 

这里是策略的重点(1)api返回数据中的max必须为最后一条数据的update_time

 

(4)现在的时间是11:20,用户点击了页面中“获取更多”的按钮,app应该从服务器的数据表中拉取数据,在发送请求前,服务器的数据表中的数据如下:

 

服务器的数据表的数据

id

update_time

1

1100

2

1101

3

1101

4

1118

5

1118

6

1119

7

1119

 

   可看到,比起上次拉取数据的时候,服务器的数据表多了id为4,5,6,7的数据。

 

   这时发送api请求, 策略的重点(2):当api的返回数据size=total时,since值比上次获取大一点,因为这时数据已经获取完整了,没必要重复获取数据上次已经获取的数据(记得条件since<=update_time<= max 吗?)所以since值设置为1101+1=1102,max为现在的时间点:1120,请求的url如下:

 

http://test/api/timeline?count=3&page=1&since=1102&max=1120

 

发送请求后api的返回数据和app存储的本地数据如下:

 

api返回的数据

{

   "size": 3,   //实际返回的数据量(因为分页获取的缘故,所以经常少于total值)

   "total": 4,  //应该返回的总数据量

   "page": 1,

   "count": 3,

   "max": 1119,

   "since":1102

},

{ //返回的数据实体

         data:.......

}

 

app的数据:

id

update_time

1

1100

2

1101

3

1101

4

1118

5

1118

6

1119

 

 

 

   这里是 策略的重点(3)在数据库中,update_time为1101~1120的数据有4条,但由于分页的缘故,只获取了3条(从size和total参数可以判定),这意味着1101~1120这段时间的数据没有获取完整,app所获取的最后一条数据的update_time是1119,服务器的数据表中剩下的没有被app获取的数据有两种情况:

a.update_time刚好是1119

b.update_time大于1119

 

   由于我们没法判断属于哪种种情况,如果我们下次拉数据的时候 since大于1119,服务器的数据表中id为7的数据不会再获取,那么会造成app中丢失了id为7的数据,所以针对上次数据获取不完整的情况,下次获取数据时since必须是等于1119,虽然有可能会获取重复的数据。

 

(5)现在的时间是11:30,用户点击了页面中“获取更多”的按钮,app应该从服务器的数据表中拉取数据,在发送请求前,服务器的数据表中的数据如下:

 

 

服务器的数据表的数据

id

update_time

1

1100

2

1101

3

1101

4

1118

5

1118

6

1119

7

1119

8

1120

 

 

   这时发送api请求,这里 是策略的重点(4):当api的返回数据size少于total,为了避免有数据丢失,since为上次收到api的返回数据的max值:1119,max为现在的时间点:1130。关于策略重点(4),请结合策略的重点(3)一起理解。

 

请求的url如下:

http://test/api/timeline?count=3&page=1&since=1119&max=1130

 

发送请求后api的返回数据和app存储的本地数据如下:

 

api返回的数据

{

   "size": 3,   //实际返回的数据量(因为分页获取的缘故,所以经常少于total值)

   "total": 3,  //应该返回的总数据量

   "page": 1,

   "count": 3,

   "max": 1120,

   "since":1119

},

{ //返回的数据实体

         data:.......

}

 

   这是策略的重点(5):api中返回数据中id为6的数据,在app的本地数据中已经存在,对于这条数据,app端应该放弃重复插入。

 

最后app存储的本地数据如下:

 

app的数据:

id

update_time

1

1100

2

1101

3

1101

4

1118

5

1118

6

1119

7

1119

8

1120

 

 

   ok,整个增量更新的策略已经分析完毕了。在这个策略中,page参数几乎没用,之所以要保留,是为了兼容分页不带since,max的情况。对于这个增量更新的策略,请仔细理解 策略的重点(1)(2)(3)(4)(5)的分析。

 

    增量更新的策略,还要处理一个删除数据的同步问题。假设,在服务器的数据表要删除一条数据,怎么通知app本地也删除这条数据。我们的解决方案是服务器的服务器的数据表中增加一个标识is_delete,当需要在业务逻辑上删除的时候,把这条数据的is_delete设为1,同时更新update_time。当app增量更新检测到这条is_delete为1的数据,就在app本地数据中把这条数据删除。为了避免在服务器保存太多的数据,在服务器设置一个crontab,定期把那些已经标识is_delete设为1的数据删除。


---------------------------------------------------------------------------------------------------------------------------

打开链接   app后端系列文章总目录 总目录 ,能查看本人发表过的所有原创“app后端”文章。

【作者】曾健生
【QQ】190678908
【app后端qq群】254659220 
【微信公众号】 appbackend
【新浪微博】 @newjueqi
【博客】http://blog.csdn.net/newjueqi 

 

作者:newjueqi 发表于2015/3/31 21:09:44 原文链接
阅读:19 评论:0 查看评论

相关 [app 后端 更新] 推荐:

[原]21.app后端如何高效更新内容

- - 曾健生的专栏
         在app的主页或通知栏,经常需要通过api取最新的数据. 那么,怎么在这部分上做优化,使获取内容的效率更高呢. 在本文中,通过推拉和增量更新,实现了一种高效获取数据的策略. 1.高效更新数据策略在app中的应用场景. 如图所示,在app首页,经常会有这种瀑布流形式的内容,具体可参考新浪微博的app.

18.app后端如何实现LBS

- - CSDN博客推荐文章
移动互联网,除了一直在线这个特点外,还有一个重要特点,能定位到手机的位置. 查找附近的人,附近的餐馆等服务,以及大量的o2o应用, 都需要使用LBS(Location Based Services). 1.如何获取用户的地理坐标.   现在,基于手机来获取用户的地理坐标,主要是下面两种方法:.   (1)使用手机上的GPS模块.

14.app后端如何设计api

- - CSDN博客推荐文章
app和后端的交互,一般都是通过后端提供的api实现. api的设计,估计很多刚进入app后端的小伙伴会一无头绪,不知道怎么入门. 下面根据自己3年的app后端经验,总结出下几个api设计原则,给小伙伴参考.   这个问题在以前发表的文章“7.app和app后端的通讯”中其实已经回答了,这里再重复一次.

移动APP后端网络处理一些问题记录

- - BlogJava-首页技术区
这里讲的移动APP主要指的是安卓平台,大部分情况也适用于IOS等移动平台,可能重点嘛会在后半部分呢. 但凡一个常用的APP都会嵌入至少一个SDK,不同来源或同一来源,有广告SDK,有推送SDK,有性能汇报SDK,有用户跟踪SDK,有统计流量SDK等,有支付SDK等等. 虽然带来了功能的复用和解耦,便于纵向扩展,但可能会存在:.

[原]23.app后端如何架设文件系统

- - 曾健生的专栏
         现在app展现内容的形式多种多样的,有文字,图片,声音,视频等等,其中文件占了一个很大的比重. 随着app不断运营,文件会越来越多,占用的磁盘空间也不断增大,架设一套高效的文件系统,对于整个app架构有着巨大的影响. 1.    如果可能,使用成熟的文件云存储服务.        对于创业公司来说,我一直推崇的架构原则是“ 尽量使用成熟的第三方服务和软件,自己只负责业务逻辑”.

每天更新正版免费iPhone app活动的站点

- Pei - 煎蛋
Dealzon这个网站上经常有各种折价活动,以及亚马逊免费CD、还有免费样品赠送啥的……可惜的是,仅限US地区. 不过嘛,上面那些限时免费的iPhone和iPad apps倒是不限地区的. 点开那些条目之后会自动跳转到你的iTunes页面,直接点击购买就行了. 需要注意的是大多数的免费期只有一天,如果它自动在iTunes里打开后你看到价钱不是“Free”的话……不好意思你晚了一步,还是继续去试试别的吧.

苹果更新 App Store 应用排行榜数据

- - 果迷网
苹果公司在 App Store 应用下载突破250亿次这个里程碑之后,随即更新了 App Store 排行榜数据,列出了过去12个月内付费及免费应用软件的排行情况. 在看完整的排行榜之前先了解下一些有意思的数据吧:(针对美国区). iPhone 付费应用软件排行榜中有17款是游戏. iPhone 付费应用软件排行榜中没有苹果应用.

[原]17.app后端如何保证通讯安全--aes对称加密

- - 曾健生的专栏
在上文《16.app后端如何保证通讯安全--url签名》提到,url签名有两个缺点,这两个缺点,如果使用对称加密方法的话,则完全可以避免这两个缺点. 在本文中,会介绍对称加密的具体原理,和详细的方案,使app通讯更加安全.   采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密.

Evernote iPhone, iPad App 關鍵更新,中文介面與支援富文本編輯

- Amo - 電腦玩物
開場白還是那句老話:Evernote是我個人慣用的數位筆記本. 接著,繼之前「Evernote Android 關鍵更新,支援富文本編輯與桌面預覽便利貼」後,今天Evernote的iOS App也進行了一番大改造,其中最關鍵的新功能,就是繼Android版本後,現在iPhone、iPad上的Evernote也可以擁有富文本編輯工具列,並且擁有中文介面了.

让更新App内建营销内容像写博客一样简单

- 书皮 - 互联网的那点事...
移动应用营销平台PlayHaven今天发布了一个新工具,让开发者能像写博客那样轻松简单的完成对App内商业营销内容的更新,大大增强了应用的生命力. PlayHaven的新工具有些类似于一个商业营销部分的内容管理系统. 可以让开发者快捷的更新App内的营销内容,比如在特定时间内给用户发放游戏币,提醒用户有新的版本升级可以使用,以及向用户推荐自己的新作品等等.