[关闭]
@yanglfyangl 2018-07-24T02:39:40.000000Z 字数 2503 阅读 414

社交技术介绍 -- To Newer

大型软件项目不容易处理的地方

  1. 高并发。
  2. 高可靠。
  3. 高安全。
  4. 数据高一致性。
  5. 数据量级大。
  6. 统计维度复杂。

举几个社交需求中比较复杂的地方

  1. 最初要求12月份达到百W日活的量级(单Rest接口500ms返回可能都不够好)。
  2. 搜索(基于各种复杂关系的)。
  3. 红黄绿好友关系的计算(同时要求性能高)。
  4. 圈,群,用户类似微信,有隐私,有群或圈中特有要求,。。。
  5. 后管的要求复杂,各种维度或范围的查询。
  6. 量级相对同档次产品大(30000或无上限)。
  7. 。。。

我们使用的技术栈

  • 服务:Spring + Dubbo 系列
  • 缓存:Redis + JetCache
  • 存储:Mysql + Mongo + Pika
  • 配置:xxl-config, xxl-job
  • 搜索:ES,图引擎
  • 大数据:PedictionIO + MRS + MLS(研讨中)
  • 其它:APM, AOM, ELK等,都是公共的。

我们为了性能和可扩展性的一些“硬”性要求

  • 非特殊原因,不能轻易使用sql中的join, union等聚合操作,主键读取(批量)为主,确保分库分表是可行的。
  • 可能影响前端速度的操作中,不要有“大”的计算代码(包括sql),所有计算放到“计算中心”异步执行。读取时只读取存在缓存或库中的结果。
  • 各服务不能有状态。

我们的框架分层

我叫他MVCEC(Model-View-Control-Engine-Calc)
MVC就不介绍了,就是传统意义上的MVC,后面的Engine和Calc单独介绍一下

Engine:为了达到公司要求的一系列复杂的需求,我们准备了五个小引擎,对于关系计算和存储,简化规则处理,日志简化处理,第三方调用的简化处理。。。分别做了一定的设计。

  • RelationEngine (关系引擎)
  • RulesEngine (规则引擎)
  • StatisticsEngine (统计引擎)
  • HistoryEngine (历史记录引擎,未完成)
  • 3rdAccessEngine (第三方调用引擎,未完成)

Calc: 社交组人叫它计算中心,它的主要功能是:

  • 每一个“时间窗口”内读取配置量的消息。
  • 对读出来的消息分配n个线程进行处理。
  • 处理失败后重新扔回队列,进行重试。

拿关系引擎举个例子

加入关系:

  1. String memberId = "100";
  2. String friendId = "60";
  3. int result = relationEngine.joinRelation(NodeTypeEnum.MEMBER, memberId, friendId, RelationEnum.TO_BE_FRIENDS, DirectionEnum.BOTH);
  4. if (result == -1) {
  5. // TODO
  6. }

获取关系列表:

  1. String memberId = "100";
  2. String startNodeId = "10";
  3. int count = 10;
  4. RelationKey relationKey = new RelationKey(NodeTypeEnum.MEMBER, memberId, RelationEnum.TO_BE_FRIENDS);
  5. PageData data = relationEngine.getRelationList(relationKey, startNodeId, count);
  6. System.out.println("用户 " + memberId + " 的好友列表: " + data);

类似的操作,我们是会做到十万级别关系量左右,TP99都是几十毫秒以内的。

建议的调用流程

Created with Raphaël 2.1.2用户用户ControllerControllerServiceA(s)ServiceA(s)DBDB引擎引擎CacheCacheQueueQueueBackendServiceA(s)BackendServiceA(s)ESES图引擎图引擎JobServiceA(s)JobServiceA(s)写数据写数据写库完成完成调用引擎写缓存入队列读队列逻辑处理调用引擎写库写ES写图引擎写缓存定时处理相关逻辑调用服务调用引擎结果写缓存结果写DB读数据读数据读缓存如果缓存中存在返回否则,读库或调用引擎或调用ES或调用图引擎能缓存,则写缓存返回

注:

  • 其中BackendService可能是calc(计算中心,也可能是规则引擎)。
  • “引擎”目前指新的engine和老的引擎。
  • 这不是一个“万能”流程,不同情况下需要不同的裁剪或扩充。

社交还遗留的一些历史问题

“老引擎”与社交融合还有些麻烦。

背景:

  1. 1. 我们之前的公司分三个大组,“社交”,“电商”和”引擎“。
  2. 2. 社交和电商都基于引擎。
  3. 3. 按公司的要求,三个组之间互相信息是保密的

导致现状:

  1. 1. 调用链有点长,至少社交增加了一层BasexxxService层,用于调用引擎服务。
  2. 2. 引擎因为既有电商又有社交,所以逻辑复杂,相应的性能就不一定能够保证了。
  3. 3. 后台管理的需求复杂,到目前为止还有一部分没有实现。
  4. 4. 拿到引擎的代码后发现循环依赖现像存在,服务治理不容易做。
  5. 5. 数据库没办法做分库分表,而且还存在数据可能不一致的情况,所以数据层横向扩展能力不强。
  6. 6. 社交的圈群用户上限提到3W级别,甚至更高的情况下,优化有些困难。

近期我们会下面的工作来缓解这些问题:

  1. 写部分改动
  2. 1. 写部分按写引擎同时写入关系引擎。
  3. 2. 引擎后台写的部分,也需要写入关系引擎(不必用异步,直接写入即可,我们已经有了代码)
  4. 3. 去掉各种上限(圈群用户上限为3000。。。)
  5. 读部分改动
  6. 1. Base Service中需要的API的读部分全部走我们自己的关系引擎。
  7. 2. 按照连接219服务器,300并发300毫秒以下来压数据(列表型数据内容中最小是5000
  8. 3. 如果达不到上面的需求,给出性能瓶颈点来。
  9. 4. 所有的列表类rest接口,全部需要支持按timestamp来获取更新的能力。(这部分贺军会在关系引擎中加这个能力)

“出错补偿”还没有做

我们期望的“出错补偿”需要支持如下功能
1. 无侵入式的幂等性重试功能支持(需要开发一个新的filter,方案已定义完)。
2. 每天进行数据校验(可以由大数据在晚上进行)
3. 定期扫描日志中“Error”级别的部分,按每个业务不同的情况进行离线补偿。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注