[中间件] 秒杀系统秒杀率提高300%?教你如何利用redis和rabbitmq 优化应用!

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: [中间件] 秒杀系统秒杀率提高300%?教你如何利用redis和rabbitmq 优化应用!

前言: 近年来,随着互联网的发展,电商越来越受到人们的欢迎,而秒杀活动也成为了电商中的一种重要营销手段。但是,秒杀活动对系统的性能、并发性和可用性提出了极高的要求,因此需要一些高效、可靠的技术来支持秒杀系统。本文将详细介绍redis和rabbitmq在秒杀系统中的作用,并提供相关的SpringBoot demo代码。


redis在秒杀系统中的作用

缓存

秒杀系统中,每秒可能会有成千上万的用户同时发起抢购请求。为了提高系统的并发性和响应速度,我们通常会采用缓存技术。redis是一种基于内存的缓存数据库,它提供了高速的读写能力和丰富的数据结构,是秒杀系统中的一种理想缓存方案。

在秒杀系统中,我们可以将商品库存信息、用户购买记录等数据存储在redis中,并通过redis提供的原子操作,如incr、decr、setnx等来保障操作的原子性和线程安全性。下面是一段使用redis模拟商品秒杀的demo代码:

@Component
public class SecKillService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    public boolean secKill(String itemId, String userId) {
        // 从redis中获取商品库存
        String stock = redisTemplate.opsForValue().get("stock:" + itemId);
        if (stock == null || Integer.parseInt(stock) <= 0) {
            return false;
        }
        // 库存减一
        Long result = redisTemplate.opsForValue().decrement("stock:" + itemId);
        if (result < 0) {
            redisTemplate.opsForValue().increment("stock:" + itemId);
            return false;
        }
        // 记录用户购买记录
        redisTemplate.opsForSet().add("user:" + userId + ":purchases", itemId);
        return true;
    }
}

在这个demo中,我们使用redis的incr、decr、setnx、add等命令来实现商品库存的管理和用户购买记录的记录。其中,incr和decr命令分别用于对库存进行原子性的加减操作,setnx命令用于限制并发抢购数量,add命令用于记录用户的购买记录。

限流

秒杀系统中,由于并发量过大,可能会造成系统崩溃。因此,我们需要对系统进行限流,确保系统稳定运行。redis提供了一些限流算法,如令牌桶算法和漏桶算法,可以限制请求的频率和数量,避免系统崩溃。下面是一个使用redis令牌桶算法实现请求限流的demo代码:

@Component
public class RateLimiter {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    public boolean acquire(String key, int capacity, int rate) {
        String tokenCount = redisTemplate.opsForValue().get(key);
        if (tokenCount == null) {
            redisTemplate.opsForValue().set(key, String.valueOf(capacity));
            redisTemplate.expire(key, 1, TimeUnit.SECONDS);
            return true;
        }
        int count = Integer.parseInt(tokenCount);
        if (count <= 0) {
            return false;
        }
        redisTemplate.opsForValue().set(key, String.valueOf(count - 1));
        redisTemplate.expire(key, 1, TimeUnit.SECONDS);
        return true;
    }
}

在这个demo中,我们使用redis的set和get命令来实现令牌桶算法。每秒钟可以产生一定数量的令牌,用户需要从桶中获取令牌才能发起请求。当桶中没有令牌时,用户请求会被拒绝,从而实现请求限流的效果。

rabbitmq在秒杀系统中的作用

异步队列

在秒杀系统中,用户的请求需要经过多个服务层的处理,包括订单生成、库存更新、消息通知等。由于各个服务层的处理时间和并发量不同,如果同步处理所有请求,可能会导致系统崩溃或响应非常慢。因此,我们可以采用异步队列的方式来处理请求,将请求加入消息队列中,由队列中的消费者异步处理。

rabbitmq是一种高效、可靠的消息队列系统,支持多种消息传输模式和多种消息协议,是秒杀系统中的一种理想消息队列系统。

下面是一个使用rabbitmq实现异步消息队列的demo代码:

@Component
public class SecKillSender{
    @Autowired
    private RabbitTemplate rabbitTemplate;
    public void send(String itemId, String userId) {
        rabbitTemplate.convertAndSend("secKillExchange", "secKillRoutingKey", itemId + ":" + userId);
    }
}
@Component
@RabbitListener(queues = "secKillQueue")
public class SecKillReceiver {
    @Autowired
    private SecKillService secKillService;
    @RabbitHandler
    public void process(String message) {
        String[] values = message.split(":");
        String itemId = values[0];
        String userId = values[1];
        secKillService.secKill(itemId, userId);
    }
}

在这个demo中,我们使用rabbitmq实现了一个异步消息队列。发送者将用户请求加入消息队列,接收者从消息队列中获取请求并异步处理。通过这种方式,我们可以将请求的处理分散到多个服务层中,提高系统的并发性和性能。

总结

本文介绍了redis和rabbitmq在秒杀系统中的作用,并提供了相关的SpringBoot demo代码。在实际开发中,我们可以根据需求选择适合的缓存方案和消息队列系统,以提高系统的并发性和性能。

demo缺点

上述demo实现了一个秒杀系统,其中redis用于缓存商品信息和库存信息,rabbitmq用于异步处理订单。但是,这种实现方式仍然存在以下缺点:

1)高并发情况下,redis的性能不足以支持;当秒杀活动开始时,短时间内可能会有大量用户同时访问系统,而redis的性能会受到影响,从而导致请求超时、系统宕机等问题。

2)rabbitmq的消息堆积问题;当系统承受不住高并发的订单处理请求,rabbitmq队列中的消息将会堆积,导致系统负载过高,进而影响系统整体稳定性。

3)redis 的原子性操作


解决方案

针对上述问题,我们可以通过以下方式来优化redis和rabbitmq的应用:

1)使用redis集群;通过将redis分布在多个服务器节点上,可以提高redis的性能和可用性,从而支持更高的访问量。当其中的某个redis节点出现宕机,集群中的其他节点将自行接管其工作,确保系统的高可用性和稳定性。

2)使用rabbitmq集群;同理,使用rabbitmq集群可以提高其性能和可用性,从而避免消息的堆积问题。当其中的某个节点出现宕机时,集群中的其他节点将自动补位,确保系统的高可用性和稳定性。

3)使用分布式锁;在秒杀系统中,商品库存有限,需要使用分布式锁来保证多个用户并发下的订单处理的顺序性和正确性。目前主流的分布式锁实现方式有基于redis的RedLock、ZooKeeper等,可以根据具体场景选择最合适的实现方式。

4)使用消息队列异步处理订单;在高并发的情况下,同步处理订单容易导致系统负载过高,进而影响系统稳定性。因此,我们可以使用消息队列异步处理订单,通过rabbitmq将订单消息发送到队列中,由监听该队列的线程异步处理,提高系统的性能和稳定性。

5)使用 lua 脚本实现原子性操作


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
NoSQL 安全 测试技术
Redis游戏积分排行榜项目中通义灵码的应用实战
Redis游戏积分排行榜项目中通义灵码的应用实战
63 4
|
14天前
|
消息中间件 存储 监控
说说MQ在你项目中的应用(一)
本文总结了消息队列(MQ)在项目中的应用,主要围绕异步处理、系统解耦和流量削峰三大功能展开。通过分析短信通知和业务日志两个典型场景,介绍了MQ的实现方式及其优势。短信通知中,MQ用于异步发送短信并处理状态更新;业务日志中,Kafka作为高吞吐量的消息系统,负责收集和传输系统及用户行为日志,确保数据的可靠性和高效处理。MQ不仅提高了系统的灵活性和响应速度,还提供了重试机制和状态追踪等功能,保障了业务的稳定运行。
53 6
|
2月前
|
Web App开发 JSON JavaScript
Node.js 中的中间件机制与 Express 应用
Node.js 中的中间件机制与 Express 应用
|
14天前
|
消息中间件 存储 中间件
说说MQ在你项目中的应用(二)商品支付
本文总结了消息队列(MQ)在支付订单业务中的应用,重点分析了RabbitMQ的优势。通过异步处理、系统解耦和流量削峰等功能,RabbitMQ确保了支付流程的高效与稳定。具体场景包括用户下单、支付请求、商品生产和物流配送等环节。相比Kafka,RabbitMQ在低吞吐量、高实时性需求下表现更优,提供了更低延迟和更高的可靠性。
29 0
|
2月前
|
监控 NoSQL 网络协议
【Azure Redis】部署在AKS中的应用,连接Redis高频率出现timeout问题
查看Redis状态,没有任何异常,服务没有更新,Service Load, CPU, Memory, Connect等指标均正常。在排除Redis端问题后,转向了AKS中。 开始调查AKS的网络状态。最终发现每次Redis客户端出现超时问题时,几乎都对应了AKS NAT Gateway的更新事件,而Redis服务端没有任何异常。因此,超时问题很可能是由于NAT Gateway更新事件导致TCP连接被重置。
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
45 5
|
2月前
|
消息中间件 存储 Apache
探索 RocketMQ:企业级消息中间件的选择与应用
RocketMQ 是一个高性能、高可靠、可扩展的分布式消息中间件,它是由阿里巴巴开发并贡献给 Apache 软件基金会的一个开源项目。RocketMQ 主要用于处理大规模、高吞吐量、低延迟的消息传递,它是一个轻量级的、功能强大的消息队列系统,广泛应用于金融、电商、日志系统、数据分析等领域。
103 0
探索 RocketMQ:企业级消息中间件的选择与应用
|
3月前
|
消息中间件 编解码 Docker
【Docker项目实战】Docker部署RabbitMQ消息中间件
【10月更文挑战第8天】Docker部署RabbitMQ消息中间件
132 1
【Docker项目实战】Docker部署RabbitMQ消息中间件
|
3月前
|
存储 消息中间件 NoSQL
【redis】redis的特性和主要应用场景
【redis】redis的特性和主要应用场景
184 1
|
4月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo