32

京东占领首页项目架构揭密

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUyMDAxMjQ3Ng%3D%3D&%3Bmid=2247491826&%3Bidx=1&%3Bsn=e47565d46c5e77924536dd2d0f9a69f0
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

60天从零开始到上线一个UGC项目,揭秘京东占领首页项目背后的故事。

项目背景

京东APP当前调性高冷,大部分用户都是抱着购物的目的来且买完即走,希望在京东内打造一款由普通用户发起内容至大流量频道,引起其他用户关注的产品,从而改变京东在用户心中工具型产品印象,提升品牌温度,拉近用户距离。

我们在2019年十月末接到产品需求,要求在十二月底之前开发完成上线,也就是说要在六十天内,完成从零开始开发到保证测试上线,压力不可谓不大。

架构介绍

整个占领首页项目被分为三部分:

  • 前台:

    负责和客户端进行数据格式化交换。

  • 数据中台:

    存储数据,提供RPC服务。

  • CMS后台:

    运营人员操作,提供诸如发帖信息管理、活动和任务信息管理等功能。

整体架构图如下:

b2yYFb6.jpg!web

依靠集团内部的基础组件和稳固的中间件,我们从零开始搭建了前、中台项目,以及CMS管理后台项目。前台部分又分为SOA和H5前台两个工程,SOA项目主要负责对接主站APP客户端,而H5项目则是负责对微信分享、用户传播方向赋能。

中台方面选择使用JSF为前台提供RPC服务,而CMS后台方面不需要关心中台业务逻辑、缓存规则,只需要将关键操作作为JMQ消息发送,中台进行消费,实现了逻辑上的解耦。数据存储方面选用了集团提供的JimDB和基于Mysql引擎的弹性数据库JED进行数据存储。

同时借助ForceBot平台进行了压力测试,使用UMP和JEX平台分析了项目中存在的优化点和问题点。对于系统中存在的配置点,借助DUCC实现了配置化,可以实现线上配置热修改。

技术实践

3.1 JimDB结构化数据

数据存储方面,将Mysql中表结构数据转化为了JimDB中的组合数据结构。

JimDB本身是基于Redis的K-V型数据库,同时JimDB也提供了和Redis一样的数据结构。

在占领首页项目中,本身存在两个热点数据:

  • 热门帖子列表,根据点赞数正序排所有发帖数据。

  • 最新帖子列表,根据发表时间倒序排序所有发帖数据。

根据需求,存储数据时采用了zset存储帖子唯一ID,利用zset自动排序的特性,可以做到插入数据实时变化、数据查询实时更新的特点。例如对于最新帖子列表中的数据,使用发帖时间作为zset中的score,帖子的ID则作为value,这样就实现了根据发帖时间自动排序帖子ID。

发帖实体数据则单独存储为String类型的数据结构,可以选择序列化为Json字符串或者序列化为二进制数据,根据项目中相关实践,综合考虑了性能和开发便捷性后,我们选用了将对象序列化为Json字符串,主要原因是其可读性较高,便于问题的排查。

优劣对比

序列化成二进制(protostuff)

序列化成JSON

序列化速度

相对慢

序列后大小

相对大

序列化后可读性

完全不可读

可读

Redis 中数据类型

String

String

发帖实体数据的Redis-Key,则根据帖子ID根据一定命名规范生成,例如:post:info:9527,帖子实体数据只需要保存一份,热门帖子和最新帖子列表共享帖子实体数据。示例图如下:

BjyYZnn.png!web

进行数据查询时,使用Redis提供的ZRANGEBYSCORE可以实现倒序分页查询、范围查询,然后通过pipeline批量查询帖子实体数据,替代了SQL语句进行查询。

在进行对比测试时,共插入帖子数据10万条,每页查询20条帖子数据,forcebot进行压力测试,Mysql和JimDB的性能对比如下:

类型

单机QPS

TP99

并发线程

Mysql

3000 左右

150ms 左右

100

JimDB

6000 左右

10ms 以内

100

Mysql

5000 左右

200ms 左右

200

JimDB

10000 左右

10ms 以内

200

使用JimDB相较于Mysql,最大的提升就是TP99的降低。主要原因有两方面:

  • Mysql对于分页查询的页码增大以后,查询效率的明显降低。虽然这里我们也对查询进行了优化,包括针对于SQL语句的EXPLAIN分析优化、回传偏移量等,但是由于SQL型数据库的原因在这种查询情况下性能不可避免的会下降,TP99会随着并发查询数量上升。

  • JimDB理论上只做了时间复杂度为O(log(N)+M)的查询,和20次时间复杂度为O(1)的查询,这里N是zset的总大小,M则是分页大小。使用Pipeline以后也只有两次网络传输开销。因此TP99保持了稳定而且非常低的效果,直到达到JimDB分片的性能上限。

在项目开发完成期,中台整体数据做到了缓存覆盖率99%,只有少数判断操作会穿透缓存。依靠JimDB的高性能,整个系统的QPS和TP99得到了保障。

3.2 JMQ解耦业务

在项目开发中期,我们遇到了CMS后台和中台数据不共享,导致了业务开发受阻的情况,经过评审分析后,决定引入JMQ实现CMS后台和中台的完全解耦,因为中台大量使用了JimDB作为缓存,而CMS后台则接触不到这些数据,引入JMQ以后,CMS后台只需要通过和中台进行约定的消息交换,从而做到不需要关心中台数据存储和业务逻辑,却可以对中台数据进行修改。

iM3MBvZ.png!web

这里需要注意,我们在使用MQ的时候出现了一个JED主库和从库不一致的问题,JED中的读写分离的实现方式的是主从分离,主库写入数据,从库查询数据,因此主从数据库的同步需要一定时间。在项目中,多次出现主库数据修改以后,从库数据没有在极短时间内同步修改的情况,由于JMQ消息传输和消费速度可能会比JED的同步速度快,因此建议某些必要操作的读写统一在JED主库(写库)进行,防止出现数据不一致的情况。

3.3 网络IO异步、并行化

我们对项目内存在的网络IO请求进行了梳理,将没有逻辑上先后关系的接口调用和数据库请求,抽取进行了并行化、异步化改造。

对比了现有的技术框架,最后决定选择了上手难度较低、可靠性较高的java.util.concurrent包中提供并发工具类,例如使用CompletableFuture类实现异步执行、编排任务,使用ExecutorCompletionService工具类实现并行化数据查询等。

例如帖子列表接口,每页每次会查询20条帖子数据,对于每条帖子数据,需要查询上游接口获取点赞信息和用户信息,点赞组件的调用又需要调用点状态和点赞用户列表两个接口,如果采用遍历列表后串行调用接口的方式,需要调用近百次上游接口,针对于这个接口,进行了如下改造:

  • 首先对于系统内涉及到的用户信息进行了缓存,将近百次的用户组件接口的RPC调用转变为了对于JimDB的批量查询。

  • 其次采用了多线程的方式,并行的调用点赞接口,极大的缩短了网络IO串行带来的累加的等待时间。

vuIR3uN.png!web

对于点赞状态接口,实际上和点赞用户信息是没有逻辑关系的接口,但该接口如果请求失败,就不需要拼接点赞用户信息,因此采用了异步任务的方式,成功后回调拼接数据。改造后的接口请求时间大大下降。

状态

单机QPS

TP99

CPU 使用率

改造前

800 左右

350ms 左右

75% 左右

改造后

1200 左右

40ms 以内

85% 左右

压测时单机的QPS并没有多大提升,是因为该接口背后的业务逻辑比较复杂,在八核16G的机器上进行测试,也已经达到了CPU瓶颈。同时需要注意的是,项目中线程池的配置需要经过严格的验证和测试,针对于不同配置的机器,和不同的业务场景需要进行不同的配置。

总结&展望

占领首页项目是京东在UGC产品上的一次深入尝试。从第一次的线上效果来看,收获了不错的成绩,有超过1.2万的用户发帖,霸屏首页的帖子有1500万的查看量,是京东UGC产品中比较成功的一款项目。作为研发人员,对于系统的改进也有更多的展望。

4.1 模块化、配置化

因为开发周期较短,占领首页项目无论是SOA还是中台,目前从代码层面上来看存在着扩展性不足、模块之间交叉较多的情况,我们还需要进一步的努力,做到使用配置化来实现扩展功能,使用开关能管控模块的能力。

AvQV7ra.png!web

4.2 能力组件化

在中台的开发过程中,我们发现有一些可以复用甚至对外赋能的组件,比如说任务组件,目前整个任务的流程都严格和各部分代码逻辑耦合,但是经过复盘分析后发现整个任务模块是可以组件化剥离出来的,后续甚至可以进一步做成通用任务组件对外赋能。

4.3 写在最后

后续我们团队会继续努力,在性能上进一步提升,在功能上进一步丰富,在架构设计上进一步优化改进,希望在现有的产品上继续深耕,同时也期望能给集团带来更多的贡献。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK