我的编程空间,编程开发者的网络收藏夹
学习永远不晚

redis秒杀系统的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

redis秒杀系统的实现

1.如何设计一个秒杀系统

在设计任何系统之前,我们首先都需要先理解秒杀系统的业务背景

下面我简单的举一个例子:

在某个时间点,某某电商网站要低价卖某件商品,而且限量1千件,抢购人数超过数十万人。
所以我们面临的第一个秒杀的问题就是:时间极短,然后瞬间流量非常大
我们的系统必须保证秒杀抢购的结果不出错,达到抢购的预期目的。
而且秒杀库存的实现也需要保障秒杀结果的准确性。
总结几个特点就是:

  • 高性能:秒杀中有大量的并发读写,所以需要使系统能支撑起高并发访问,这是一个关键点。
  • 高可用:藐视瞬间流量非常大,很有可能会导致系统宕机,所以需要从各方面保证系统的可用性。
  • 一致性:由于秒杀请求量非常大,此时就需要我们的秒杀结果要准确。因为一旦出错,那么波及面会非常广,损失非常大。

2.秒杀流程

我们先从秒杀的入口开始说起
在秒杀入口的地方会有这些问题需要解决:

2.1 前端处理

静态资源处理

秒杀商品一般都会包含很多静态资源,所以这些图片什么的静态资源一定要放到CDN(Content Delivery Network,即内容分发网络),能放的尽量放进去。让秒杀时后端服务器的压力尽可能小。
说到此处,我重点描述讲解CDN

为了能在传统IP网上发布丰富的宽带媒体内容,提出在现有互联网基础上建立一个内容分发平台专门为网站提供服务。由于CDN是为加快网络访问速度而被优化的网络覆盖层,因此被形象地称为“网络加速器”。
首先要说的是应用服务器和资源服务器应该解耦,也就是应用服务器只处理逻辑,而资源服务器存放内容或者叫资源。

  • CDN专注于「内容」,也就是CDN的C所代表的Content,专注于静态资源的分发和访问,比如一张图片,一个文本文件,一个视频,一个CSS,一个JS等等,任何以文件形式存储的,为了提高在互联网上的访问速度和质量,都可以将这个资源部署在CDN这个网络上。
  • CDN动作是「分发」,也就是如何让刚才提到的那些「内容」快速的部署在这个网络中,从而快速为用户服务,其实还有一层更重要的含义是用户的快速访问与就近接入,分发的目的是为了用户更好的体验。
  • CDN落定于「网络」,是部署于全国或者全世界的一大堆服务器,这些服务器基于当前互联网的基础架构在其上层再构成一个网络,这个网络专为资源分发而生。

那CDN的原理是什么呢?为什么用户可以接入离他最近的服务器呢?
主要是利用了DNS来判断用户位置,再返回给用户最近的机房的服务器的资源地址。
下面我再通俗的解释一下:
肯德基的总部在美国,可是你家楼下也有一家肯德基,并且汉堡包是一模一样的,这就是CDN(这个比喻来自知乎,觉得非常的恰当)。肯德基部署了很多个CDN在世界各地提供服务,用户都是找到最近的店,这个计算过程就是刚才讲的「就近接入」。

什么是CDN的调度呢?

(1)DNS调度是最常用和最通用的调度方案,缺点是存在DNS劫持的风险,调度的精确度也会差一些;
(2)302调度非常适合用在大文件下载和视频点播这两个应用场景,优点是可以提高调度的精确度,缺点是将会增加首包的时延(在大文件下载和视频点播场景下对首包时延不太敏感,而对调度精确度要求更高)
(3)HTTPDNS调度的优点是有较高的安全性(可以规避DNS劫持风险)和调度精确度,但是有个很大的缺点,需要客户端提供支持(例如在手机APP上嵌入SDK),通用性较差。

通俗来讲:

在一个商圈有两家肯德基,有一家组织活动,鸡腿随便吃,所以顾客全部涌到这家店,已经水泄不通,另一家店则门可罗雀。这个时候CDN的调度功能就要发挥作用了,另一家店也发布了一个消息说,买一个汉堡,打五折。这个时候,在第一家店抢不上鸡腿的顾客,马上跑去了第二家店,这个时候两个店的流量处于均衡状态。这就是CDN的调度。

恶意访问行为的处理

当我们推出秒杀活动后,还需要考虑黄牛党们开发出的各种秒杀器,可以自动填单,自动回答各种问题,以及自动模拟点击等,令我们防不胜防。
针对这些我们可以通过各种工作来限制和识别这些恶意访问。

  • 例如限制IP的提交次数
  • 提高各种动态验证码及问题的难度
  • 增加黑名单账户

秒杀链接隐藏

如果稍微懂点程序的人可以提前拿到秒杀链接,那么就可以通过程序在最快的时间发起秒杀请求,这样人家就可以拿到大部分商品了。为了防止这一点,可以使秒杀链接动态化。使用MD5算法等加密随机字符串作为URL的一部分,秒杀开始后才将连接放出来,同时在后台进行校验,此时已经可以防止一大批的羊毛党了。

前端限流

可以在秒杀按钮点击之后灰掉几秒钟,几秒钟之内只能点击一次。
可以使用Nginx用户请求到Nginx的时候将流量分散到多个服务器上,而且也可以针对用户进行一些过滤,将一些请求拦截,保证后端的稳定性。比如1万个商品,最多放进来10万个请求就可以了,其他的用户就只能等着静态页面喽。同时也可以在秒杀预约的时候随机发放一些token,只有拥有这些token的客户才有可能抢购成功。
同时在分布式的架构下,我们也可以通过gateway,redis+lua或者nginx进行限流

2.2 后端处理

后端限流

如果服务的流量到达最大值的时候,新的请求就不能再进来了。
而服务宕机的时候也需要引导请求到备用服务器上面,然后返回一些静态提示页面等。
隔离就要求,秒杀的服务单独部署,只承担其秒杀的单一职责,即使出问题,也不会影响其他的服务。

削峰

秒杀流量在某一个时间点非常高,那么我们让瞬间进来的流量进到一个缓冲池,然后再进行平缓处理。比较多用到的方案就是使用消息队列来处理。

库存预热

由于秒杀的商品的数量一般都是提前已知的,这时我们可以提前将商品的一些数据提前加载到缓存中。并且可以将商品分区来进行秒杀,根据每个大区的用户数量以及活跃程度,为每个大区分配单独的秒杀商品数量。这样也可以分散服务器压力。

使用缓存

高并发的情况下必然会遇到缓存雪崩,缓存击穿,缓存穿透等问题。而且秒杀的场景是读多写少,使用Redis作为缓存非常合适,为了避免单台Redis服务器出问题,导致缓存击穿等问题,升级使用Redis集群是一个比较好的方案。提升可用性的性能也可以大大提高。
下面我简单说一下缓存雪崩,缓存击穿以及缓存穿透

首先我们要先了解一下缓存的处理流程
前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。

知道什么是缓存之后我们重点来了解一下这三个名次具体指什么,以及如何去解决
缓存穿透
描述:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

缓存击穿
描述: 缓存击穿是指缓存中没有数据但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案:

  • 设置热点数据永远不过期。
  • 加互斥锁,互斥锁参考代码如下

我简单解释一下代码思路:
我们首先从缓存中获取数据,如果数据不存在,我们则去获取锁,这把锁 只需要能够互斥,可重入即可,最简单的就是redis的setnx来实现,获取锁资源以后,从数据库读取数据,同时将数据更新至缓存,然后释放锁;如果获取锁资源失败,我们就让其隔一段时间之后重新尝试去获取锁资源。

缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。
和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:

  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
  • 设置热点数据永远不过期。

3.超卖问题

秒杀中一个重要的点就是超卖问题,由于抢购人数多,流量也很大,但是也不能卖多了。
目前常见的解决方案就是:

1.数据库要加唯一索引,减库存的时候要先进行库存数量判断等,数据库锁,加版本号的乐观锁方式等等。2

.采用Redis来维护库存,由于秒杀活动可以预先知道商品的数量,所以可以提前将商品的数据加载到Redis中,如果Redis的库存不足的话则秒杀失败。

3.生成订单的时候将请求放到服务端的异步队列中去处理,可以使用Redis的队列,或者MQ均可。

4.总体思路

其实秒杀方案的总体思路也很简单:

1.尽可能的将请求拦截在上游;

2.后端均要处理限流;

3.尽量减少请求到数据库;

4.多利用缓存;

5.使用异步操作-可以使用队列等;

6.秒杀服务单一职责;

7.尽早失败,让秒杀请求返回

到此这篇关于redis秒杀系统的实现的文章就介绍到这了,更多相关redis 秒杀系统内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

redis秒杀系统的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎样用Redis轻松实现秒杀系统

这篇文章将为大家详细讲解有关怎样用Redis轻松实现秒杀系统,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。秒杀系统的架构设计秒杀系统,是典型的短时大量突发访问类问题。对这类问题,有三种优化性
2023-06-02

php中使用redis实现秒杀

正文:利用Redis的原子操作和分布式特性,在PHP中实现秒杀可防止高并发下单超卖。初始化Redis哈希表和集合来存储商品库存和成功秒杀用户。秒杀流程包括获取库存、原子性减少库存,并记录成功秒杀用户。优化措施包括限流、商品预热、管道和Lua脚本。该方法具有高并发能力、防止超卖和可扩展性,但需考虑数据一致性和容量限制。
php中使用redis实现秒杀
2024-04-25

php中使用redis实现秒杀

connect("127.0.0.1",6379); if(!$result){ throw new Exception("redis连接失败"); }} catch (Exception $e){ echo $e->getMe
php中使用redis实现秒杀
2019-10-28

Springboot+redis+Vue实现秒杀的项目实践

本文主要介绍了Springboot+redis+Vue实现秒杀的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

Redis实现商品秒杀的示例代码

本文详细讲解了使用Redis实现商品秒杀的示例代码。通过代码示例,文章展示了如何使用Redis的原子性操作和高性能来处理高并发秒杀场景。代码使用Redis的decr命令来原子性地扣除库存,确保秒杀过程的数据一致性。此外,Redis的可扩展性和分布式特性也使其能够满足大规模秒杀的需求。
Redis实现商品秒杀的示例代码
2024-04-02

如何使用Redis实现秒杀功能

这篇文章主要介绍如何使用Redis实现秒杀功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 怎样预防数据库超售现象设置数据库事务的隔离级别为Serializable(不可用)Serializable就是让数据库
2023-06-14

Redis消息队列怎么实现秒杀

要实现秒杀功能,可以使用Redis的消息队列来进行异步处理。下面是一种基本的实现方法:1. 准备工作:创建一个商品库存键值对,如"stock:商品ID",初始值为商品的库存数量;创建一个秒杀订单集合,用于保存已成功秒杀的订单。2. 用户秒杀
2023-10-11

Redis优惠券秒杀企业实战

目录一、全局唯一ID1. 全局ID生成器2. 全局唯一ID生成策略3. Redis自增ID策略二、实现优惠券秒杀下单1. 添加优惠券2. 编写添加秒杀券的接口三、实现秒杀下单四、超卖问题1. 加锁方式 - 乐观锁2. 乐观锁解决超卖问题3.
2022-07-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录