BBSSDK是一套能快速实现discuz论坛移动化的一套解决方案。今天主要讲讲这个产品的数据同步存储原理。
主要从这三个方面:一.存储机制;二.版本控制;三.同步原理。
一.存储机制
首先要理清我们有哪些内容,在对内容进行各种不同程度的存储和持久化。
根据内容类型我们分为:文本和多媒体。主要同步的内容就是文本内容,多媒体内容基本通过URL的形式进行访问,存储方式可以在用户的服务器端和我们提供的(或第三方提供的)对象存储系统。
文本内容又拆分为不同的等级:高频内容,低频内容,冷内容。
高频内容我们根据业务也进行进一步的拆分,核心的业务比如论坛版块、用户组、最新热帖等。进行主要的内容同步。而一些不是核心业务的内容比如家园、博客就没有在我们项目的同步规划内。
低频内容包括有用户,陈贴等,通过异步激活的方式进行数据的同步。
冷内容比如僵尸用户,历史广告数据等,这部分内容就在用户的论坛上而不参与BBSSDK线上逻辑。
理清了需要存储的数据,就需要对各种等级数据进行存储。在存储方案中有两种选择nosql和RDBS,考虑到没有复杂的事务性操作和读写效率,最终选择了mongodb作为线上数据存储服务。mongodb在热数据的查询和raw的快速写入,由于其在数据读写方面由于充分使用速度快的内存而占据优势。一些更高频内容(比如板块列表等)又在redis里面进行持久化,方便高并发的同时减少磁盘的IO。
二.版本控制
怎么去处理内容?当前内容是否最新?需要我们去维护一套内容的版本信息。在用户服务器需要一套,这样可以通知或提交最新的内容;平台也需要一套,知道这些通知或内容是否值得去获取和存储。
由于版本控制要保持内容的最终一致性,这就必须要有一个原子时钟。这个时钟就以用户服务器里的DB时间为标准。
用户服务器根据DB的触发器记录状态缓存在版本信息表里,后提交(或平台发送心跳获取)版本信息通知平台来获取数据。平台根据请求体或返回体里面的时间,或每次成功返回的头信息去维护平台自己的版本信息库。
三.同步原理
同步原理分三个部分:1.传输方式,2.时效性,3.安全性
1.传输方式,选择了http(s)的方式进行数据的推拉同步,首先http的兼容性高,只要是discuz的论坛搭建在虚拟空间也支持,不需要额外的环境配置;二是由于http是TCP协议稳定性好,缺点也就是耗费网络IO增加用时。
2.时效性,涉及到网络同步总会有延迟,怎么做到用户无感知延迟的内容同步?用户的网站千差万别,有些时候总会遇到不可避免的因素,导致获取消息的不及时,怎么解决最终内容的一致性?主要从三个方面进行:a.初始化方式;b.通知队列的消耗方式;c.心跳轮询机制。
a.初始化方式
在论坛插件安装成功后,会发送一个通知给平台。平台根据队列开启线程发起初始化。
初始化由于内容上我们进行了各种颗粒的切割,所以这个初始化不是整个论坛的全量数据同步。而是获取必要的配置信息,再加上高频的热内容同步在平台上。类似CDN的初始化流程。
b.通知队列的消耗方式
在通知队列中的每条通知需要描述当前任务的属性:包含权重,任务细节等。当消费者消耗通知队列的时候,去判断当前任务在版本描述中是否值得去获取,再通过http请求去获取内容,如果遇到不可避免因素导致内容获取失败,就需要对当前任务进行指数型递增下一次的执行时间。这样在不影响健康论坛运行的同时保持问题论坛内容的一致性。
如果一个论坛一直在发送通知而获取不到内容。在一个时间段达到一定数量级,我们可以判断当前论坛已经假死。为保证平台资源的合理利用,对问题论坛进行临时关闭,拉高指数重试,这样如果问题论坛还需要平台提供服务就需要再次提交初始化请求。
c.心跳轮询机制
在定长的时间内,平台会发送请求去目标论坛进行最新版本信息的获取。如果目标论坛没有返回。在多次无效的情况下,平台会判定目标网站已经关闭服务不再发起心跳轮询。
如果论坛用户是卸载了插件应用,就需要重新安装论坛插件,再次初始化服务。
如果论坛用户只是临时关闭服务或论坛出现短暂问题,插件在前端埋下的钩子会在定时内会通过前端用户触发发送平台服务器请求,去唤醒论坛服务,后激活心跳轮询保持服务的正常运行。
3.安全性,a.通信的安全:考虑到信息资产的安全所有的交互都是带签名验证的。这种验证方式使用的是请求体加秘钥的hash算法。秘钥通过mob管理后台进行获取,配置在插件端;b.内容存储安全:平台使用mongdb副本集的方式进行内容的存储。