电商项目part07 订单系统的设计与海量数据处理

订单重复下单问题(幂等)

用户在点击“提交订单”的按钮时,不小心点了两下,那么浏览器就会向服务端连续发送两条创建订单的请求。这样肯定是不行的
解决办法是,让订单服务具备幂等性。什么是幂等性?幂等操作的特点是,操作任意多次执行所产生的影响,均与一次执行所产生的影响相同。也就是说,对于幂等方法,使用同样的参数,对它进行多次调用和一次调用,其对系统产生的影响是一样的。

在这里插入图片描述

读写分离与分库分表

使用 Redis 作为 MySQL 的前置缓存,可以帮助 MySQL 挡住绝大部分的查询请求。这种方法对于像电商中的商品系统、搜索系统这类与用户关联不大的系统、效果特别好。因为在这些系统中、任何人看到的内容都是一样的,也就是说,对后端服来说,任何人的查询请求和返回的数据都是一样的。在这种情况下,Redis 缓存的命中率非常高,几乎所有的请求都可以命中缓存。但是与用户相关的系统(不是用户系统本身,用户信息等相关数据在用户登录时进行缓存,就价值很高),使用缓存的效果就没有那么好了,比如,订单系统、账户系统、购物车系统、订单系统等等。对于这些系统而言,各个用户查询的信息与用户自身相关,即使同一个功能界面,用户看到的数据也是不一样的。比如,“我的订单”这个功能,用户看到的都是自己的订单数据。在这种情况下,缓存的命中率就比较低了,会有相当一部分查询请求因为命中不了缓存,穿透到 MySQL 数据库中。随着系统的用户数量越来越多,穿透到 MySQL 数据库中的读写请求也会越来越多,当单个 MySQL 支撑不了这么多的并发请求时,该怎么办?

读写分离

读写分离是提升 MySQL 并发能力的首选方案,当单个 MySQL 无法满足要求的时候,只能用多个 MySQL 实例来承担大量的读写请求。MySQL 与大部分常用的关系型数据库一样,都是典型的单机数据库,不支持分布式部署。用一个单机数据库的多个实例组成一个集群,提供分布式数据库服务,是一件非常困难的事情。一个简单且非常有效的是用多个具有相同数据的 MySOL 实例来分担大量查询请求,也就是“读写分离”。很多系统,特别是互联网系统,数据的读写比例严重不均衡,读写比例一般在 9:1 到几十比 1,即平均每发生几十次查询请求,才会有一次更新请求,那就是说数据库需要应对的绝大部分请求都是只读查询请求。
分布式存储系统支持分布式写是非常困难的,因为很难解决好数据一致性的问题。但分布式读相对来说就简单得多,能够把数据尽可能实时同步到只读实例上,它们就可以分担大量的查询请求了。读写分离的另一个好处是,实施起来相对比较简单。把使用单机 MySQL 的系统升级为读写分离的多实例架构非常容易,一般不需要修改系统的业务逻辑,只需要简单修改 DAO (Data Access Object,一般指应用程序中负责访问数据库的抽象层)层的代码,把对数据库的读写请求分开,请求不同的 MySQL 实例就可以了。通过读写分离这样一个简单的存储架构升级,数据库支持的并发数量就可以增加几倍到十几倍。所以,当系统的用户数越来越多时,读写分离应该是首要考虑的扩容方案。
主库负责执行应用程序发来的数据更新请求,然后将数据变更同步到所有的从库中。这样,主库和所有从库中的数据一致,多个从库可以共同分担应用的查询请求。
在这里插入图片描述

分库分表

除了访问 MySQL 的并发问题,还要解决海量数据的问题,很多的时候,会使用分布式的存储集群,因为 MySQI 本质上是一个单机数据库,所以很多场景下,其并不适合存储 TB 级别以上的数据。

如何规划分库分表

哪种情况适合分表,哪种情况适合分库。选择分厍或是分表的目的是解决如下两个问题。
第一,是为了解决因数据量太大而导致查询慢的问题。这里所说的“查询”,其实主要是事务中的查询和更新操作,因为只读的查询可以通过缓存和主从分离来解决。分表主要用于解决因数据量大而导致的查询慢的问题。
第二,是为了应对高并发的问题。如果一个数据库实例撑不住,就把并发请求分散到多个实例中,所以分库可用于解决高并发的问题。
简单地说,如果数据量太大,就分表如果并发请求量高,就分库。一般情况下,解决方案大都需要同时做分库分表,可以根据预估的并发量和数据量,分别计算应该拆分成多少个库以及多少张表。

实现

数据量

在设计系统,预估订单的数量每个月订单 2000W,一年的订单数可达2.4 亿。而每条订单的大小大致为 1KB,按照 MySQL 的知识,为了让 B+树的高度控制在一定范围,保证查询的性能,每个表中的数据不宜超过2000W。在这种情况下,为了存下 2.4 亿的订单,似乎应该将订单表分为 16(12 往上取最近的 2 的幂)张表。

选择分片键

既然决定订单系统分库分表,则还有一个重要的问题,那就是如何选择一个合适的列作为分表的依据,该列一般称为分片键(Sharding Key)。选择合适的分片键和分片算法非常重要,因为其将直接影响分库分表的效果。
这个问题的解决办法是,在生成订单 ID 的时候,把用户 ID 的后几位作为订单 ID 的一部分。这样按订单 ID 查询的时候,就可以根据订单 ID 中的用户 ID 找到分片。 所以在系统中订单 ID 从唯一 ID 服务获取 ID 后,还会将用户 ID的后两位拼接,形成最终的订单 ID。

在分片算法上,常用的有按范围,比如时间范围分片,哈希分片,查表法分片。最经常使用是哈希分片,对表的个数 进行直接取模

一旦做了分库分表,就会极大地限制数据库的查询能力,原本很简单的查询,分库分表之后,可能就没法实现了。分库分表一定是在数据量和并发请求量大到所有招数都无效的情况下,才会采用的最后一招。

具体实现

如何在代码中实现读写分离和分库分表呢?一般来说有三种方法。
1)纯手工方式:修改应用程序的 DAO 层代码,定义多个数据源,在代码中需要访问数据库的每个地方指定每个数据库请求的数据源。
2)组件方式:使用像 Sharding-JDBC 这些组件集成在应用程序内,用于代理应用程序的所有数据库请求,并把请求自动路由到对应的数据库实例上。
3)代理方式:在应用程序和数据库实例之间部署一组数据库代理实例,比如Atlas 或 Sharding-Proxy。对于应用程序来说,数据库代理把自己伪装成一个单节点的 MySQL 实例,应用程序的所有数据库请求都将发送给代理,代理分离请求,然后将分离后的请求转发给对应的数据库实例。

在这三种方式中一般推荐第二种,使用分离组件的方式。采用这种方式,代码侵入非常少,同时还能兼顾性能和稳定性。如果应用程序是一个逻辑非常简单的微服务,简单到只有几个 SQL,或者应用程序使用的编程语言没有合适的读写分离组件,那么也可以考虑通过纯手工的方式。不推荐使用代理方式(第三种方式),原因是代理方式加长了系统运行时数据库请求的调用链路,会浩成一定的性能损失,而且代理服务本身也可能会出现故障和性能瓶颈等问题。代理方式有一个好处,对应用程序完全透明。
所以在我们的订单服务中,使用了第二种方式,引入了 Sharding-JDBC,考虑要同时支持读写分离和分库分表,配置如下:
在这里插入图片描述
具体参考sharding-jdbc配置文件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网关认证的技术方案

我们认证授权使用springsecurity 和oauth2技术尽心实现具体实现流程见第五章文档,这里就是记录一下我们的技术方案 这是最开始的技术方案,我们通过认证为服务获取令牌然后使用令牌访问微服务,微服务解析令牌即可。但是缺点就是每个微服务都要…

如何构建多域名HTTPS代理服务器转发

在当今互联网时代,安全可靠的网络访问是至关重要的。本文将介绍如何使用SNI Routing技术来构建多域名HTTPS代理服务器转发,轻松实现多域名的安全访问和数据传输。 SNI代表"Server Name Indication",是TLS协议的扩展,用于…

打怪升级之从零开始的网络协议

序言 三个多月过去了,我又来写博客了,这一次从零开始学习网络协议。 总的来说,计算机网络很像现实生活中的快递网络,其最核心的目标,就是把一个包裹(信息)从A点发送到B点去。下面是一些共同的…

【Unity】【Amplify Shader Editor】ASE入门系列教程第一课 遮罩

新建材质 (不受光照材质) 贴图:快捷键T 命名: UV采样节点:快捷键U 可以调节主纹理的密度与偏移 添加UV流动节点: 创建二维向量:快捷键 2 遮罩:同上 设置shader材质的模板设置 添加主…

解决无法远程连接MySQL服务的问题

① 设置MySQL中root用户的权限: [rootnginx-dev etc]# mysql -uroot -pRoot123 mysql> use mysql; mysql> GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY Root123 WITH GRANT OPTION; mysql> select host,user,authentication_string from user; -…

项目总结知识点记录(二)

1.拦截器实现验证用户是否登录: 拦截器类:实现HandlerInterception package com.yx.interceptor;import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpS…

react-sortable-hoc 拖拽列表上oncick事件失效

const SortableItem SortableElement(({value, onChangePayment}) > {const onClickItem () > {// todo}return (<View className"-item" onClick{onClickItem}>xxxxxxx</View>) })问题&#xff1a;onClick 无效 解决&#xff1a;添加distance

VMware ESXi 7.0 优化VMFSL磁盘占用与系统存储大小

文章目录 VMware ESXi 7.0 优化VMFSL磁盘占用与系统存储大小引言创建ESXi7.0可启动 U 盘结果检查VMware ESXi 7.0 优化VMFSL磁盘占用与系统存储大小 引言 本文讲述了在 J1900平台上安装ESXi7.0时减少 VMFSL 分区占用的说明, 通常这来说些主机内置的磁盘空间非常小, 采用默认安…

bh004- Blazor hybrid / Maui 使用 BootstrapBlazor UI 库快速教程

1. 建立工程 bh004_BootstrapBlazorUI 源码 2. 添加 nuget 包 <PackageReference Include"BootstrapBlazor" Version"7.*" /> <PackageReference Include"BootstrapBlazor.FontAwesome" Version"7.*" />3. 添加样式表文…

stm32之7.位带操作---volatile---优化等级+按键控制

源码--- #define PAin(n) (*(volatile uint32_t *)(0x42000000 (GPIOA_BASE0x10-0x40000000)*32 (n)*4)) #define PEin(n) (*(volatile uint32_t *)(0x42000000 (GPIOE_BASE0x10-0x40000000)*32 (n)*4)) #define PEout(n) (*(volatile uint32_t *)(0x420…

Kubernetes(K8S)简介

Kubernetes (K8S) 是什么 它是一个为 容器化 应用提供集群部署和管理的开源工具&#xff0c;由 Google 开发。Kubernetes 这个名字源于希腊语&#xff0c;意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系。 Google 在 2014 年开源了 Kubernetes 项…

飞书小程序开发

1.tt.showModal后跳转页面 跳转路径要为绝对路径&#xff0c;相对路径跳转无响应。 2.手机息屏后将不再进入onload()生命周期&#xff0c;直接进入onshow()生命周期。 onLoad()在页面初始化的时候触发&#xff0c;一个页面只调用一次。 onShow()在切入前台时就会触发&#x…

[matlab]matlab配置mingw64编译器

第一步&#xff1a;下载官方绿色版本mingw64编译器然后解压放到一个非中文空格路径下面 比如我mingw64-win是我随便改的文件名&#xff0c;然后添加环境变量&#xff0c;选择用户或者系统环境变量添加下面的变量 变量名&#xff1a; MW_MINGW64_LOC 变量值&#xff1a;自己的m…

1.linux的常用命令

目录 一、Linux入门 二、Linux文件系统目录 三、Linux的vi和vim的使用 四、Linux的关机、重启、注销 四、Linux的用户管理 五、Linux的运行级别 六、Linux的文件目录指令 七、Linux的时间日期指令 八、Linux的压缩和解压类指令 九、Linux的搜索查找指令 ​​​​​​…

2023国赛数学建模思路 - 案例:随机森林

文章目录 1 什么是随机森林&#xff1f;2 随机深林构造流程3 随机森林的优缺点3.1 优点3.2 缺点 4 随机深林算法实现 建模资料 ## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff…

最新本地大模型进展#Chinese-LLaMA-2支持16k长上下文

‍‍ Hi&#xff0c;今天为大家介绍最新的本地中文语言模型进展。 [2023/08/25] Chinese-LLaMA-2发布了新的更新&#xff1a; 长上下文模型Chinese-LLaMA-2-7B-16K和Chinese-LLaMA-2-13B-16K&#xff0c;支持16K上下文&#xff0c;并可通过NTK方法进一步扩展至24K。 这意味着在…

基于OpenCV的迷宫路径查找

附上代码&#xff1a; import cv2 import numpy as np# 读取图像 img cv2.imread("img_3.png") thres_min 150 # 二值化最小阈值if not img is None:# 二值化处理ret, img cv2.threshold(img, thres_min, 255, cv2.THRESH_BINARY)cv2.imshow("img_thres&qu…

数据结构——布隆计算器

文章目录 1.什么是布隆过滤器&#xff1f;2.布隆过滤器的原理介绍3.布隆过滤器使用场景4.通过 Java 编程手动实现布隆过滤器5.利用Google开源的 Guava中自带的布隆过滤器6.Redis 中的布隆过滤器6.1介绍6.2使用Docker安装6.3常用命令一览6.4实际使用 1.什么是布隆过滤器&#xf…

【python】jupyter notebook导出pdf和pdf不显示中文问题

文章目录 写在前面1. 使用jupyter notebook导出pdf1.1 安装Pandoc1.2 安装MiKTex1.3 示例导出pdf 2. 中文显示问题2.1 显示中文问题示例2.2 解决办法1&#xff1a;修改tex2.3 解决办法2&#xff1a;修改内置文件 写在前面 使用jupyter notebook导出pdf时&#xff0c;出现了一些…

用python从零开始做一个最简单的小说爬虫带GUI界面(3/3)

目录 上一章内容 前言 出现的一些问题 requests包爬取小说的不便之处 利用aiohttp包来异步爬取小说 介绍 代码 main.py test_1.py test_3.py 代码大致讲解 注意 系列总结 上一章内容 用python从零开始做一个最简单的小说爬虫带GUI界面&#xff08;2/3&#xff09;_…