当前位置: 首页 > news >正文

秒杀服务------技术点及亮点

大技术

使用Redisson

使用Redisson在秒杀服务中有两个作用,一个是作为分布式锁来确保多个秒杀服务同时在线时同时上架秒杀商品,只允许有一个秒杀服务成功上架秒杀商品,其他的上架失败。第二个作用是作为分布式信号量,每个秒杀商品在存到Redis中时都设置一个分布式信号量,把每个秒杀商品的数量作为信号量的值,这是为了防止秒杀的时候出现穿库的情况(就是只设置了3个秒杀数量,结果秒杀结束后秒杀数量是5个,这就亏本了)

1、导入依赖

<!-- 以后使用redisson作为分布式锁,分布式对象等功能框架 -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.8</version>
</dependency>

2、设置Redission配置类

package com.saodai.saodaimall.saodaimall.seckill.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.IOException;/**
* redission分布式锁配置类
*/
@Configuration
public class MyRedissonConfig {/*** 所有对Redisson的使用都是通过RedissonClient* @return* @throws IOException*/@Bean(destroyMethod="shutdown")public RedissonClient redisson() throws IOException {//1、创建配置Config config = new Config();//配置虚拟机的地址config.useSingleServer().setAddress("redis://192.168.241.128:6379");//2、根据Config创建出RedissonClient实例(单个实例)//Redis url should start with redis:// or rediss://RedissonClient redissonClient = Redisson.create(config);return redissonClient;}
}

3、Redission作为分布式锁

package com.saodai.saodaimall.saodaimall.seckill.scheduled;
import com.saodai.saodaimall.saodaimall.seckill.service.SeckillService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;/**
* 秒杀商品定时上架
*  每天晚上3点,上架最近三天需要三天秒杀的商品
*  当天00:00:00 - 23:59:59
*  明天00:00:00 - 23:59:59
*  后天00:00:00 - 23:59:59
*/@Slf4j
@Service
public class SeckillScheduled @Autowiredprivate SeckillService seckillService;@Autowiredprivate RedissonClient redissonClient;//秒杀商品上架功能的锁private final String upload_lock = "seckill:upload:lock";/**保证幂等性问题**///     @Scheduled(cron = "*/5 * * * * ? ") //秒 分 时 日 月 周@Scheduled(cron = "0 0 1/1 * * ? ") public void uploadSeckillSkuLatest3Days() {//1、重复上架无需处理log.info("上架秒杀的商品...");//分布式锁RLock lock = redissonClient.getLock(upload_lock);try {//加锁(指定锁定时间为10s)lock.lock(10, TimeUnit.SECONDS);seckillService.uploadSeckillSkuLatest3Days();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}

使用Redisson作为分布式锁是为了确保多个秒杀服务同时在线时同时上架秒杀商品,只允许有一个秒杀服务成功上架秒杀商品,其他的上架失败

4、Redission实现分布式信号量

作为分布式信号量,每个秒杀商品在存到Redis中时都设置一个分布式信号量,把每个秒杀商品的数量作为信号量的值,这是为了防止秒杀的时候出现穿库的情况(就是只设置了3个秒杀数量,结果秒杀结束后秒杀数量是5个,这就亏本了)

/*** 封装秒杀活动的关联商品信息到缓存里* @param sessions 秒杀活动信息*/private void saveSessionSkuInfo(List<SeckillSessionWithSkusVo> sessions) {if (sessions!=null){sessions.stream().forEach(session -> {//准备hash操作,绑定hash值seckill:skusBoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(SECKILL_CHARE_PREFIX);//遍历秒杀活动中的商品项(seckillSkuVo表示的就是每个遍历的商品项)session.getRelationSkus().stream().forEach(seckillSkuVo -> {//生成随机码String token = UUID.randomUUID().toString().replace("-", "");//查看redis中有没有这个key (秒杀场次id_秒杀商品id)String redisKey = seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString();if (!operations.hasKey(redisKey)) {//缓存我们商品信息(SeckillSkuRedisTo是存入缓存中的对象)SeckillSkuRedisTo redisTo = new SeckillSkuRedisTo();Long skuId = seckillSkuVo.getSkuId();//1、先查询sku的基本信息,调用远程服务R info = productFeignService.getSkuInfo(skuId);if (info.getCode() == 0) {SkuInfoVo skuInfo = info.getData( "skuInfo",new TypeReference<SkuInfoVo>(){});redisTo.setSkuInfo(skuInfo);}//2、sku的秒杀信息BeanUtils.copyProperties(seckillSkuVo,redisTo);//3、设置当前商品的秒杀时间信息redisTo.setStartTime(session.getStartTime().getTime());redisTo.setEndTime(session.getEndTime().getTime());//4、设置商品的随机码(防止恶意攻击)redisTo.setRandomCode(token);//序列化json格式存入Redis中String seckillValue = JSON.toJSONString(redisTo);//秒杀活动的商品项的详细信息存入redis/**格式是key:4_47 value:SeckillSkuRedisTo对象的String类型**/operations.put(seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString(),seckillValue);//如果当前这个场次的商品库存信息已经上架就不需要上架/**5、使用库存作为分布式Redisson信号量(限流)**///把每个秒杀商品的总数量作为信号量存入redis缓存,信号量标识seckill:stock:+随机(相当于key)RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMAPHORE + token);/**库存的格式key:seckill:stock:5d1df46618d34f9f9808f25cda60ba01 value:秒杀商品的总数量 其中5d1df46618d34f9f9808f25cda60ba01是随机码**/semaphore.trySetPermits(seckillSkuVo.getSeckillCount());}});});}else {log.error("没有秒杀活动");}}
@Autowired
private RedissonClient redissonClient;/**5、使用库存作为分布式Redisson信号量(限流)**/
//获取分布式信号量,信号量名称为seckill:stock:+随机码
RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMAPHORE + token);
// 秒杀商品的库存数量作为信号量的值(允许同时seckillSkuVo.getSeckillCount()个用户获取到信号量)
semaphore.trySetPermits(seckillSkuVo.getSeckillCount());

实现uploadSeckillSkuLatest3Days方法中saveSessionSkuInfo(封装秒杀活动的关联商品信息到缓存里,每一个Redis缓存中具体sku信息用的是HashMap结构),通过HashMap结构把每个秒杀商品的详细信息以下面的格式存到Redis中,然后通过Redisson实现分布式信号量来把秒杀商品的库存总数量作为信号量存入redis缓存,每一个Redis缓存中具体sku信息的格式如下:

  • hash值是seckill:skus key: 4_47 value: SeckillSkuRedisTo对象

  • 其中key的4表示秒杀的场次id,47表示秒杀商品的skuId,由于用的是hashMap结构,其中hash值是seckill:skus

  • Redission实现分布式信号量设置时就会把信号量以key-value的格式存到reids缓存中,Redis缓存中信号量信息的格式如下:

  • key: seckill:stock:随机码 value:每个秒杀商品的总数量

  • 其中key的seckill:stock是固定前缀,随机码就是随机成功的uuid值,把每个秒杀商品的总数量作为信号量的值

  • 准备hash操作,绑定seckill:skus关键字的hash

  • 遍历封装存入redis的秒杀活动的秒杀商品项

  • 生成随机码

  • 封装SeckillSkuRedisTo对象并序列化后存入redis缓存

  • 远程调用product商品服务

  • 使用Redission实现分布式信号量来把秒杀商品的库存总数量作为信号量存入redis缓存(限流)

  • 秒杀活动的商品项的详细信息存入redis缓存

  • 设置商品的随机码(防止恶意攻击)

  • 设置当前商品的秒杀时间信息

  • 封装秒杀活动中秒杀商品项信息

4、秒杀时具体实现

@Autowired
private RedissonClient redissonClient;//分布式锁
RSemaphore semaphore = redissonClient.getSemaphore(key);
//尝试快速拿到信号量,100毫秒没有用拿到就返回false
//在指定的时间内尝试地获取1个许可,如果获取不到就返回false
boolean semaphoreCount = semaphore.tryAcquire(num, 100, TimeUnit.MILLISECONDS);

相关文章:

秒杀服务------技术点及亮点

大技术使用Redisson使用Redisson在秒杀服务中有两个作用&#xff0c;一个是作为分布式锁来确保多个秒杀服务同时在线时同时上架秒杀商品&#xff0c;只允许有一个秒杀服务成功上架秒杀商品&#xff0c;其他的上架失败。第二个作用是作为分布式信号量&#xff0c;每个秒杀商品在…...

【Python数据挖掘入门】一、数据挖掘概况

一、数据挖掘概况 数据挖掘是指从大量的数据中&#xff0c;通过统计学、人工智能、机器学习等方法&#xff0c;挖掘出未知的、具有价值的信息和知识的过程。 典型案例&#xff1a; 啤酒与尿布杜蕾斯与口香糖杜蕾斯与红酒 数据挖掘是一门交叉学科&#xff0c;覆盖了统计学、数…...

【python】anaconda 管理 python 环境

anaconda 管理虚拟环境anaconda 简介python 虚拟环境的安装查看当前 anaconda中所有的虚拟环境创建新的虚拟环境激活所创建的虚拟环境删除指定的虚拟环境退出当前虚拟环境查看当前虚拟环境中所有安装的库安装常用包pycharmpycharm 下环境配置pycharm 使用anaconda 简介 anacon…...

线上插画培训班有用吗,教你选靠谱的插画课程

线上插画培训班有用吗&#xff0c;教你选靠谱的插画课程&#xff0c;推荐5个靠谱的动漫插画培训课程&#xff0c;各有特色和优势&#xff0c;相信可以给大家一些参考&#xff01; 一&#xff1a;5个靠谱的动漫插画网课 1、轻微课&#xff08;五颗星&#xff09; 主打课程有日…...

吃鸡用什么蓝牙耳机效果好?手游吃鸡公认最好的几款蓝牙耳机

蓝牙耳机的作用很多&#xff0c;几乎每个人都需要一副很棒的耳机在通勤或锻炼途中使用&#xff0c;并且玩游戏也少不了它&#xff0c;手游近几年十分的流行&#xff0c;下面整理了几款性能不错的蓝牙耳机。 第一款&#xff1a;南卡小音舱蓝牙耳机 蓝牙版本&#xff1a;5.3 发…...

四个步骤在CRM系统中设置游戏化机制

长期高强度的单一工作会让销售人员逐渐失去对工作的兴趣&#xff0c;导致销售状态缺少动力和激情&#xff0c;工作开展愈加困难。不少企业通过CRM销售管理系统设置游戏化竞赛&#xff0c;调动销售人员的工作积极性。那么&#xff0c;如何在CRM系统中设置游戏化机制&#xff1f;…...

2023年TikTok营销如何破局?品牌应做好这6点

转眼到了2023年&#xff0c;虽然过去的一年&#xff0c;国际市场风云变幻&#xff0c;但对TikTok来说&#xff0c;却是丰收的一年。2022年&#xff0c; TikTok的全球收入为35亿美元&#xff0c;同比增长60%。TikTok以6.72亿次下载量依旧位居榜首&#xff0c;短视频进一步风靡全…...

2023年CDGA考试-第5章-数据建模和设计(含答案)

2023年CDGA考试-第5章-数据建模和设计(含答案) 单选题 1.请从下列选项中选择关于企业数据模型描述准确的选项 A.企业模型包括继承关系模型、概念模型、主题域模型、逻辑模型 B.企业模型包括数据名称、数据属性和元数据定义、概念和逻辑实体关系以及业务规则 C.企业模型包括…...

蓝桥杯入门即劝退(二十)快乐数(我不快乐了)

欢迎关注点赞评论&#xff0c;共同学习&#xff0c;共同进步&#xff01; ------持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法&#xff0c;欢迎订阅专栏共同学习交流&#xff01; 你的点赞、关注、评论、是我创作的动力&#xff01; -------希望我的文章…...

Aspose.Imaging for .NET V23

Aspose.Imaging for .NET V23 Aspose.Imaging for.NET是帮助开发人员在自己的应用程序中创建、编辑、绘制或转换图像的类库。它包括在不安装Photoshop或任何其他图像编辑器的情况下以Adobe Photoshop原生格式保存的功能。Aspose.Imaging for.NET是一个灵活稳定的API&#xff0c…...

通信算法复习题纲

通信算法复习题1、当信源发送信号满足以下哪一项条件时&#xff0c;接收端采用最小距离准则进行判决等价于采用最大后验概率准则进行判决&#xff1f;2、OFDM系统的正交性体现在哪个方面&#xff1f;3、模拟信号数字化过程中&#xff0c;哪一步会引入量化噪声&#xff1f;4、OF…...

交叉编译 MQTT/Mosquitto

交叉编译 MQTT/Mosquitto 概述 Eclipse Mosquitto 是一个开源&#xff08;EPL/EDL许可&#xff09;消息代理&#xff0c;它实现了 MQTT 协议版本 5.0、3.1.1 和 3.1。Mosquitto 重量轻&#xff0c;适用于从低功耗单板计算机到全服务器的所有设备。 MQTT 协议提供了一种使用发…...

无重复字符的最长子串的解法

class Solution {public int lengthOfLongestSubstring(String s) {// 哈希集合&#xff0c;记录每个字符是否出现过Set<Character> occ new HashSet<Character>();int n s.length();// 右指针&#xff0c;初始值为 -1&#xff0c;相当于我们在字符串的左边界的左…...

Apache Hadoop生态部署-zookeeper单机安装

目录 查看服务架构图-服务分布、版本信息 一&#xff1a;安装前准备 1&#xff1a;zookeeper安装包选择--官网下载 2&#xff1a;zookeeper3.5.7安装包--百度网盘 二&#xff1a;安装与常用配置 2.1&#xff1a;下载解压zk安装包 2.2&#xff1a;配置修改 2.3&#xff1…...

java面试题-IO流

基础IO1.如何从数据传输方式理解IO流&#xff1f;IO流根据处理数据的类型可以分为字节流和字符流。字节流字节流以字节&#xff08;8位&#xff09;为单位读写数据。字节流主要用于读写二进制文件&#xff0c;如图片、音频、视频等。Java中的InputStream和OutputStream就是字节…...

Java性能-GC工具

GC工具(帮助分析程序性能 WE always need THAT TO help US) 开启GC日志 JDK 8 -verbose:gc 开启gc -XX:PrintGC 打印gc信息 -XX:PrintGCDetails 打印详细信息 -XX:PrintGCTimeStamps 相对于jvm启动时间0值开始 -XX:PrintGCDateStamps 日期字符串 -Xloggc:filename gc输入日志…...

复赛名单公布!2022隐私计算HACKATHON大赛火热进行中!

开放隐私计算开放隐私计算开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的服务区”。183篇原创内容公众号O…...

微信小程序的全局弹窗以及全局实例

全局组件 微信小程序组件关系中&#xff0c;父组件使用子组件需要在父组件index.json中引入子组件&#xff0c;然后在父组件页面中使用&#xff0c;这种组件的对应状态是一对一的&#xff0c;一个组件对应一个页面。如果有一个全局弹窗&#xff08;登录&#xff09;&#xff0…...

100种思维模型之诺依曼思维模型-019

生活中&#xff0c;难免总会遇到一些“大”、“笼统”、“难入手”的问题&#xff01; 如&#xff0c;前几天突然接到领导安排&#xff0c;帮忙梳理一个材料“***景区创建5A级旅游景区提升规划”。 对于一个没有学过景区提升规划、没有做过规划的我来说&#xff0c;真的挺难的…...

Python + Airtest + poco + pytest + pytest-html 实现Android App自动化测试框架

Python Airtest poco pytest pytest-html 实现Android App自动化测试框架 一、背景 为了尝试除Appium外的测试框架&#xff0c;本文将介绍基于网易的airtest框架为基础&#xff0c;配合poco及pytest实现对Android App的自动化测试。 二、框架介绍 框架集成使用airtest p…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...