榜单在经历了供给量迅速增长及C端分发场景多样化等迭代,数据量及峰值流量呈十倍百倍增长,这必然带来数据库的极大存储压力和C端查询性能降低。为满足未来各类复杂定制化规则和亿万级数据甄选,综合引导消费者的购物决策,得物商品榜单生产迁移及B/C端数据存储隔离应运而生。
得物榜单作为C端核心导购场景之一,通过建立丰富的规则矩阵,多维度提供用户购买参考建议,帮助用户快速决策并完成商详转化。目前涵盖六种类型包括热销榜、新品榜、趋势榜、种草榜、好评榜及回购榜,主要入口包括商详、品牌主页、分类tab、瀑布流、会场、频道等。
通过圈品条件圈选出一系列商品,再根据排序规则排名后取TOP20商品入选榜单。**圈品范围包括类目、品牌、系列、标签等,通过【6类模型、N项指标因子】综合计算排序后的总分代表商品的综合竞争力,分值越大,代表该商品表现越好。**得物榜单基于上述算法模型严格把控上榜商品品质,从而帮助用户根据自身诉求快速决策。
通过对榜单排序逻辑优化可针对性提升榜单承接效率,探索一套最佳排序规则公式需要通过不断的尝试,因此整个实验周期较长,在设计上就需要支持实验的快速推进。
来看下目前如何实现榜单的创建及生产。
涉及表
如何绑定圈品范围?
数据流转?
商品后台新增榜单基础信息至基础表,将圈品范围信息(类目、品牌、系列、标签、spuIds等)保存至圈品条件表,搜索每两小时定时从库中捞取圈品条件表数据,获取最新数据刷到商品集合表中。
商品/搜索存在双写榜单商品表场景,由于搜索通过dts数据同步方式回流数据,导致数据相互覆盖甚至主键冲突,通过id隔离的方式可以暂时解决。
目前榜单商品生产链路强依赖搜索,由搜索实现商品圈选及排序,搜索榜单商品生产方式单一,无法满足榜单圈选/排序规则定制化供给。而 「捞月」 作为得物核心选品投放平台,已经具备强大的圈品排序能力。
海量选品指标维度(商品基础信息,活动信息,价格与库存,流量与转化等)支撑各业务,分钟级别选品实时指标数据;
分钟级别执行引擎更新选品结果。
支持个性化、统计字段、自定义权重配比等多维度复杂升降序排序规则;也支持用户特征,进行推荐算法个性化排序。
具体细节不在本文展开,重点关注捞月指标体系、选品及排序能力在本次迁移中的应用。
针对第一个和第二个问题,我们提出榜单迁移捞月——通过复用捞月现有圈选/排序能力,完成榜单商品生产能力搭建,将榜单生产从搜索侧迁移至商品侧,移除榜单底层能力搭建对搜索的依赖。
未来榜单需支撑类目下沉场景,“类目下沉”即针对目前以类目为维度的榜单,再按品牌、系列、标签等维度进行榜单延伸。如:跑步鞋热卖榜下,再细分出耐克跑步鞋、入门跑步鞋、透气跑步鞋等榜单,更多维度扩充包括人群、风格等。按照笛卡尔积生成方式将任意维度与类目进行两两组合,将产生百万级甚至千万级别 海量数据 ,造成极大的存储压力。同时,榜单从生产到C端分发,经历榜单商品圈定、审批流及其他状态控制,最终能够在C端成功分发的榜单数量有限,每次查询都会触发有效数据的实时过滤。随着榜单数量的快速增长,必然带来C端查询性能降低,如大key、索引失效等,存在性能隐患。榜单在商详分发,必然伴随着 高并发读 。
针对这个问题,虽然可以尽量地从优化 sql、优化索引、缓存等等方面进行优化,但总会有到达极限的时候。关于海量数据的存储选型已经有非常广泛的案例,该如何进行存储选型?存储选型的目的还是为了我们的使用场景和用户服务,因此在选型前需要回答一些业务指标&技术指标方面的问题,以便于我们清楚存储选型的应用环境:
结合榜单业务特征以及海量数据和高并发的特点,可能的解决方案不限于
设计实践中,要基于需求、业务驱动架构,无论选用 DB/NoSQL, 一定是以需求为导向,最终数据存储方案必然是各种权衡的综合性设计:
综合考虑,B/C端数据存储隔离成为当下性价比最高的解决方案。
以下将阐述本次实践的详细实施点。
整体改造将分为两个阶段进行:首先完成链路改造,即榜单生产迁移捞月,待数据验证通过进行第二阶段的存储改造,即B/C端数据存储隔离。
捞月需支持榜单实验能力,因此在榜单对照组通用指标的基础上新增实验组通用指标,同时预留对应的实验组排序规则。可支持同类型榜单同时段进行一项实验,实验结束后根据实验结果修改通用算法模型。实验指标可在多次实验复用,不会造成捞月指标数量的递增。
{ "name": "best_seller_score", "type": "long" },
{ "name": "new_product_score", "type": "long" },
{ "name": "soare_score", "type": "long" },
{ "name": "favorite_score", "type": "long" },
{ "name": "rebuy_score", "type": "long" },
{ "name": "best_seller_score_test", "type": "long" },
{ "name": "new_product_score_test", "type": "long" },
{ "name": "soare_score_test", "type": "long" },
{ "name": "collect_score_test", "type": "long" }
{ "name": "favorite_score_test", "type": "long" },
{ "name": "rebuy_score_test", "type": "long" },
{ "name": "sort_best_seller", "type": "long" },
{ "name": "sort_new_product", "type": "long" },
{ "name": "sort_soare", "type": "long" },
{ "name": "sort_collect", "type": "long" },
{ "name": "sort_favorite", "type": "long" },
{ "name": "sort_rebuy", "type": "long" },
{ "name": "sort_best_seller_test", "type": "long" },
{ "name": "sort_new_product_test", "type": "long" },
{ "name": "sort_soare_test", "type": "long" },
{ "name": "sort_collect_test", "type": "long" },
{ "name": "sort_favorite_test", "type": "long" },
{ "name": "sort_rebuy_test", "type": "long" }
改造后全链路数据流转如图所示:
在链路改造环节我们已经完成了榜单和捞月集的绑定,因此查榜单下的商品就等同于查捞月集下的商品。
具体逻辑如下:
那么是否完全可以复用捞月存储结构,释放榜单商品集独立存储的空间?首先根据B/C查询场景划分为正向链路和反向链路。正向链路,也就是从榜单id获取到捞月集id,从捞月es根据捞月集id获取捞月商品结果集,B端查询方式均为正向链路,因此可以复用捞月存储结构。反向链路,即从捞月es根据商品id获取其所在的捞月集ids,从捞月集ids查询榜单ids。由于捞月集id暂无场景打标,只能遍历捞月集ids判断是否属于某一个榜单,查询成本极高,榜单在C端的核心分发场景商详便是满足了这个链路特征,当然我们可以通过建立捞月集场景打标体系、构建榜单商品ES大宽表的方式来解决问题,有没有性价比更高的解决方式?
###4.2.2 C端数据源-榜单集合mysql表
针对当前业务规模及C端查询复杂度,考虑采用B/C端查询隔离的方式进行实现。捞月选品结果变更、榜单显示/隐藏、审核通过/驳回、生效/失效都会影响榜单的分发状态。最终能在C端分发的榜单十分有限,为避免在C端做大量数据的实时过滤,降低索引失效和大key风险,原B/C端公用数据源榜单集合表仅存储可分发榜单商品数据供C端查询,实现方式及其简单:在状态变更及捞月结果集变更时触发实时更新/删除榜单集合表即可,整个改造过程无需改动C端代码,仅通过几行业务代码,就将DB存储数据量量级降至原来的40%,可支撑未来两至三年数据量的稳定增长。
相对于功能完整性,如何实现平滑稳定的切流是整个项目中比较重要的一环。
为了实现用户无感切换,降低切换过程中可能出现的故障对系统的影响,通过多个灰度读写开关保证切流过程的平滑和稳定性,整个过程可,做到“随切随停”。整体灰度分阶段逐步推进,采用:
即采用先进行增量数据维护,待增量数据check+fix通过后,进行全量数据刷数,待全量数据check+fix完成后,实施灰度读切流,并进行双读check,一旦出现问题则开关关闭;写切流采用先写临时表,临时表数据验证通过后切换写主表,一旦出现故障或脏数据,预案启动,可保证数据一小时内回滚。具体来说,我们关注以下四点:
首先进行风险评估,涉及榜单需绑定捞月集数量为N,以每个捞月集限制M个SPU为准,选品结果集总数量可达N*M,写入高流量将造成ES实例整体性能急剧下降。另一方面,数据修复成本极高,绑定错误只能重新绑定新的捞月集,需全量删除旧捞月集后再绑定新捞月集,两次写入成本极高。因此先进行增量数据维护,待增量数据check+fix通过后进行全量数据分批刷数。
双读check、不定时全量数据check+fix 、增量数据check+fix 、应用监控、日志告警埋点等;
针对灰度过程可能出现的所有数据错误预备对应数据订正接口。多想一步,如果在写切流过程中切换写主表后出现未识别到的数据错误,如何快速止血? 在迁移的过程中我们暂时保留搜索更新榜单商品的能力作为数据修复预案,可在一小时内完成数据修复。
具体灰度切流推进流程如下:
经历两个星期的灰度,已移除对搜索的依赖实现全链路闭环,依照灰度方案通过切流开关及预案等手段确保“随切随停”,上线期间零故障。
综上所述,榜单通过生产迁移彻底解决了一直以来榜单底层能力支撑不足的痛点。完成链路合并后,借助捞月圈品排序能力降低未来各类复杂定制化供给场景的维护成本,功能上线后已提升榜单各类业务迭代效率提升50%以上。并通过B/C端数据存储隔离,以极低的改造成本降低表存储成本60%。
在这个基础上,思考是否有更多的发力点:结合当前系统现状和未来的可能性,结合业务规划,围绕用户对平台榜单预期,未来将演变出多维度(内容、品牌、sku、spu等)榜单通用生产引擎,在供给充足基础上实现场景化个性化分发。
以上就是我们在得物商品榜单生产改造探索实践中的一些经验和总结,分享出来希望对阅读本文的你有一些帮助!
文/希希
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。