设计概述
同步协议的设计就是业务契约的设计,本质就是client和server双方就同步的信息范围达成一致。
同步
同一个事物,存在不同的演化路线。从事物最初状态开始,不同的演化路线导致同一时间点事物状态不一样。给所有不同演化路线上的事物状态同一时间点确定一个共同状态的过程,就叫同步。
IM同步
IM同步是给IM用户进行的信息同步,同步的事物就是“该IM用户需要知道的所有信息”。
IM同步有两个基本的特征:第一是事物共同状态的确定有且只有一个标准,那就是server中事物状态;第二是任何时间点其他client中事物状态都只能是server中事物状态的中间状态。
注:为了降低同步场景的复杂度,client没有改变本地状态的权限,client本地状态的变化一定是server来主导的。
意义
凡是c/s架构的系统,都可以看作是信息同步的过程。对于任何需要移动终端和服务器配合的业务,信息同步都是业务演进过程中必须要面对的问题。
目的
降低流量。
元信息
元信息,是整个同步协议的基石。没有元信息数据,就无法将需要同步的内容描述清楚。任何领域里面的任何信息都是由该领域里面的基本元信息构成的,信息本质就是根据元信息组织规则对元信息进行组织。
IM元信息
IM元信息是组织IM业务的最小信息单元,由于IM信息组织规则是线性的,IM信息就是IM元信息经过线性组合的结果。
- IM元信息(也叫IM一维信息)
单个属性
单个关系
单个消息
- IM二维信息是一维信息的线性扩展
群:关系的列表
XX属性:属性的列表
好友列表:关系的列表
黑名单列表:关系的列表
单聊会话列表:关系的列表
群聊会话:关系的列表
单聊会话消息列表:消息的列表
- IM三维信息是二维信息的线性扩展
群组列表:群的列表
群聊会话列表:群聊会话的列表
群聊会话消息列表:群聊会话的消息的列表
好友属性:好友列表中所有好友属性
同步协议
同步协议设计包括两方面:
- 给同一时间点同一事物的不同状态确定一个共同状态
- 把不同事物状态迁移到共同状态
注:IM同步协议中共同状态已经确定,所以只需要考虑如何把不同client的状态变成server的状态。
信道
添加IM命令字XX作为协议通道。
通信数据
① 上行
上行数据也叫同步驱动。同步驱动的意义在于把sdk需要同步的具体信息告诉server。不管是全量信息的同步还是部分信息的同步,都需要明确告诉server需要同步的具体信息。
Request
{
version;//信息当前的同步版本号
what_do_you_want_to_sync;//信息代号,也可以叫做业务代号(既然不能在请求里把信息描述清楚,那就需要双方明确就这个代号所指的信息和需要获取的结果做个约束,这称之为业务契约)
};
② 下行
同步结果。同步结果是元信息的集合,它明确告诉了sdk需要干什么,以及如何去干。根据元信息的性质,可以定下规则。凡是静态属性(不能被增删的),一律用值通知;凡是动态属性(可被增删的),一律用操作通知。
根据IM信息的构成规则,可以得到同步结果的抽象数据结构是多维列表,这样就可以明确告诉client更新的信息及更新的方法。
Response
{
version;//信息最终的同步版本号
what_do_you_want_to_sync;//信息代号
value;//信息静态属性的增量
operation;//信息动态属性的增量
};
制衡规律
client低信息量、server低计算复杂度和存储冗余度两者之间不能同时满足。
业务契约
概念
注:业务契约是同步协议设计的核心内容,定义好业务契约就定义了client和server双方的业务范围,也就确定的同步信息的范围。
what_do_you_want_to_sync
- 获取用户单个群的成员列表
包括[关系]、[用户 [属性] ]两种IM信息的同步。
对于[关系]:需要返回群成员列表的“变化增量”。
对于[用户 [属性] ]:需要返回属性信息有变化的群组成员信息,新增的用户也算。
在同步群组成员属性信息的时候,有可能该群的有些群组成员属性信息已经在其他群中被同步了,已经被同步过的成员是否还需要在该群的同步请求中继续同步?
不需要,那么完成该业务实际所用到的信息范围就和业务描述的信息范围不相符了。本来给的信息只够描述用户单个群的,但是实际要求完成的业务却是要基于用户整个信息空间的。
需要,那么同步仅仅只针对该群的成员属性信息,这样业务同步需要的信息范围就和业务描述的信息范围一致了。这样缺点很明显,那就是该同步范围可能和其他业务的同步范围有重叠,造成同步结果的冗余。
原则
请求描述的信息范围和需要同步的信息范围一致性(你不能说你要同步a,却把同步b时需要的信息告诉我)、业务和其他业务同步范围正交性(同步的元信息尽量做到完全增量)。
设计
- 当前设计
凡是改变了sdk本地数据状态的接口都属于业务契约,当前能够改变sdk本地数据状态的接口如下:
- 获取用户信息
- 获取用户信息
- 修改密码
- 用户信息更新
- 修改群组详情
- 获取群组详情
- 获取好友信息
- 修改好友备注
- 获取群组列表
- 创建群组
- 退出群组
- 添加群组成员
- 删除群组成员
- 获取群组成员
- 添加黑名单
- 删除黑名单
- 获取黑名单列表
- 添加好友
- 删除好友
- 获取好友列表
- 发消息-单聊
- 发消息-群聊
- 接收聊天消息
由于IM业务本身的特点,业务很难分离成完全正交的子业务,业务与业务之间总会存在着信息的交集,所以考虑将IM整个业务划分成正交的子业务的想法不可能实现。
但是同步的主要目的是为了降低流量,根据28法则,经常同步的信息只占信息总量的20%,所以能够将同步的信息粒度减小才是设计的重中之重。所以同步契约的对外接口只能保持不变,接口设计上不是正交的。
- 理论设计
对有信息交集的业务做聚类,聚类的结果为业务集,每个业务集之间就是正交的,针对每个业务集做同步就能够在业务契约设计上实现正交。
- 折中设计
每类元信息的集合当作一个信息同步的粒度,此方法能够实现完全正交。尽管由于同一个元信息可能参与了不同业务,并且這些业务之间存在着信息交集,表面上看起来该类元信息与其他类元信息存在着关联,其实元信息和元信息之间是不可能有交集的,有交集的只是业务,不然元信息就不叫元信息了。
最典型的场景:获取群组成员列表,导致属性的变化和关系的变化会由于业务关联到一起。
元信息是关系:
好友列表(同步好友关系的)
群列表(同步群关系的)->群成员列表(同步群关系的)
群列表(同步群关系的)->群聊会话列表(同步群聊会话的)
单聊会话列表(同步单聊会话的)
元信息是属性:
所有的用户信息(同步用户属性的)
所有的关系信息(同步关系属性的)
元信息是消息:
单聊会话的消息(同步单聊消息的)
群聊会话的消息(同步群聊消息的)
致命缺陷:该同步粒度能够实现同步请求之间同步信息没有交集,但是同步信息的粒度却是全局的,每次业务同步请求都需要同步许多不是该请求所要求的信息。
通信过程
事件触发同步
事件触发同步适合不需要将变化及时通知到client的情况。
事件通知同步
事件通知同步适合client需要将变化尽快同步的情况。