当前位置:首页 > 科技  > 软件

转转回收持久层的架构演进

来源: 责编: 时间:2024-06-14 08:53:41 285观看
导读1、前言我们在大部分开发场景下,对持久层的建设基于单库单表其实就可以实现当前的产品需求。但是随着业务发展越来越久,数据量、请求量也在不断的增加,只是单库单表可能不足以支撑系统的稳定运行,本文主要给大家分享一下

rsm28资讯网——每日最新资讯28at.com

1、前言

我们在大部分开发场景下,对持久层的建设基于单库单表其实就可以实现当前的产品需求。但是随着业务发展越来越久,数据量、请求量也在不断的增加,只是单库单表可能不足以支撑系统的稳定运行,本文主要给大家分享一下笔者在项目实际迭代过程中对持久层稳定性的建设过程。rsm28资讯网——每日最新资讯28at.com

2、项目简介

图片rsm28资讯网——每日最新资讯28at.com

简单来讲就是用户在一些活动场景下获取优惠券信息,领取并绑定到关系表里,后续用户去售卖一些商品的时候可以从领取的优惠券列表里选择一个合适的优惠券来使用。rsm28资讯网——每日最新资讯28at.com

3、面临的问题

3.1 数据越来越多

项目初期,单表完全可以hold住系统的稳定运行,但是由于优惠券的发放门槛特别低,导致优惠券的数量随着业务的发展激增,用户领券的关系表数量也越来越多,为了避免以后单表数据量过大带来的不必要的麻烦,我们对绑定关系表进行分表处理。rsm28资讯网——每日最新资讯28at.com

图片rsm28资讯网——每日最新资讯28at.com

3.1.1 技术选型

目前市面上对于分库分表的方案大体分为三类:rsm28资讯网——每日最新资讯28at.com

1.基于JDBC进行代理:该方案不需要运维等人员的介入,技术内部即可进行开发优化。rsm28资讯网——每日最新资讯28at.com

图片rsm28资讯网——每日最新资讯28at.com

2.基于数据库进行代理:该方案需要DBA或者运维的介入,维护起来不方便。rsm28资讯网——每日最新资讯28at.com

图片rsm28资讯网——每日最新资讯28at.com

3.TiDB数据库:支持无限的水平扩展,具备强一致性和高可用性,编码层面的使用跟MYSQL无异。rsm28资讯网——每日最新资讯28at.com

最终选型
以上三种方案,笔者这边最终选择了基于JDBC进行代理,因为这种方案可以纯内部进行消化,不需要外部部门介入,对于开发成本、时间周期来讲都是比较容易弹性调整的,后续有改造也不需要外部介入。rsm28资讯网——每日最新资讯28at.com

至于框架的选择选择了ShardingJDBC,原因以下几点:
1.社区活跃,遇到问题可以快速收到反馈。
2.框架经过多年演进,已经是很稳定且成熟的产品。
3.公司内部应用广泛,可以协助共建。rsm28资讯网——每日最新资讯28at.com

分库分表如何设计?
分库分表扩容涉及到重新hash分片的问题,极其麻烦,所以最好一步到位,短期内不进行扩容操作。
我们基于数据当前的增长速度,简单计算下未来十年可能带来的数据量,计算出8库8表即可满足该场景。
查询场景都是基于用户维度,所以拿uid作为分片键即可。rsm28资讯网——每日最新资讯28at.com

增长速度远超预期怎么办?
即使增长速度远超预期也不打算进行扩容操作,因为成本过高。优惠券过期时间很短,用户在优惠券过期一定时间后就可以考虑将优惠券进行归档操作,这样即可保证数据量稳定在我们预期之内。rsm28资讯网——每日最新资讯28at.com

为什么不用TiDB?
由于笔者对TiDB了解不深,考虑到遇到问题不易快速定位、解决,且该表对于业务流程至关重要,所以暂不考虑使用TiDB来存储。rsm28资讯网——每日最新资讯28at.com

3.1.2 数据迁移流程

迁移流程大体如下:
1 延迟双写
我们先插入或修改旧表数据,成功之后再去写入或修改新表,然后发送一个延迟消息,消息触达之后进行新老数据核对,如果数据存在异常则进行修正,令其保持一致。rsm28资讯网——每日最新资讯28at.com

2 数据清洗
设置一个时间节点,将该时间点前的主键id全部跑出来,然后在脚本任务里,实时去查询该主键id对应的最新数据,写入到新表中。rsm28资讯网——每日最新资讯28at.com

3 异步纠错
迁移后的一定时间内,查询的时候对新老数据进行校验,如有不一致数据进行异步修复。rsm28资讯网——每日最新资讯28at.com

具体流程如图:
图片rsm28资讯网——每日最新资讯28at.com

3.2 查询越来越复杂

3.2.1 初期方案

优惠券由于查询条件比较复杂(涉及到数组查询、模糊查询),且随着业务发展不断追加新的查询条件,导致不太适合每个查询条件作为单独的字段存储,故而放到了一个json里统一维护,但是这种存储方式查询的时候就无法直接利用mysql进行过滤。
例如:小明想查询一个条件为:iPhone13非全新机、价格满1000元可用、以旧换新场景下、邮寄售卖可用的优惠券。
最初数据量不多的时候直接把配置表全部拿出来机型进行内存过滤,拿着满足条件的配置id去绑定关系表里进行查找。
图片rsm28资讯网——每日最新资讯28at.com

3.2.2 临时改进方案

随着产品不断创建优惠券进行精细化投放,热门机型都会有对应的优惠券,库里的券大概有几百条。这样每次都要从库里全量拉出几百条进行处理的话显然99.9%的数据都是不必要的,因为用户只需要一张券,所以考虑成本最小的临时改进方案就是将优惠券放到内存中进行缓存,通过内存过滤减少每个请求过来造成的不必要的额外查询,降低gc频率。
这里借鉴了一些中间件同步缓存数据的方案,进行推拉结合的方式,一方面实时广播推送保证时效性,另一方面定时去拉数据来进行兜底处理。图片rsm28资讯网——每日最新资讯28at.com

但是本方案也不是长久之计,随着券的不断创建,内存中过滤的id可能会命中的特别多,这样查询的时候性能也会很糟糕,所以在时间充裕的时候考虑介入其他更适合的中间件,虽然成本高,但是能从根本上是解决问题。rsm28资讯网——每日最新资讯28at.com

图片rsm28资讯网——每日最新资讯28at.com

3.2.3 接入ElasticSearch中间件

通过调研发现公司内部比较适合的查询中间件只有ElasticSearch,市面上也可能有其他适合的中间件,但还需要考虑额外的搭建、运维维护的成本,使用ElasticSearch就足够解决该问题。
这里实际接入流程不做多赘述,有兴趣的可以参考相关的文章。rsm28资讯网——每日最新资讯28at.com

不过使用ElasticSearch也有一个缺点,就是数据写入到查询存在一定的延迟,并且我们这边有的场景还对时效性要求很高,例如:系统在请求的开始阶段给用户发一张券,用户拿到后还会再去获取最优券,这张券直接查可能会获取不到。
原来的兼容方案是写入成功后业务内部把id带到上下文在内存中进行过滤,这样需要兼容的地方很多,且每个场景都要单独处理。rsm28资讯网——每日最新资讯28at.com

那我是如何解决的?
我这边通过Redis+ElasticSearch 联动查询来保证时效性,在写入成功之后将配置id同步保存到Redis的zset结构中,设置个10s的过期时间。rsm28资讯网——每日最新资讯28at.com


图片rsm28资讯网——每日最新资讯28at.com

当有查询过来的时候,同时查询ElasticSearch与redis中的数据,然后合并过滤获取出最合适的券。rsm28资讯网——每日最新资讯28at.com


图片rsm28资讯网——每日最新资讯28at.com

一些性能优化手段:
1.查询只返回需要的字段信息。
2.定义索引的时候使用合适的字段。
3.限制数据总量,根据实际场景做数据归档。
4.减少索引范围,强制根据uid进行分片路由。rsm28资讯网——每日最新资讯28at.com

图片rsm28资讯网——每日最新资讯28at.com

3.3 请求量越来越大

3.3.1 读写分离

随着业务qps越来越高,每逢大促写入、查询的流量都会激增,所以经常收到关于主库流量太高的数据库告警,为了应对各种带来的尖刺流量,保证主库的稳定,进行了读写分离,减缓主库写入的压力。rsm28资讯网——每日最新资讯28at.com

主从延迟怎么解决?
有一种最简单粗暴的方案,单独提供主库的查询接口,但是这种对于调用方改造成本极大, 况且提供了主库接口之后可能很多人都不会去再使用从库了,从而无法达到读写分离的效果。rsm28资讯网——每日最新资讯28at.com

Object getByInfoFromMater(Long id);rsm28资讯网——每日最新资讯28at.com

理想中的方案
我这边调研了下是否有中间件能帮我实现主从选取的能力,即在主从同步成功之后才进行从库的读取,否则都是读取主库。rsm28资讯网——每日最新资讯28at.com

优点:服务方无感知
缺点:可能对性能造成影响rsm28资讯网——每日最新资讯28at.com

图片不过没找到这种中间件,所以我这边针对于这种方案用redis做了个一个简化版:rsm28资讯网——每日最新资讯28at.com

rsm28资讯网——每日最新资讯28at.com

通过定义注解来控制是否执行该组件:
设置了写入注解的方法:内部全部使用主库进行读操作,保证一致性,且设置2s左右过期时间的TAG。
设置读注解的方法:内部判断TAG是否存在,存在则走主库,否则从库。rsm28资讯网——每日最新资讯28at.com

这种方案也会带来负面影响:
带有注解的方法都要查询一次redis,耗时会增高, 且如果2s内主从同步失败,还是会存在查询不一致的情况,当然考虑实际场景,这种概率微乎其微,我们业务是可以接受的。rsm28资讯网——每日最新资讯28at.com

4、总结

在从0到1做一个项目的时候,没必要过度设计,应该快速上线,保证系统正常运行即可。项目初期可以先遇到问题再去解决问题,但是项目具备一定的流量之后,需要提前发现项目痛点并规划如何解决,否则等到真正遇到问题,再去解决可能已经来不及了,留给我们解决的时间已经不多了。rsm28资讯网——每日最新资讯28at.com

以上都是笔者在实际工作中的总结、归纳,各位如果有更好的方案或是不同的见解,欢迎评论区留言,共同讨论、进步。rsm28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-93706-0.html转转回收持久层的架构演进

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 面试官:谈谈对SpringAI的理解?

下一篇: React 19 全览,新特性进行一次深度的体验学习

标签:
  • 热门焦点
  • 中兴AX5400Pro+上手体验:再升级 双2.5G网口+USB 3.0这次全都有

    2021年11月的时候,中兴先后发布了两款路由器产品,中兴AX5400和中兴AX5400 Pro,从产品命名上就不难看出这是隶属于同一系列的,但在外观设计上这两款产品可以说是完全没一点关系
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • 6月安卓手机性价比榜:Note 12 Turbo断层式碾压

    6月份有一个618,虽然这是京东周年庆的日子,但别的电商也都不约而同的跟进了,反正促销没坏处,厂商和用户都能满意。618期间一些产品也出现了历史低价,那么各个价位段的产品性价比
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • 在线图片编辑器,支持PSD解析、AI抠图等

    自从我上次分享一个人开发仿造稿定设计的图片编辑器到现在,不知不觉已过去一年时间了,期间我经历了裁员失业、面试找工作碰壁,寒冬下一直没有很好地履行计划.....这些就放在日
  • 只需五步,使用start.spring.io快速入门Spring编程

    步骤1打开https://start.spring.io/,按照屏幕截图中的内容创建项目,添加 Spring Web 依赖项,并单击“生成”按钮下载 .zip 文件,为下一步做准备。请在进入步骤2之前进行解压。图
  • 腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    作者:无锈钵来源:财经无忌7月16日晚,上海1862时尚艺术中心。伴随着幻象的精准命中,硕大的荧幕之上,比分被定格在了14:12,被寄予厚望的EDG战队以绝对的优势战胜了BLG战队,拿下了总决
  • 签约井川里予、何丹彤,单视频点赞近千万,MCN黑马永恒文希快速崛起!

    来源:视听观察永恒文希传媒作为一家MCN公司,说起它的名字来,可能大家会觉得有点儿陌生,但是说出来下面一串的名字之后,或许大家就会感到震惊,原来这么多网红,都签约这家公司了。根
  • 2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
Top