首页 > 数据库 >Redis+分布式+秒杀

Redis+分布式+秒杀

时间:2023-05-29 19:47:59浏览次数:49  
标签:请求 数据库 Redis 并发 秒杀 分布式

聊一下MySQL

关于mysql关系型数据库的一些分析:

1、从性能上:如果我们碰到需要执行耗时特别久,并且执行结果不是很频繁变动的SQL语句,我们就没有必要每次都去查询数据库,因为每次操作数据库都很耗时。

2、从并发上:在大并发的情况下(比如618秒杀活动,你敢让千万级的请求直接打到数据库上吗?)所有的请求直接访问数据库,数据库就由可能造成宕机。

Redis

针对第一种情况,可以将不那么频繁变换的结果放入基于缓存的数据库中,每次查询就去缓存中读数据,这样就提升了查询效率,也减轻了数据库的压力。

针对第二种情况,可以让这些高并发的请求从数据库中分离出来,不去直接访问数据库,另外找一个适合高并发的来处理请求。

那就是Redis!!!

是什么?

  • 基于内存的K/V存储中间件(关于K/V你还能想到谁?)
  • NoSQL(非关系型)数据库

干啥用?

  • 缓存

(将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率)

  • 设置定时过期数据
  • 分布式锁

(在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁)

  • 抽奖功能
  • 实现排行榜
  • .......

面试题:1、redis常见的数据结构有哪些?

2、Redis持久化了解么?

秒杀场景

618预热早已开启,其中必不可少的秒杀是一个非常典型的活动场景。比如,在双 11、618 等电商促销活动中,都会有秒杀场景。秒杀场景的业务特点是限时限量,业务系统要处理瞬时的大量高并发请求。在秒杀活动中,大量用户在同一时间窗口内抢购限量商品,这往往会给系统带来极高的并发压力。使用传统的关系型数据库来处理并发请求往往会导致性能瓶颈和系统崩溃。而Redis作为一种高性能的内存数据库,能够快速处理大量的读写请求,非常适合用于秒杀场景。

秒杀的特征一:瞬时并发访问量非常高。一般数据库只能支撑千级别的并发请求,而redis的并发处理能力能达到万级别,甚至更高。在秒杀时,我们需要使用redis拦截大部分请求,避免大量请求直接发送给数据库,造成数据库宕机。

秒杀的特征二:读多写少,都是简单的查询操作。对于简单的查询操作并且结果相对固定我们可以先将其查询出来放入redis中,减轻数据库的压力。秒杀活动中只有少部分用户能成功下单,所以,商品库存查询操作(读操作)要远多于库存扣减和下单操作(写操作)。

秒杀的特征三:实时性和响应时间要求。 秒杀活动通常是实时进行的,用户希望尽快得知抢购结果。系统需要具备高性能和低延迟,及时响应用户的请求。

三个阶段

秒杀前

秒杀前,用户会不断的刷新商品详情页,那么就会导致对详情页的请求量急剧增加。这个阶段的应对方案,一般是尽量把商品详情页的页面元素静态化,然后使用 CDN 或是浏览器把这些静态化的元素缓存起来。这样一来,秒杀前的大量请求可以直接由 CDN 或是浏览器缓存服务,不会到达服务器端了。

秒杀时

用户点击秒杀按钮---->大量并发请求查询库存--->有库存(下单){没有则返回,可能会点击其他秒杀按钮,继续查询库存}--->库存扣减---->生成实际订单---->后续处理(物流、订单支付等)

这个阶段的操作是:库存查验、库存扣减、订单处理。而最大的并发力都在库存查验操作上。这个阶段为了支撑大量高并发的库存查验请求,我们需要在这个环节使用 Redis 保存库存量,这样一来,请求可以直接从 Redis 中读取库存并进行查验。

为什么订单处理操作可以在数据库中执行?而库存扣减操作不能在数据库中执行?

1、在数据库中进行库存扣减操作会带来额外的开销。我们已经事先在redis中保存好了库存量,如果交给数据库来处理扣减,那么就需要数据库将最新的值再同步到redis中,这样反而繁琐也带来了额外的开销。

2、可能会出现超售的情况。数据库的处理速度很慢,而秒杀又是一个快速高并发的场景,可能数据库更新完一个库值,秒杀就结束了,可能会导致用户查询到旧的库存值,再进行下单,出现超售的情况。

所以需要在redis中把库存扣减和库存查验两个操作一气呵成,实现原子操作。

秒杀后

用户量减少,服务器完全可以独立进行订单处理等操作。

实现

我们可以使用Redis的原子操作和分布式锁来支撑秒杀时的场景。(本文介绍分布式锁)

简单聊聊分布式

简单理解:类比卫生间的隔间:

  1. 隔离性: 卫生间的隔间将每个使用者隔离开来,使每个人都能独立使用空间,不会相互干扰。同样,分布式系统中的各个节点也是相互隔离的,它们可以独立运行,不会相互影响。
  2. 资源共享: 卫生间的隔间提供共享的基础设施,如水源和排水管道等。类似地,分布式系统中的节点可以共享一些资源,如共享存储、共享数据库等。
  3. 容错性: 如果一个卫生间隔间出现故障或需要维护,其他隔间仍然可以继续使用。同样,分布式系统中的节点之间可以具备容错能力,如果某个节点发生故障,其他节点可以接替其工作。
  4. 扩展性: 如果需要更多的卫生间隔间,可以增加更多的隔间来满足需求。同样,分布式系统可以通过增加更多的节点来实现扩展性,以处理更大的负载和流量。

Redis分布式锁(秒杀场景)

先让客户端向 Redis 申请分布式锁,只有拿到锁的客户端才能执行库存查验和库存扣减。这样一来,大量的秒杀请求就会在争夺分布式锁时被过滤掉。而且,库存查验和扣减也不用使用原子操作了,因为多个并发客户端只有一个客户端能够拿到锁,已经保证了客户端并发访问的互斥性。大部分秒杀请求本身就会因为抢不到锁而被拦截。

为啥要实现分布式锁:

  • 在有限的资源情况下,控制同一时间(段)只有某些线程(用户/服务器)能访问到资源。(比如秒杀时)
  • 单个锁只对单个jvm有限(好比用厕所只能用专属于自己的哪个)

关键:怎么保证同一时间内只有一个服务器抢到锁。

核心思想是:先来的人先把数据改成自己的标识(ip)后来的人发现标识已存在,就抢锁失败,继续等待,等先来的人执行方法结束,把标识清空,其他的人继续抢锁。(类比抢厕所/上厕所 )

注意事项:

  • 要注意解锁(你不可能一直占着厕所吧!!!)。
  • 一定要注意加上过期时间(否则如果因为服务器挂掉,锁就会一直存在了)。

使用分布式锁可能存在的问题

1、锁提前过期:分布式锁设置的时间提前过期,会导致其他方法加入一块同时执行。(好比你拉*没拉完,外面大哥把厕所门给撬开了)导致多个方法同时执行了。

2、还有可能导致连锁效应(解锁时不小心释放掉别人的锁)同样导致多个方法同时执行。

3、解锁的时候,判断好了是自己的锁,但是当要执行解锁的时候,就在这个时刻,自己的锁过期了(不需要删了)有其他的方法见缝插针进来了,导致A删了B的锁。(就像是你用完厕所,你自己的门锁时间过期开了,你手里还有把解锁的“钥匙”,结果你打开了旁边大哥的门)这里其实是破坏了原子性。(需要保证A的操作是原子性的,不能有其他操作打断。(也就是说A的上锁和解锁中间不能有其他的锁操作)跟操作系统的PV操作好像)。

4、锁提前过期,任务还没执行完,可以进行续期。(就像你上厕所,外面大哥等了你10min,结果你还没完事,然后你跟大哥说再给我10min)进行续期。

关于redis在秒杀场景中的应用还有很多,这只是一丢丢~

场景题

1、如何防止超卖问题?

2、如何保证订单的顺序和可靠性?

3、如何解决重复下单的问题?

4、做了什么限流削峰的措施?

5、如果缓存中的数据突然失效,导致请求全部打到了数据库,怎么办?

6、秒杀系统面临的问题有哪些?

........

博客参考

实践篇(11)Redis支撑秒杀场景的关键技术

知识星球

标签:请求,数据库,Redis,并发,秒杀,分布式
From: https://www.cnblogs.com/kuangsun125/p/17441451.html

相关文章

  • redis本地部署
    1、Linux部署到https://redis.io/download/下载安装包下面的是最新的稳定版本,当然你也可以下载其他稳定版本 2、window部署到https://github.com/MicrosoftArchive/redis/releases下载安装包3、可视化工具 RedisPlus:免费、开源、支持Linux、window下载地址:https:/......
  • 聊聊分布式解决方案Saga模式
    Saga模式Saga模式使用一系列本地事务来提供事务管理,而一个本地事务对应一个Saga参与者,在Saga流程里面每一个本地事务只操作本地数据库,然后通过消息或事件来触发下一个本地事务,如果其中一个本地事务失败了,Saga就会执行一系列补偿事务来实现回滚操作。(补偿事务简单来讲就是对之前本......
  • Python连接Redis
    1、操作模式redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。 2、连接池redis-py使用connectionpool来管理对一个redisserver的所有连接,避免......
  • ubuntu22安装docker、redis、mysql及部署net6应用
    一、更新系统软件包索引sudoaptupdate二、安装dockersudoaptinstalldocker.io三、在docker中安装Mysql拉取mysql镜像dockerpullmysql:latest查看镜像dockerimages运行容器dockerrun-itd-p3306:3306-eMYSQL_ROOT_PASSWORD=123456--namemysql......
  • 十三、利用分布式锁解决超卖问题
    库存超卖问题对于商城系统。超卖了一部分可以补获,12306对超卖问题更敏感。JMeter的使用  超卖演示&使用JMeter对购票功能进行压测  使用synchronized是否能解决库存超卖?超卖问题出现原因: 假设余票为1,此时多个线程同时查询到这条余票记录,并进行扣减,那么则会导致......
  • SpringCloudAlibaba整合分布式事务Seata
    目录1整合分布式事务Seata1.1环境搭建1.1.1Nacos搭建1.1.2Seata搭建1.2项目搭建1.2.1项目示意1.2.2pom.xml1.2.2.1alibaba-demo模块1.2.2.2call模块1.2.2.3order模块1.2.2.4common模块1.2.3配置文件1.2.3.1order模块1.2.3.2call模块1.2.4OpenFeign调用1.2.5order......
  • 微服务架构学习与思考(13):分布式配置中心
    一、配置中心的诞生用编程语言编写应用项目时,一般都会有项目的配置文件。比如用java编写项目,有一个properties的配置文件,会把一些配置信息写入到该文本文件中,例如数据库相关的配置信息。这也体现了软件设计的一个原则:关注点分离。把代码和配置信息相分离。​......
  • 2023-05-28:为什么Redis单线程模型效率也能那么高?
    2023-05-28:为什么Redis单线程模型效率也能那么高?答案2023-05-28:1.C语言实现,效率高C语言程序运行速度快,因为其相较于其他高级语言更加接近底层机器。由于C语言直接操作内存,不会像其他语言那样依赖虚拟机或垃圾回收机制等中间层,从而能够实现更高的执行效率。2.单线程的优势Redi......
  • 2023-05-28:为什么Redis-单线程模型效率也能那么高?
    2023-05-28:为什么Redis-单线程模型效率也能那么高?答案2023-05-28:1.C语言实现,效率高C语言程序运行速度快,因为其相较于其他高级语言更加接近底层机器。由于C语言直接操作内存,不会像其他语言那样依赖虚拟机或垃圾回收机制等中间层,从而能够实现更高的执行效率。2.单线程的优势Redis采用......
  • Redis基础课程讲义
    Redis基础课程内容Redis入门Redis数据类型Redis常用命令Redis使用场景在Java中操作Redis1.前言1.1什么是RedisRedis是一个基于内存的key-value结构数据库。Redis是互联网技术领域使用最为广泛的存储中间件,它是「RemoteDictionaryService」的首字母缩写,也就是「远......