电商中常见的高并发解决方案
目录
多级缓存
什么叫多级缓存
多级缓存的实现思路
Redis 缓存同步 MySql 数据
Nginx 限流
什么是限流
常见的限流算法之漏桶算法
nginx 限流的方式
控制速率
控制并发量(连接数)
在本文中,我们将以京东为例,了解电商中常见的高并发解决方案
多级缓存
我们以京东首页为例
在上图中,我们可以看出商品的分类是较少发生变化的,这时我们可以把它存储到缓存中,这样数据库的压力会大大减少。这时我们会想到 redis 进行缓存,但是有时电商网站的并发数仅仅靠 redis 会使用 redis 压力过大,这时我们在此引出一个概念:多级缓存。
什么叫多级缓存
为了解决上文中的那个问题,我们在 redis 的基础上再添加一个 nginx 缓存,此时用户在访问我们网站时会先访问 nginx 缓存,如果 nginx 缓存没有,再访问 redis 缓存,如果 redis 也没有,此时我们最后访问 MySQL 获取数据,这样一来,我们将 redis 的压力大大减轻了,此时 nginx 缓存和 redis 缓存就构成了多级缓存。
多级缓存的实现思路
那么我们如何实现上面所说多级缓存呢?
我们可以使用 OpenResty 这一基于 Nginx 与 Lua 的高性能 Web 平台,该平台整合了 Nginx 和大量精良的 Lua 库、第三方模块以及大多数的依赖项。Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。关于 OpenResty 和 Lua,我们在本文不多过多涉及,这里只提供实现思路,有兴趣的可以访问 OpenResty 官网(http://openresty.org/cn/)和 Lua 官网(http://www.lua.org/)进行学习。在实际操作中,我们通常使用 Lua 脚本去访问 Nginx 缓存、Redis 缓存以及 MySQL,过程如下图:
但是在上面的过程中,我们会发现一个问题,在 Redis 缓存已存在的情况下,数据库的数据发生了改变,这时用户访问的都是缓存数据,那我们要如何解决这一问题呢?
Redis 缓存同步 MySql 数据
我们可以通过 canal 解决上面的问题。canal 是一个用来监控数据库数据的变化的工具,可以在Mysql 数据更新时获取其更新的数据。
解决思路:在 Mysql 数据变化时,我们可以通过 canal 微服务或配置MQ模式,配合 RocketMQ 或者 Kafka 来更改 Redis 中的缓存数据,这样 redis 缓存的数据就可以和 Mysql 中的数据保持一致了
关于 canal 的入门可以参考文章 超详细的Canal入门,看这篇就够了!_yehongzhi1994的博客-CSDN博客_canal
Nginx 限流
一般情况下,首页的并发量是比较大的,即使 有了多级缓存,当用户不停的刷新页面的时,或者有大量恶意的请求达到,也会对系统造成影响。这时我们就需要采用限流这一解决方案。
什么是限流
顾名思义,限流就是限制流量。例如你手机流量包只有1个G的流量,用完了就没了,这时候我们可以说我们的流量是受到限制,这就叫限流。
常见的限流算法之漏桶算法
算法思想是:
- 水(请求)从上方倒入水桶,从水桶下方流出(被处理);
- 来不及流出的水存在水桶中(缓冲),以固定速率流出;
- 水桶满后水溢出(丢弃)。
这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。
nginx 限流的方式
控制速率
我们先来说第一种,控制速率。Nginx 控制速率主要使用的是漏桶算法,即能够强行保证请求的实时处理速度不会超过设置的阈值。
配置 OpenResty 中 Nginx 的配置文件,使在访问 ip/test1 地址时进行限流,该地址会访问一个 Lua 脚本
user root root;
worker_processes 1;
events {worker_connections 1024;
}
http {include mime.types;default_type application/octet-stream;#限流设置limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=10r/s;sendfile on;#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65;#gzip on;server {listen 80;server_name localhost;location /test1{#使用限流配置limit_req zone=contentRateLimit;content_by_lua_file /root/lua/test1.lua;}}
}
配置说明:
binary_remote_addr 是一种key,表示基于 remote_addr(客户端IP) 来做限流,binary_ 的目的是压缩内存占用量。
zone:定义共享内存区来存储访问信息, contentRateLimit:10m 表示一个大小为10M,名字为 contentRateLimit 的内存区域。1M能存储 16000 IP地址的访问信息,10M可以存储16W IP地址访问信息。
rate 用于设置最大访问速率,rate=10r/s 表示每秒最多处理10个请求。Nginx 实际上以毫秒为粒度来跟踪请求信息,因此 10r/s 实际上是限制:每100毫秒处理一个请求。这意味着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求。
限流速度为每秒 10 次请求,如果有10次请求同时到达一个空闲的 nginx,他们都能得到执行吗?
事实上,漏桶漏出请求是匀速的。10r/s是怎样匀速的呢?每100ms漏出一个请求。在这样的配置下,桶是空的,所有不能实时漏出的请求,会被拒绝掉。所以如果10次请求同时到达,那么只有一个请求能够得到执行,其它的,都会被拒绝。这不太友好,大部分业务场景下我们希望这10个请求都能得到执行。
处理突发流量
上面这种情况我们管它叫做突发流量,上面例子限制 10r/s,如果有时正常流量突然增大,超出的请求将被拒绝,无法处理突发流量,可以结合 burst 参数使用来解决该问题。
修改上文中的 Nginx 配置文件
server {listen 80;server_name localhost;location /test1 {limit_req zone=contentRateLimit burst=20 nodelay;content_by_lua_file /root/lua/test1.lua;}
}
burst 译为突发、爆发,表示在超过设定的处理速率后能额外处理的请求数,当 rate=10r/s 时,将1s拆成10份,即每100ms可处理1个请求。
此处,burst=12,若同时有12个请求到达,Nginx 会处理第一个请求,剩余11个请求将放入队列,然后每隔100ms从队列中获取一个请求进行处理。若请求数大于12,将拒绝处理多余的请求,直接返回 503。
不过,单独使用 burst 参数并不实用。假设 burst=50 ,rate依然为10r/s,排队中的50个请求虽然每100ms会处理一个,但第50个请求却需要等待 50 * 100ms即 5s,这么长的处理时间自然难以接受。
因此,burst 往往结合 nodelay 一起使用。
继续修改上文中的 Nginx 配置文件
server {listen 80;server_name localhost;location /test1 {limit_req zone=contentRateLimit burst=20 nodelay;content_by_lua_file /root/lua/test1.lua;}
}
平均每秒允许不超过10个请求,突发不超过20个请求,并且处理突发20个请求的时候,没有延迟,等到完成之后,按照正常的速率处理。
如上两种配置结合就达到了速率稳定,但突然流量也能正常处理的效果。
控制并发量(连接数)
nginx 还提供了利用连接数限制某一个用户的ip连接的数量来控制流量。一种是限制固定连接数,第二种是限制每个客户端IP与服务器的连接数,同时限制与服务器的连接总数。
注意:并非所有连接都被计算在内,只有当服务器正在处理请求并且已经读取了整个请求头时,才会计算有效连接。
配置限制固定连接数:
http {include mime.types;default_type application/octet-stream;#限流设置limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=10r/s;#根据IP地址来限制,存储内存大小10Mlimit_conn_zone $binary_remote_addr zone=addr:1m;sendfile on;#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65;#gzip on;server {listen 80;server_name localhost;location /test2 {limit_conn addr 2;content_by_lua_file /root/lua/test2.lua;} location /test1 {limit_req zone=contentRateLimit burst=20 nodelay;content_by_lua_file /root/lua/test1.lua;} }
}
limit_conn_zone $binary_remote_addr zone=addr:10m; 表示限制根据用户的IP地址来显示,设置存储地址为的内存大小10M
limit_conn addr 2; 表示同一个地址只允许连接2次。
限制每个客户端IP与服务器的连接数,同时限制与服务器的连接总数:
http {include mime.types;default_type application/octet-stream;#限流设置limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=10r/s;#存储个人请求IP的限流配置limit_conn_zone $binary_remote_addr zone=perip:10m;#整个location对应的请求并发容量配置limit_conn_zone $server_name zone=perserver:100m;sendfile on;#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65;#gzip on;server {listen 80;server_name localhost;location /test2 {limit_conn perip 10;#单个客户端ip与服务器的连接数"10"limit_conn perserver 100; #限制与服务器的总连接数"100"content_by_lua_file /root/lua/test2.lua;} location /test1 {limit_req zone=contentRateLimit burst=20 nodelay;content_by_lua_file /root/lua/test1.lua;} }
}
电商中常见的高并发解决方案相关推荐
- 电商中常见的高并发怎么处理?
一.大规模并发带来的挑战 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战.如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态.我们现在 ...
- 电商中常见的高并发设计
一.大规模并发带来的挑战 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战.如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态.我们现在 ...
- Java面试中常见的高并发解决方案
Java面试中常见的高并发解决方案 一般来讲,提高系统应对高并发能力的解决方案可以从以下几个方面入手: (1)高性能服务器 (2)高性能数据库 (3)高效编程语言 (4)高性能web容器 提高数据库性 ...
- 深度解析大型分布式电商网站演变过程以及构架部署解决方案
前言: 本文是学习大型分布式网站架构的技术总结.对架构一个高性能,高可用,可伸缩,可扩展的分布式网站进行了概要性描述,并给出一个架构参考.一部分为读书笔记,一部分是个人经验总结.对大型分布式网站架构有 ...
- 分布式事务中常见的三种解决方案
分布式事务中常见的三种解决方案 目录 一.分布式事务前奏 二.柔性事务解决方案架构 (一).基于可靠消息的最终一致性方案概述 (二).TCC事务补偿型方案 (三).最大努力通知型 三.基于可靠消息的最 ...
- 搞懂分布式技术30:高并发解决方案——提升高并发量服务器性能解决思路
高并发解决方案--提升高并发量服务器性能解决思路 一个小型的网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很 ...
- 电商项目实战之分布式事务解决方案
电商项目实战之分布式事务解决方案 本地事务 事务隔离级别 事务传播机制 分布式事务 CAP理论 选举与同步理论 BASE理论 解决方案 2PC模式(XA事务) 柔性事务-TCC事务补偿型方案 柔性事务 ...
- Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析
Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析 生鲜电商搜索引擎的特点 众所周知,标准的搜索引擎主要分成三个大的部分,第一步是爬虫系统,第二步是数据分析,第三步才 ...
- 什么是高并发?高并发解决方案
比如接口响应超时.CPU load 升高.GC 频繁.死锁.大数据量存储等等,这些问题能推动我们在技术深度上不断精进. 在过往的面试中,如果候选人做过高并发的项目,我通常会让对方谈谈对于高并发的理解. ...
最新文章
- Spark MLlib实现的中文文本分类–Naive Bayes
- 相邻记录日期差 oracle,sql 相邻2条记录时间差比较
- ise 时钟约束_「新手入门」ISE工程升级到Vivado及板级信号调试技术
- Linux 管道使用示例
- mysql执行计划字段解析_MySQL执行计划解析
- 【linux网络编程】网络字节序、地址转换
- 开源系统管理资源大合辑
- .net Core 生产环境 KestrelServer + Shell 实践
- .Net 调用wordCOM组件转PDF
- 继Nat Friedman离开Github之后,Xamarin联合创始人离开微软
- UCI机器学习库和一些相关算法
- 大数据创业,数据哪里来?需要跨过几道坎?
- 在VB中使用API“SHFileOperation”删除文件的三个问题
- 回归模型1:优化的灰色模型matlab实现
- 小学生数据分析《西游记》发现大BUG
- 计算机网络基础(TCP/IP)
- android模拟器高德地图,【高德地图电脑版】高德地图电脑版官方下载 含安卓模拟器 车机版-趣致软件园...
- 凌恩生物文献分享|颠覆性的宏基因组新思路,速来get!
- Sql Server 时间格式转换
- BI 是如何数据分析的?