职贝云数AI新零售门户

标题: 企业微信组织架构同步优化的思绪与实操演练 [打印本页]

作者: rC9s7r2    时间: 2023-1-28 16:55
标题: 企业微信组织架构同步优化的思绪与实操演练
(, 下载次数: 5)
                作者|胡腾                        编辑|小智                        作为企业级的微信,在业务疾速发展的背景下,迭代优化的要求也越发急迫。企业微信初版的全量同步方案在疾速的业务增长面前曾经捉襟见肘,针对其遇到的成绩,怎样做好组织架构同步优化?这是又一篇来自微信团队的技术实战。                        写在后面       
企业微信在疾速发展过程中,陆续有大企业加入运用,企业微信初版采用全量同步方案,该方案在大企业下存在流量和功能两方面的成绩,每次同步耗费大量流量,且在 iPhone 5s 上拉取 10w+ 成员架构包解压时会提示 memory warning 而运用崩溃。

全量同步方案难以支撑业务的疾速发展,优化同步方案越来越有必要。本文针对全量同步方案遇到的成绩停止分析,提出组织架构增量同步方案,并对移动端完成增量同步方案的思绪和重难点停止了讲解。
                企业微信业务背景       
在企业微信中,组织架构是非常重要的模块,用户可以在首页的 tab 上选择"通讯录"查看到本公司的组织架构,并且可以经过"通讯录"找到本公司的一切成员,并与其发起会话或者视频语音通话。

组织架构是非常重要且敏感的信息,企业微信作为企业级产品,一直把用户隐私和安全放在重要地位。针对组织架构信息,企业管理员具有高粒度隐私保护操作权限,不只支持个人信息隐藏,也支持通讯录查看权限等操作。

(, 下载次数: 4)

在企业微信中,组织架构特征有:

1、多叉树结构。叶子节点代表成员,非叶子节点代表部门。部门最多只要一个父部门,但成员可属于多个部门。

(, 下载次数: 4)

2、架构隐藏操作。企业管理员可以在管理后台设置白名单和黑名单,白名单可以查看残缺的组织架构,其他成员在组织架构里看不到他们。黑名单的成员只能看到本人所在小组和其一切的父部门,其他人可以看到黑名单的成员。

3、组织架构操作。企业管理员可以在 web 端和 app 端添加 / 删除部门,添加 / 删除 / 移动 / 编辑成员等操作,并且操作结果会及时同步给本公司一切成员。
                全量同步方案的成绩       
本节大致讲解下全量同步方案完成以及遇到的成绩。
                全量同步方案原理       
企业微信在 1.0 时代,从波动性以及疾速迭代的角度思索,延用了企业邮通讯录同步方案,采取了全量架构同步方案。

核心思想为服务端下发全量节点,客户端对比本地数据找出变更节点。此处节点可以是用户,也可以是部门,将组织架构视为二叉树结构体,其下的用户与部门均为节点,若同一个用户存在多个部门下,被视为多个节点。

全量同步方案分为初次同步与非初次同步:
                用户反馈       
初版上线后,收到了大量的组织架构相关的 bug 赞扬,次要集中在:

这些成绩在大企业下更分明。

(, 下载次数: 4)

                成绩分析       
深究全量同步方案难以支撑大企业同步的背后缘由,皆是由于采取了服务端全量下发 hash 值方案的缘由,方案存在以下成绩:

优化组织架构同步方案越来越有必要。
                寻觅优化思绪       
寻求同步方案优化点,我们要找准原来方案的痛点以及不合理的地方,经过方案的调整来避免这个成绩。
                组织架构同步难点       
准确且耗费最少资源同步组织架构是一件很困难的事情,难点次要在:
                技术选型-提出增量更新方案       
上述提到的成绩,在大型企业下会变得更分明。在几轮方案讨论后,我们给原来的方案添加了两个特性来完成增量更新:

在新方案中,服务端针对某个节点的存储结构可简化为:

(, 下载次数: 4)

vid 是指节点用户的独一标识 id,departmentid 是指节点的部门 id,is_delete 表示该节点能否已被删除。

其中,seq 是自增的值,可以了解成版本号。每次组织架构的节点有更新,服务端添加相应节点的 seq 值。客户端经过一个旧的 seq 向服务器央求,服务端前往这个 seq 和 最新的 seq 之间一切的变更给客户端,完成增量更新。

图示为:

(, 下载次数: 3)

经过提出增量同步方案,我们从技术选型层面处理了成绩,但是在实践操作中会遇到许多成绩,下文中我们将针对方案原理以及实践操作中遇到的成绩停止讲解。
                增量同步方案       
本节次要讲解客户端中增量同步架构方案的原理与完成,以及基础概念讲解。
                增量同步方案原理       
企业微信中,增量同步方案核心思想为:

服务端下发增量节点,且支持传阈值来分片拉取增量节点,若服务端计算不出客户端的差量,下发全量节点由客户端来对比差异。

增量同步方案可笼统为四步完成:

忽略掉各种边界条件和异常状况,增量同步方案的流程图可以笼统为:

(, 下载次数: 4)

接上去我们再看看增量同步方案中的关键概念以及残缺流程是怎样的。
                版本号       
同步的版本号是由多个版本号拼接成的字符串,版本号的详细含义对客户端透明,但是对服务端非常重要。

版本号的组成部分为:

(, 下载次数: 4)

                版本号回退       
增量同步在实践操作过程中会遇到一些成绩:

理想状况下,若服务端下发全量节点,客户端铲掉旧数据,并且去拉全量节点的信息,并且用新数据覆盖即可。但是移动端这样做会耗费大量的用户流量,这样的做法是不可接受的。所以若服务端下发全量节点,客户端需求本地对比出增删改节点,再去拉变更节点的详细信息。

增量同步状况下,若服务端下发全量节点,我们在本文中称这种状况为版本号回退,效果相似于客户端用空版本号去同步架构。从统计结果来看,线上版本的同步中有 4% 的状况会出现版本号回退。
                阈值分片拉取       
若客户端的传的 seq 过旧,增量数据能够很大。此时若一次性前往全部的更新数据,客户端央求的数据量会很大,工夫会很长,成功率很低。针对这种场景,客户端和服务端需求商定阈值,若央求的更新数据总数超过这个阈值,服务端每次最多前往不超过该阈值的数据。若客户端发现服务端前往的数据数量等于阈值,则再次到服务端央求数据,直到服务端下发的数据数量小于阈值。
                节点结构体优化       
在全量同步方案中,节点经过 hash 独一标示。服务端下发的全量 hash 列表,客户端对比本地存储的全量 hash 列表,若有新的 hash 值则央求节点详细信息,若有删除的 hash 值则客户端删除掉该节点信息。

在全量同步方案中,客户端并不能了解 hash 值的详细含义,并且能够遇到 hash 碰撞这种极端状况导致客户端无法正确处理下发的 hash 列表。

而增量同步方案中,运用 protobuf 结构体代替 hash 值,增量更新中节点的 proto 定义为:

(, 下载次数: 4)

在增量同步方案中,用 vid 和 partyid 来独一标识节点,完全废弃了 hash 值。这样在增量同步的时分,客户端完全了解了节点的详细含义,而且也从方案上避免了曾经在全量同步方案遇到的 hash 值反复的异常状况。

并且在节点结构体里带上了 seq 。节点上的 seq 来表示该节点的版本,每次节点的详细信息有更新,服务端会提高节点的 seq,客户端发现服务端下发的节点 seq 比客户端本地的 seq 大,则需求去央求节点的详细信息,避免有效的节点信息央求。
                判别残缺架构同步完成       
由于 svr 接口支持传阈值批量拉取变更节点,一次网络操作并不意味着架构同步曾经完成。那么怎样判别架构同步完成了呢?这里客户端和服务端商定的方案是:

若服务端下发的(新增节点+删除节点)小于客户端传的阈值,则以为架构同步结束。

当残缺架构同步完成后,客户端需求肃清掉缓存,并停止一些额外的业务工作,譬如计算部门人数,计算成员搜索热度等。
                增量同步方案 - 残缺流程图       
思索到各种边界条件和异常状况,增量同步方案的残缺流程图为:

(, 下载次数: 4)

                增量同步方案难点       
在加入增量和分片特性后,针对几十万人的超大企业,在版本号回退的场景,怎样保证架构同步的残缺性和方案选择成为了难点。

前文提到,隐藏规则变更以及后台物理删除有效节点后,客户端若用很旧的版本同步,服务端算不出增量节点,此时服务端会下发全量节点,客户端需求本地对比一切数据找出变更节点,该场景可以了解为版本号回退。在这种场景下,对于几十万节点的超大型企业,若服务端下发的增量节点过多,客户端央求的工夫会很长,成功率会很低,因此需求分片拉取增量节点。而且拉取上去的全量节点,客户端处理不能央求全量节点的详细信息覆盖旧数据,这样的话每次版本号回退的场景流量耗费过大。

因此,针对几十万节点的超大型企业的增量同步,客户端难点在于:
                思绪       
若服务端下发了全量节点,客户端的处理时序图为:

(, 下载次数: 3)

                服务端下发版本号回退标记       
从时序图中可以看出,服务端下发的版本号回退标记是很重要的信号。

而版本号回退这个标记,仅仅在同步的初次会随着新的版本号而下发。在残缺架构同步时期,客户端需求将该标记缓存,并且跟着版本号一同存在数据库中。在残缺架构同步结束后,需求根据能否版本号回退来决议删除掉数据库中的待删除节点。
                备份架构树方案       
架构树备份最直接的方案是将 db 中数据 copy 一份,并存在新表里。假如在数据量很小的状况下,这样做是完全没有成绩的,但是架构树的节点往往很多,采取这样简单粗暴的方案在移动端是完全不可取的,在几十万人的企业里,这样做会形成极大的功能成绩。

经过思索后,企业微信采取的方案是:

而且,在增量同步过程中,不应该影响正常的架构树展现。所以在架构同步过程中,若有下层来央求 db 中的数据,则需求过滤掉有待删除标记的节点。
                缓存架构树       
方案决议客户端避免不了全量节点对比,将重要的信息缓存到内存中会大大加快处理速度。内存中的架构树节点体定义为:

此处我们用 std::map 来缓存架构树,用 std::pair 作为 key。我们在比较节点的时分,会触及到很多查询操作,运用 map 查询的工夫复杂度仅为 O(logn)。
                增量同步方案关键点       
本节单独将优化同步方案中关键点拿出来写,这些关键点不只仅适用于本文架构同步,也适用于大多数同步逻辑。
                保证数据处理完成后,再储存版本号       
在几乎一切的同步中,版本号都是重中之重,一旦版本号乱掉,后果非常严重。

在架构同步中,最最重要的一点是:

保证数据处理完成后,再储存版本号。

在组织架构同步的场景下,为什么不能先存版本号,再存数据呢?

这触及到组织架构同步数据的一个重要特征:架构节点数据是可反复拉取并覆盖的。

思索下实践操作中遇到的真实场景:

若一旦先存版本号再存详细数据,一定会有概率丢失架构更新数据。
                同步的原子性       
正常状况下,一次同步的逻辑可以简化为:

(, 下载次数: 4)

在企业微信的组织架构同步中存在异步操作,若停止同步的过程不保证原子性,极大能够出现下图所示的状况:

(, 下载次数: 4)

该图中,同步的途中插入了另外一次同步,很容易形成成绩:

怎样保证同步的原子性呢?

我们可以在末尾同步的时分记一个 flag 表示正在同步,在结束同步时,肃清掉该 flag。若另外一次同步到来时,发现正在同步,则可以直接舍弃掉本次同步,或者等本次同步成功后再停止一次同步。

此外也可将同步串行化,保证同步的时序,多次同步的时序应该是 FIFO 的。
                缓存数据分歧性       
移动端同步过程中的缓存多分为两种:

内存缓存多缓存同步时的数据以及同步的中间形态,磁盘缓存用于缓存同步的中间形态防止缓存形态丢失。

在整个同步过程中,我们都必须保证缓存中的数据和数据库的数据的更改需求逐一对应。在增量同步的状况中,我们每次需求更新 / 删除数据库中的节点,都需求更新相应的缓存信息,来保证数据的分歧性。
                优化数据对比                        内存运用       
测试方法:运用工具 Instrument,用同一账号监控全量同步和增量同步分别在初次加载架构时的 App 内存峰值。
                内存峰值测试结果       
(, 下载次数: 4)

                分析       
随着架构的节点增多,全量同步方案的内存峰值会不断攀升,在极限状况下,会出现内存不足运用程序 crash 的状况(实践测试中,30w 节点下,iPhone 6 全量同步方案必 crash)。而增量同步方案中,总节点的多少并不会影响内存峰值,仅仅会添加同步分片的次数。

优化后,在腾讯域下,增量同步方案的 App 总内存运用仅为全量同步方案的 53.1%,且企业越大优化效果越分明。并且不论架构的总节点数有多少,增量同步方案都能将残缺架构同步上去,达到了预期的效果。
                流量运用       
测试方法:在管理端对成员做添加操作五次,经过日志分析客户端耗费流量,取其平均值。日志会打印出央求的 header 和 body 大小并估算出流量运用值。
                测试结果       
(, 下载次数: 3)

                分析       
添加成员操作,针对增量同步方案仅仅会新拉单个成员的信息,所以无论架构里有多少人,流量耗费都是相近的。异样的操作针对全量同步方案,每次央求变更,服务端都会下发全量 hash 列表,企业越大耗费的流量越多。可以看到,当企业的节点数达到 20w 级别时,全量同步方案的流量耗费是增量同步方案的近 500 倍。

优化后,在腾讯域下,每次增量同步流量耗费仅为全量同步方案的 0.4%,且企业越大优化效果越分明。
                写在最后       
增量同步方案从方案上避免了架构同步不及时以及流量耗费过大的成绩。经过用户反馈和数据分析,增量架构同步上线后运转波动,达到了理想的优化效果。
作者引见

胡腾,腾讯工程师,参与企业微信从无到有的整个过程,目前次要担任企业微信移动端组织架构和外部联络人等模块的开发工作。
昔日荐文

点击下方图片即可阅读

(, 下载次数: 4)

                                        技术漫谈:为何 KPI 毁了索尼,而 OKR 却成就了谷歌?                               








欢迎光临 职贝云数AI新零售门户 (https://www.taojin168.com/cloud/) Powered by Discuz! X3.5