京东APP百亿级商品与车关系数据检索实践 | 京东云技术团队

news2025/1/18 7:41:11

导读

本文主要讲解了京东百亿级商品车型适配数据存储结构设计以及怎样实现适配接口的高性能查询。通过京东百亿级数据缓存架构设计实践案例,简单剖析了jimdb的位图(bitmap)函数和lua脚本应用在高性能场景。希望通过本文,读者可以对缓存的内部结构知识有一定了解,并且能够以最小的内存使用代价将位图(bitmap)灵活应用到各个高性能实际场景。

1.背景

整个汽车行业行特殊性,对于零配件有一个很强的对口特性,不同车使用的零配件(例如:轮胎、机油、三滤、雨刮、火花塞等)规格型号不一样。在售卖汽车零配件的时候,不能像3C家电、服饰,需要结合用户具体车辆信息,推荐适合的配件商品。基于此原因,京东自建人车档案模型并且利用算法清洗出百亿级的车型-零配件的适配关系数据,最终形成“人->车-〉货”关系链路,解决“人不识货”的问题。 具体使用场景如下图:

.

图1.1京东商详推荐商品 图1.2京东加购弹窗推荐商品

2.数据模型

人-> 车->货”关系的核心链路是由人(京东用户)、乘用车和SKU这三部分组成。

首先,用户在京东APP的商搜页、商详页多个位置都可以选择自己的车型信息进行绑定(例如:图2.1,京东商详绑车入口位置“+添加爱车”按钮),建立“人车档案”数据。

.

图2.1.京东商详绑车入口位置 图2.2.京东商搜绑车入口位置

其次,运营在后台管理系统中将商品与车型进行绑定,建立“商品与车型关系”数据(商品与车型的关系数据量级在百亿级别)。

最终,购买商品的时候,京东推荐系统可以通过用户自己绑定的车型推荐出适合该车型的商品。具体商品适配车型数据模型,见图2.3

图2.3京东商品适配车型数据模型

3.缓存结构设计

基于前面两个部分的介绍,我们可以了解到整个商品搜索适配推荐存在两个最核心问题。第一、百亿级商品适配车型数据的存储结构设计,尽可能的占用资源成本最小;第二、商详通过用户车型来搜索适配商品时,必须保证接口性能的TP99位于毫秒级。最终技术选型的时候,采用了jimdb的位图(bitmap)函数来进行数据存储。

3.1位图(bitmap)结构

位图(bitmap)是通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态。一个bit的值是0或者1;也就是说一个bit能存储的最多信息是2。

• 位(bit):计算机内部数据存储的最小单位,例如:11001100是一个八位二进制数。

• 字节(byte):计算机中数据处理的基本单位,习惯上用大写B来表示,1B(byte,字节)=8bit。

图3.1位图(bitmap)内部结构

3.2位图(bitmap)数据写流程

位图(bitmap)是基于jimdb的SDS(简单动态字符串)类型的一系列位操作,遵循jimdb的SDS特性,例如:位图(bitmap)最大长度512M,最大可以存储232位。以下是“big”字符串的SDS结构示例:

图3.2.1“big”字符串的SDS结构

SDS(简单动态字符串)为了保证性能采用了空间预分配的策略:空间预分配用于优化SDS的字符串增长操作。SDS的API对一个SDS进行修改并且需要对SDS进行空间扩展的时候,程序不仅会为SDS分配修改所必须要的空间,还会为SDS分配额外的未使用空。具体预分配流程图如下:

图3.2.2SDS预分配流程图

**位置1:**创建SDS简单字符串预分配空间为:偏移量/8+1。

**位置2:**剩余空间不足时,预分配空间流程。

3.3压缩商品与车关系缓存

偏移量(自增ID)全量车型商品SKU
11165788101362
21165793101362

商品适配车型关系(百亿级数据量)

商品与车关系缓存存储过程中,采用了商品SKU作为KEY,全量车型ID的偏移量(采用偏移量是为降低内存消耗)作为VALUE值来进行存储。

全量车型ID大约有几十万的数据量,极限情况下一个商品SKU可以适配几十万辆车,很容易造成缓存大KEY的问题,为此我们进行了偏移量(全量车型ID对应的自增ID)的分段处理。具体是按照:SKU作为缓存KEY的基础上,追加一个分段标记数字作为新KEY,每个偏移量都会按照分段范围对应一个分段标记数字。例如:偏移量1~50000,对应缓存KEY为SKU+0;偏移量50001~100000,对应缓存KEY为SKU+1,其它偏移量以此类推,这样就保证了一个SKU即使适配所有车辆也不会出现缓存大KEY的情况。

BitMap缓存结构底层使用SDS简单字符串,为了保证性能采用了预分配空间的策略(图3.2.2,“缓存BitMap内部存储流程图”的“位置2”中虚线框圈选),这样在缓存商品与车关系的时候浪费了大量的缓存空间。为此我们调整了偏移量存储顺序,首先获取到需要缓存的车型内最大的偏移量,保证同一个缓存KEY第1次创建SDS简单字符串(图3.2.2,“缓存BitMap内部存储流程图”的“位置1”中虚线框圈选)后,不再进行第2次空间扩容,这样来最大限度的提升缓存利用率,起到压缩空间目的。缓存数据关系流程如下:

图3.3.1缓存数据关系流程

位置3:设置分段最大的偏移量,保证后续新增偏移量不再扩容空间。

位置4:设置分段较小的偏移量。

全量车型ID是定长7位的数字,如果用它作为偏移量将消耗内存巨大,所以采用对应自增ID作为偏移量。最终在bitmap缓存的商品SKU与车的适配关系缓存结构如下图:

3.3.2商品与车缓存结构图

位置5:spuId用{}括起来表示缓存路由(Lua脚本中同一次请求,数据必须在缓存同一个分片上,否则会丢失数据)。POP商品spuId是SKU的产品ID,自营商品spuId是SKU的MainSkuId。

备注:

1、自营商品MainSkuId可能发生变化,所以我们接入了商品变化MQ消息,实时调整SKU与车适配关系的存储位置。

2、京东商详页面中每个不同的规格/型号分别对应不同的SKU,但是它们都对应同一个SpuId或者MainSkuId。

4.缓存架构设计

商品与车的关系数据量每天都在不断增长,要求缓存架构设计,需要支持集群横向/纵向扩容和来满足业务发展以及高可用性。整个缓存架构体系主要有前端、京东养车商品与车关系层和存储三部分组成。

“商品与车关系缓存架构”层核心包括:1、“集群路由”层,实现了集群横向扩容,保证数据量增涨的时候,缓存容量也能跟上。2、“分片路由”层,保证搜索的底层数据的分片相同,避免数据丢失。

“存储”层核心包括:1、实现了缓存压缩,参见3.3压缩商品与车关系缓存。2、单元化实现跨区域灾备,保障大促系统稳定性。具体商品与车关系缓存架构如下:

4.1商品与车关系缓存架构图

位置6:集群路由,通过商品类型或者商品编号(POP商品)路由到不同缓存集群,便于横向扩展,每个集群单分片限制,解决分片超过限制问题。

位置7:分片路由,保障Lua脚本搜索数据的底层数据集群分片相同,避免数据丢失。其中自营商品和POP商品的路由分别是main_sku_id和product_id。

位置8:自营商品缓存集群,单元化实现跨区域灾备,采用自研DRC(Data Replication Center)数据同步机制。

位置9:POP商品缓存集群,通过商家编号拆分为两个子集群。

5.高性能搜索

基于BitMap(位图)缓存的商品与车关系数据,商详调用接口的内部实现采用了Lua脚本来降低网络开销,保障整个接口的性能。以下是搜索接口的流程图:

5.1商详搜索商品与车适配关系流程图

位置10:商详调用接口的时候,要传两个参数。第1个参数是全量车型ID列表,大约5个全量车型ID。第2个参数是商品SKU列表,SKU的数量极限超过200个。最后全量车型ID与商品SKU组合为上千个商品与车的关系后,再到百亿级适配关系去搜索看是否匹配的。如果不匹配返回适配商品,反之则返回不适配。

Lua脚本减少了应用服务器与缓存服务器的交互,降低了网络开销的时间,达到提升搜索服务的性能。以下是Lua脚本具体代码:

5.2商详搜索商品与车适配关系Lua代码

基于以上缓存设计和Lua脚本的使用,整个接口T999小于13ms。具体的接口性能监控如下图:

5.3商详搜索商品与车适配关系接口性能

6.总结

整个缓存结构设计的时候,使用BitMap(位图)来存储数据。解析SDS的内部存储流程,通过存储流程机制避开预分配空间节点,最大限度的利用缓存空间,避免资源浪费。采用Lua脚本来实现数据的适配搜索,降低网络开销,进一步提升接口的性能。希望此文对大家后续设计类似场景有一定的帮助和启发。

作者:京东零售 张强

内容来源:京东云开发者社区

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/500909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文带你写好:项目说明文档README.md

1、前言 公开项目中,一个好的 README 能帮助我们的公开项目,在 GitHub 上的众多项目和开发人员中脱颖而出;商业项目中,一个好的 README 能帮助部门同事更好理解用途和项目进展。下面我们一起讨论什么是 README 自述文件以及如何编…

如何使用node发布自己的包

一、新建文件夹 gzmTestNode二、npm init {"name": "gzmTestNode","version": "1.0.0","description": "处理不同日期函数组件","main": "index.js","scripts": {"test&quo…

从爆火的“哇呀挖”,思考我软件开发的人生意义何在?

【 在什么样的花园里面,挖呀挖呀挖,种什么样的种子,开什么样的花,在小小的花园里面,挖呀挖呀挖,种小小的种子,开小小的花,在大大的花园里面,挖呀挖呀挖,种大大…

springboot+vue火车订票管理系统(源码+文档)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的火车订票管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 💕💕作者:风…

String [中]

目录 一、 string 的深浅拷贝 0x00 构造函数与析构函数的实现 0x01 拷贝构造 0x02 赋值 0x03 整体代码 二、 string的实现 0x01 引入 0x02 c_str 0x03 默认构造函数 三、size()与operator[]的实现 0x01 size()的实现 0x02 operator[]的实现 0x03 遍历实现 四、迭代器…

同步任务、异步任务、宏任务、微任务、任务的执行过程实例详解、setTimeout()是同步还是异步

一、前言 JavaScript是单线程语言,也就是说,只有一条通道,且js中任务是按顺序依次执行的,但若有一个任务时间过长,就会让后续任务一直等待。为了解决这个问题,将任务分为同步任务和异步任务,异…

文案把卖点被埋没?如此挖掘电商产品卖点,让你轻松获客

绝大部分电商卖家开店面临的最大问题就是不知道如何写文案,直接复制品牌的文案容易被告Q权,自己写的又不吸引人,复制竞争对手的更是无法脱颖而出。同时你也不知道这个文案到底好不好,在别人那里可行的文案,可能你就完全…

CTF-PHP反序列化漏洞3-构造POP链

作者:Eason_LYC 悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。 一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有! 技术领域:WEB安全、网络攻防 关注WEB安全、网络攻防。我的…

宽表 VS 多表关联,谁才是大数据分析的最佳选择?

各位数据的朋友,大家好,我是老周道数据,和你一起,用常人思维数据分析,通过数据讲故事。 前段时间和一个客户就数据中台搭建的一些问题进行了交流,其中讨论最多的是到底是用宽表来实现业务需求,…

Lecture 13(Preparation):Network Compression

目录 Network Pruning Knowledge Distillation Parameter Quantization Architecture Design Dynamic Computation 下面介绍五个network compression的技术。这五个技术都是以软体为导向的,在软体上面对network进行压缩,不考虑硬体加速部分。 Netwo…

springboot+vue校园宿舍管理系统

项目简介 分享一个SpringBootvue所做的一个项目,有需要的私信 1.项目描述 访问地址 http://localhost:8088/login.html?redirect_urlhttp://localhost:8087/myproject 超级管理员账户 账户名:admin 密码:123456 系统管理员账户 账户名…

【系统集成项目管理工程师】计算题专题一

一、决策树和期望货币值 1、项目经理向客户推荐了四种供应商选择方案。每个方案损益值已标在下面的决策树上。根据预期收益值,应选择设备供应商 A.供应商1B.供应商2C.供应商3D.供应商4 解题: 供应商 1:60% * 10000 (-30000&am…

DDR基础

欢迎关注我的博客网站nr-linux.com,图片清晰度和,排版会更好些,文章优先更新至博客站。 DDR全称Double Data Rate Synchronous Dynamic Random Access Memory,是当代处理器必不可少的存储器件之一。本文关于DDR介绍的核心点如下&…

Hadoop 3:YARN

YARN简介 Apache Hadoop YARN (Yet Another Resource Negotiator,另一种资源协调者)是一种新的Hadoop资源管理器。 YARN是一个【通用资源管理系统和调度平台】,可为上层应用提供统一的资源管理和调度。 它的引入为集群在利用率、…

数据结构学习记录——堆的小习题(对由同样的n个整数构成的二叉搜索树(查找树)和最小堆,下面哪个说法是不正确的)

目录 习题一 习题二 习题三 答案区 解析区 习题一 习题二 习题三 习题一 一、下列序列中哪个是最小堆? .2,55,52,72,28,98,71 .2,28,71,72&#x…

排序(数据结构系列13)

目录 前言: 排序算法的引言: 1.插入排序 1.1直接插入排序 1.2希尔排序 2.选择排序 2.1直接选择排序 2.2堆排序 3.交换排序 3.1冒泡排序 3.2快速排序 3.2.1Hoare版 3.2.2挖坑法 3.2.3前后指针法 4.归并排序 5.排序总结 结束语: 前言&…

docker容器日常操作命令

1.docker日常命令 文章目录 1.docker日常命令1.1.运行一个容器(run)1.1.1.创建contos 7.6容器 1.2.查询容器列表(ps)1.3.容器命名(--name)1.4.容器删除命令(rm)1.5.容器命令(inspect&#xff09…

【Vue2.0源码学习】变化侦测篇-Array的变化侦测

文章目录 1. 前言2. 在哪里收集依赖3. 使Array型数据可观测3.1 思路分析3.2 数组方法拦截器3.3 使用拦截器 4. 再谈依赖收集4.1 把依赖收集到哪里4.2 如何收集依赖4.3 如何通知依赖 5. 深度侦测6. 数组新增元素的侦测7. 不足之处8. 总结 1. 前言 上一篇文章中我们介绍了Object…

5 大分区管理器 - 最好的硬盘分区软件

分区是一个计算机术语,指的是在硬盘上创建多个区域,以允许操作系统和分区管理器软件有效且单独地管理每个区域中的信息。拥有大量计算机使用历史的人最有可能受益于多个分区。在硬盘中进行分区的好处之一是可以更轻松地将操作系统和程序文件与用户文件分…

node.js (fs文件系统模块,path路径模块,http模块web服务器)

node.js是js的后端运行环境 浏览器是js的前端运行环境 node.js是无法调用DOM和BOM和ajax等浏览器内置API node.js是一个基于ChromeV8引擎的JavaScript运行环境 目录 node.js可以做什么? node.js的学习路径 node安装 在node.js环境中执行javaScript代码 fs文…