商品服务难点

  2015年上半年离开京东之前在《京东架构师》杂志上写的一篇文章,今天分享给大家

一.问题

1. 京东商品服务特点:

    - 数据量大,目前已达到4亿8000多万,并且增长速度非常快,预计2020年可达到10亿(预估失误,去年貌似就30多亿了)

    - 服务访问量大、并发高,读服务在历史上最高达每天36亿次,最高并发6万次,预计2020年访问可达100亿次 

    - 数据更新量大,每天sku上柜操作每天可达1000万次,峰值达到2000万 

    - 数据实时性和数据一致性要求高,如果商品的属性、价格、上下架等信息处理延迟过大或出现误差,会造成业务损失

2. 京东商品服务的问题:

    - 数据集中式访问,所有应用通过直接连接商品数据库存取数据 

    - 单数据库实例无法满足性能需求

    - 多级复制在某个阶段起到了作用,但经常出现复制延迟 

    - 迁移到性能比较好的Oracle上时,只是缓解了压力,随业务快速发展,其连接数限制很快成为新的瓶颈。

二.解决

    针对于以上业务特点,进行了如下的解决:

1. 中心化,服务化

    建设主数据、任务系统、读服务三大中心:

    应用中心化后,底层数据库系统按照不同的业务数据进行了一系列的拆分。此类拆分方式具有以下特点:

    - 拆分方式简单,只需要把不同的业务数据进行分离

    - 避免了不同业务数据读写操作时的相互影响

2. 异构的读写分离

    - 写库为sqlserver环境,提供数据安全性保障 

    - 读库使用mysql,采用数据分片,分库分表,每台mysql放少量的数据,单个数据分片内部采用mysql复制机制 

    - sqlserver到多台mysql按规则复制

3. 大数据量核心业务数据迁移

为什么不直接迁移到mysql上面去呢? 

    - 对于核心业务,停机时间有限,庞大的数据无法短时间内迁移

    - 无法在短时间内完成项目发布过程中的测试

    - 当时项目团队缺少MySQL分布式系统经验,需要采用更稳妥的方案

采用两步走战略,不仅走的稳,而且走的好:

    - 先采用异构的数据库读写分离,将数据复制到mysql各节点,不断切换应用相关的读服务到mysql节点上,验证可靠性,机器压力,服务响应时间

    - 将写压力从sqlserver节点迁移到mysql各节点,sqlserver停写 

 对于一些不太核心,业务不太复杂,相关影响点不多的数据,可以直接进行迁移。

4、高效的异步任务处理系统

    某些功能的实现对实时性要求并不是那么高,但是逻辑比较复杂、执行比较耗时。比如涉及外部系统的调用,我们将这些复杂的业务逻辑放在后台执行,而前台用户的交互可以不用等待,从而提高用户体验。所以我们通过高效的异步任务系统来处理,随着任务量的增长,任务系统架构也随之升级,现在的架构如下:

注:mongodb为任务队列的灾备存储。

5、高速的读服务

    在商品交易过程中,频繁的商品数据访问给商品数据库造成了极大的压力,严重时会造成系统崩溃。商品的读服务基于Redis存储,缓解了商品数据库的数据访问压力

    当前sku4亿8000多万,实际使用内存512G,每组8台主机,每个主机8个实例, 每实例14G,每组内存容量896G,共9组 Redis集群,1主(黄村)、4从(黄村)、2从(B28)、2从(亦庄)。

随着数据量的增长,从以下几方面考虑: 

- 存储: 

    未来规划存储50亿sku,大约扩展到10倍,总计5120G/组。进行数据压缩(压缩比70%),预计内存3584G左右。内存使用率安全边际75%预估,总共需要 6T/组。扩大分片个数,128个分片, 每个分片14G,每个主机8个分片,每组需要45台主机。

- 压缩

    基本信息及特殊属性进行了key转换:写入时字段名转为数字,读取时方向解析(name:0), 该转换可降低网络IO、降低内存使用率;采用hash存储,配置zipmap参数,紧凑存储节约内存空间。

可考虑方案:MessagePack序列化为字节数组,存储于redis中,读取时解析。因数据结构不再是hash,无法再享受hash按字段访问的优势。读取时获取全部,应用解析后按字段返给调用方。此方案需进行测试,实际压缩率及性能变化。因硬件设施越来越便宜,并且京东业务发展对商品服务性能要求越来越高。如条件允许,增加硬件资源的方式更好,以避免解压缩带来的性能损失。

- 服务治理:

    客户端调用商品服务的调用量按照分钟维度进行存储,其中详细记录调用方的ip、调用量及调用的方法等信息。当服务流量过大情况下,可迅速定位客户端,并可通过zk配置对相应的ip

- 缓存数据恢复:

    目前缓存数据存储基于一致性哈希散列到各个分片,因分片数量调整,所有数据需重新刷新。全量刷新完成后,为避免丢失(已完成初始化的可能也会变更了),再初始化一次当天的增量刷新,完成缓存数据的初始化。

- HA:

    通过DBCONFIG动态切换数据源,动态调整主从关系,需项目负责人切换。风险点:UMP监控报警或业务方反馈后,定位问题,人工切换所需时间不定(可能受限于时间地点)。改进点:配置热备数据源,当前存储集群宕机情况下,自动通过备用数据源重试。

三.新的挑战

    在商品服务规划中,系统面临着大数据的考验,接下来我们将迎接新的挑战 

1.商品号段的升级 

    sku数据库中定义的是整型,已经不能满足数据量的增长,需要升级为long型 

2.海量商品数据存储 

    自主定制研发KV存储系统,平衡资源耗用和性能请求,保证大数据量冲击下的系统稳定性 

3.冷数据 

    商品比较明显的冷数据主要是被删除商品,可以转移出目前的主数据库并使用低配置硬件存储和提供服务。

4.二级路由 

    对于不断增长的SKU来说,采用二级路由的方式来避免调整原有的数据分片。

5.商品搜索服务

    按照sku维度分库分表之后,采用ElasticSearch分布式搜索引擎来搭建商品搜索服务 

6.商品类目属性SOA化

    目前主数据和POP各维护一套类目系统,并且还有一些系统直接读取数据库获取类目属性,每次分类属性的变更都需要主数据同步到POP,数据的一致性很难得到保证,要打造一套完整的类目属性服务满足所有业务的需要

我是分割线----------------------------------------------

介绍下自己: 公号IT令狐冲作者,江湖人称老白,前京东码农,前必要商城技术总监、技术委员会主席,现任北京北广视CTO,信奉终身学习,终身探索。后续会不断更新,用来分享技术管理、产品运营等方面的经验和互联网行业信息。如果对某些话题感兴趣的同学,欢迎大家关注。

发布了54 篇原创文章 · 获赞 16 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/aisoo/article/details/104569727