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

黑马Redis(三)黑马点评项目

优惠卷秒杀

一、全局唯一ID

基于Redis实现全局唯一ID的策略:

@Component
@RequiredArgsConstructor
public class RedisIdWorker {private static final Long BEGIN_TIMESTAMP=1713916800L;private static final int COUNT_BITS = 32;@Resourceprivate final StringRedisTemplate stringRedisTemplate;public long nextId(String keyPrefix){//1.生成时间戳LocalDateTime now =LocalDateTime.now();long nowSecond = now.toEpochSecond(ZoneOffset.UTC);long timestamp = nowSecond - BEGIN_TIMESTAMP;//2.生成序列号//2.1. 获取当天的日期String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));Long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);//3.拼接并返回  时间戳 左移32位  随后与  count 或运算 实现拼接return timestamp<<COUNT_BITS | count;}}

二、实现优惠卷秒杀下单

@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {@Resourceprivate ISeckillVoucherService seckillVoucherService;@Resourceprivate RedisIdWorker redisIdWorker;@Override@Transactionalpublic Result seckillVoucher(Long voucherId) {//1.查询优惠卷SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())){//开始时间在当前时间之后--未开始return Result.fail("秒杀尚未开始!");}//3.判断秒杀是否结束if (voucher.getEndTime().isBefore(LocalDateTime.now())){//结束时间在当前时间之前 --  已经结束return Result.fail("秒杀已经结束!");}//4.库存判断if (voucher.getStock() < 1){//库存不足return Result.fail("库存不足!");}//5.扣减库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1").eq("voucher_id", voucherId).update();if(!success){//扣减失败return Result.fail("库存不足!");}//6.创建订单VoucherOrder voucherOrder = new VoucherOrder();//6.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);//6.2.用户idLong userId = UserHolder.getUser().getId();voucherOrder.setUserId(userId);//6.3.代金卷idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);//7.返回订单idreturn Result.ok(voucherOrder);}
}

超卖问题:

解决问题--加锁:

 乐观锁:

实现--版本号法:

实现--CAS法:

使用对应数据代替版本号进行查询

 业务修改:

乐观锁的判断只针对库存是否>0,如果库存发现已经=0,则终止

        boolean success = seckillVoucherService.update().setSql("stock = stock - 1").eq("voucher_id", voucherId).gt("stock",0)//乐观锁,在进行扣减前查询数据库中数据是否发生改变.update();

 

三、实现一人一单

 //5.一人一单Long userId = UserHolder.getUser().getId();//5.1.查询订单Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();if(count>0){//5.2.判断是否存在//说明已经下过单了return Result.fail("该用户已经购买过一次!");}

还是有多单成功 

解决办法--加锁:

版本1(优缺点):

    @Overridepublic Result seckillVoucher(Long voucherId) {//1.查询优惠卷SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())){//开始时间在当前时间之后--未开始return Result.fail("秒杀尚未开始!");}//3.判断秒杀是否结束if (voucher.getEndTime().isBefore(LocalDateTime.now())){//结束时间在当前时间之前 --  已经结束return Result.fail("秒杀已经结束!");}//4.库存判断if (voucher.getStock() < 1){//库存不足return Result.fail("库存不足!");}return  creatVoucherOrder(voucherId);}@Transactionalpublic  Result creatVoucherOrder(Long voucherId){//5.一人一单Long userId = UserHolder.getUser().getId();synchronized(userId.toString().intern()){//5.1.查询订单Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();if(count>0){//5.2.判断是否存在//说明已经下过单了return Result.fail("该用户已经购买过一次!");}//6.扣减库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1").eq("voucher_id", voucherId).gt("stock",0)//乐观锁,在进行扣减前查询数据库中数据是否发生改变.update();if(!success){//扣减失败return Result.fail("库存不足!");}//7.创建订单VoucherOrder voucherOrder = new VoucherOrder();//7.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);//7.2.用户idvoucherOrder.setUserId(userId);//7.3.代金卷idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);//8.返回订单idreturn Result.ok(voucherOrder);}}

改进版:

    @Overridepublic Result seckillVoucher(Long voucherId) {//1.查询优惠卷SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())){//开始时间在当前时间之后--未开始return Result.fail("秒杀尚未开始!");}//3.判断秒杀是否结束if (voucher.getEndTime().isBefore(LocalDateTime.now())){//结束时间在当前时间之前 --  已经结束return Result.fail("秒杀已经结束!");}//4.库存判断if (voucher.getStock() < 1){//库存不足return Result.fail("库存不足!");}Long userId = UserHolder.getUser().getId();synchronized(userId.toString().intern()) {return creatVoucherOrder(voucherId);}}@Transactionalpublic  Result creatVoucherOrder(Long voucherId){//5.一人一单Long userId = UserHolder.getUser().getId();//5.1.查询订单Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();if(count>0){//5.2.判断是否存在//说明已经下过单了return Result.fail("该用户已经购买过一次!");}//6.扣减库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1").eq("voucher_id", voucherId).gt("stock",0)//乐观锁,在进行扣减前查询数据库中数据是否发生改变.update();if(!success){//扣减失败return Result.fail("库存不足!");}//7.创建订单VoucherOrder voucherOrder = new VoucherOrder();//7.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);//7.2.用户idvoucherOrder.setUserId(userId);//7.3.代金卷idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);//8.返回订单idreturn Result.ok(voucherOrder);}

不能将锁加在方法上:会造成串行操作,多个用户不能并行调用该方法

因此将锁加载用户id上面,根据用户id不同的特点来实现多个用户并行

注意1:

用户id调用ToString方法时,底层代码仍然是通过new 实现,因此即便同一个用户id仍然会有不同的toString值,因此调用 intern( )  方法,通过往字符串池中寻找是否存在对应的字符串,避免new导致的不同。

注意2:

两个版本的锁位置不一样,前者的锁会出现以下并发安全问题:当锁中内容执行完毕释放锁之后,事务可能还没有提交,此时具有相同id的线程可能会重新调用方法,导致问题进而使得事务失败回滚

因此锁在进阶版中加入到了调用这个方法的部分(既锁住了整个函数,又没有影响函数被其他线程调用)

新问题:

可以看到进阶版代码中虽然通过悲观锁预防了并发安全问题,但是也引出了另一个问题 ,在进阶代码中 createVoucherOrder 方法的@Transactional 注释并不会生效:

原因: 代码中的 return creatVoucherOrder(voucherId);

      等价于  return   this.creatVoucherOrder(voucherId);  即 调用的是整个Service实现类的方法(方法属性),而不是代理对象(方法本身),spring实现事务是通过对这个方法进行动态代理,用代理对象去实现事务处理,因此如果通过service实现类调用方法无法实现事务功能。

最终 版本:

 引入依赖:

        <!--aspectj--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency>

配置启动项注释--开启暴露代理对象:

@EnableAspectJAutoProxy(exposeProxy = true) //设置暴露代理对象 -- true
@MapperScan("com.hmdp.mapper")
@SpringBootApplication
public class HmDianPingApplication {public static void main(String[] args) {SpringApplication.run(HmDianPingApplication.class, args);}}
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {@Resourceprivate ISeckillVoucherService seckillVoucherService;@Resourceprivate RedisIdWorker redisIdWorker;@Overridepublic Result seckillVoucher(Long voucherId) {//1.查询优惠卷SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())){//开始时间在当前时间之后--未开始return Result.fail("秒杀尚未开始!");}//3.判断秒杀是否结束if (voucher.getEndTime().isBefore(LocalDateTime.now())){//结束时间在当前时间之前 --  已经结束return Result.fail("秒杀已经结束!");}//4.库存判断if (voucher.getStock() < 1){//库存不足return Result.fail("库存不足!");}Long userId = UserHolder.getUser().getId();synchronized(userId.toString().intern()) {//需要拿到当前对象的代理对象//spring就能通过代理对象来进行事务管理IVoucherOrderService proxy = (IVoucherOrderService)AopContext.currentProxy();return proxy.reatVoucherOrder(voucherId);}}@Transactionalpublic  Result creatVoucherOrder(Long voucherId){//5.一人一单Long userId = UserHolder.getUser().getId();//5.1.查询订单Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();if(count>0){//5.2.判断是否存在//说明已经下过单了return Result.fail("该用户已经购买过一次!");}//6.扣减库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1").eq("voucher_id", voucherId).gt("stock",0)//乐观锁,在进行扣减前查询数据库中数据是否发生改变.update();if(!success){//扣减失败return Result.fail("库存不足!");}//7.创建订单VoucherOrder voucherOrder = new VoucherOrder();//7.1.订单idlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);//7.2.用户idvoucherOrder.setUserId(userId);//7.3.代金卷idvoucherOrder.setVoucherId(voucherId);save(voucherOrder);//8.返回订单idreturn Result.ok(voucherOrder);}
}

 一人一单的并发安全问题:

同一个用户发送两个请求,在并发的两个服务中都会接收请求,不会锁住(锁只会在一个虚拟环境中生效)

 四、分布式锁实现一人一单

分布式锁:

分布式锁的实现:

 基于Redis的分布式锁:

 案例--基于Redis实现分布式锁初级版本:

package com.hmdp.utils;public interface ILock {/*** 尝试获取锁* @param* @return*/boolean tryLock(Long timeoutSec);/*** 释放锁* */void unlock();
}
public class SimpleRedisLock implements ILock{private StringRedisTemplate stringRedisTemplate;private String name;private static final String KEY_PREFIX= "lock:";public SimpleRedisLock(String name,StringRedisTemplate stringRedisTemplate){this.stringRedisTemplate=stringRedisTemplate;this.name=name;}@Overridepublic boolean tryLock(Long timeoutSec) {//获取线程标识long threadId = Thread.currentThread().getId();//获取锁Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId + "", timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success); //预防空指针错误}@Overridepublic void unlock() {stringRedisTemplate.delete(KEY_PREFIX+name);}
}
    @Overridepublic Result seckillVoucher(Long voucherId) {//1.查询优惠卷SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())){//开始时间在当前时间之后--未开始return Result.fail("秒杀尚未开始!");}//3.判断秒杀是否结束if (voucher.getEndTime().isBefore(LocalDateTime.now())){//结束时间在当前时间之前 --  已经结束return Result.fail("秒杀已经结束!");}//4.库存判断if (voucher.getStock() < 1){//库存不足return Result.fail("库存不足!");}Long userId = UserHolder.getUser().getId();//创建锁对象SimpleRedisLock lock= new SimpleRedisLock("order:"+userId,stringRedisTemplate);//获取锁boolean isLock = lock.tryLock(1200L);//判断是否获取锁成功if (!isLock){//获取失败,返回错误或者重试return Result.fail("不允许重复下单!");}try {//需要拿到当前对象的代理对象//spring就能通过代理对象来进行事务管理IVoucherOrderService proxy = (IVoucherOrderService)AopContext.currentProxy();return proxy.creatVoucherOrder(voucherId);} finally {//释放锁lock.unlock();}}

潜在问题:

解决办法--增加释放锁的标识: 

案例--改进的Redis分布式锁:

public class SimpleRedisLock implements ILock{private StringRedisTemplate stringRedisTemplate;private String name;private static final String KEY_PREFIX= "lock:";private static final String ID_PREFIX = UUID.randomUUID().toString(true)+"-";public SimpleRedisLock(String name,StringRedisTemplate stringRedisTemplate){this.stringRedisTemplate=stringRedisTemplate;this.name=name;}@Overridepublic boolean tryLock(Long timeoutSec) {//获取线程标识String threadId =ID_PREFIX + Thread.currentThread().getId();//获取锁Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success); //预防空指针错误}@Overridepublic void unlock() {//获取线程标识String threadId=ID_PREFIX+Thread.currentThread().getId();//获取锁的中标识String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);//判断是否一致if (id.equals(threadId)){//一致--释放锁stringRedisTemplate.delete(KEY_PREFIX+name);}}
}

潜在问题:

 原因: 判断锁标识 和 释放锁 不具有原子性  是两个操作

解决办法---Lua脚本:

Lua 教程 | 菜鸟教程

 执行脚本:

带参数脚本:

Lua语言数组的下标从1开始 

 基于Lua脚本修改释放锁业务:

编写Lua脚本:


-- 获取锁中的线程标识 get key
local id = redis.call('get',KEYS[1])
-- 比较线程标识与锁中的标识是否一致
if(redis.call('get',KEYS[1]) == ARGV[1]) then-- 释放锁 del keyreturn redis.call('del', KEYS[1])
end
return 0

使用Java执行Lua脚本:

    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));UNLOCK_SCRIPT.setResultType(Long.class);}@Overridepublic void unlock(){//调用Lua脚本stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name),ID_PREFIX+Thread.currentThread().getId());}

潜在问题: 

解决办法---Redisson

五、Redisson

Redisson | Valkey & Redis Java client. Ultimate Real-Time Data Platform

GitHub - redisson/redisson: Redisson - Valkey and Redis Java client. Real-Time Data Platform. Sync/Async/RxJava/Reactive API. Over 50 Valkey and Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Spring, Tomcat, Scheduler, JCache API, Hibernate, RPC, local cache..

Redisson入门:

        <!--Redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version></dependency>


@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient(){//配置Config config = new Config();config.useSingleServer().setAddress("redis://192.168.50.129:6379").setPassword("123");//创建RedissonClient对象return Redisson.create(config);}
}
    @Resourceprivate RedissonClient redissonClient;

Redisson可重入锁原理:

可重入:一个线程里面允许多次获取锁 

流程对应的Lua脚本:

获取锁

 释放锁:

 Redisson分布式锁原理:

主从一致性问题:

解决办法: 

其他线程需要在所有的redis节点中都获取到锁才能进行

 六、分布式锁总结

相关文章:

黑马Redis(三)黑马点评项目

优惠卷秒杀 一、全局唯一ID 基于Redis实现全局唯一ID的策略&#xff1a; Component RequiredArgsConstructor public class RedisIdWorker {private static final Long BEGIN_TIMESTAMP1713916800L;private static final int COUNT_BITS 32;Resourceprivate final StringRed…...

dedecms织梦arclist标签noflag属性过滤多个参数

织梦dedecms系统arclist标签noflag属性默认是只能过滤一个参数&#xff0c;比如过滤推荐是noflagc&#xff0c;过滤有图片的文章是noflagc&#xff0c;在模板制作过程中&#xff0c;有时候我们为了seo和避免重复&#xff0c;需要过滤多个参数。今天小编就来跟大家讲讲织梦dedec…...

Jira、PingCode、Redmine等18款缺陷管理工具对比评测

本文主要介绍了以下&#xff1a;1. PingCode; 2. Worktile; 3. Jira; 4. Bugzilla; 5. TAPD; 6. 码云; 7. Redmine; 8. Trac; 9. 蓝鲸智云; 10. 阿里云效等等18款缺陷管理工具。 在现代软件开发和项目管理中&#xff0c;缺陷管理工具扮演着至关重要的角色。随着企业对软件质量的…...

京东以图搜图(拍立淘)API接口返回参数详解

京东以图搜图&#xff08;拍立淘&#xff09;API接口的返回参数通常以结构化JSON格式呈现&#xff0c;涵盖商品基础信息、相似度评分、库存状态及扩展字段&#xff0c;以下为关键参数详解及使用建议&#xff1a; 一、核心返回参数解析 状态标识类 status&#xff1a;请求状态…...

LSTM+KNN - 多元数据异常检测 !

大家好!我是我不是小 upper~ 今天想和大家分享一个超实用的案例:如何通过 LSTM 与 KNN 实现多元数据异常检测。 想象一下,在工厂的智能化监控场景中,各类传感器实时采集着温度、湿度、压力等海量数据。我们的目标,就是从中精准识别出设备潜在故障等异常情况。 LSTM 作为时…...

OpenHarmony之电源管理子系统公共事件定义

OpenHarmony之电源管理子系统公共事件定义 电源管理子系统面向应用发布如下系统公共事件&#xff0c;应用如需订阅系统公共事件&#xff0c;请参考公共事件接口文档。 COMMON_EVENT_BATTERY_CHANGED 表示电池充电状态、电平和其他信息发生变化的公共事件的动作。 值&#x…...

angular 实现可编辑可选择复制的表格

这个实现的核心就是ag-grid 当然有类似的库就不必多说&#xff0c;React, Vue和纯h5类似。简单贴一下代码 1.首先是h5部分&#xff0c;就一个id为supply-chain-material-grid-table的div&#xff0c;记住要设置高度 <div class"dki-supply-chain-page-body">…...

组织用户数统计实现

# 完整的组织用户数统计实现 完整的组织用户数统计实现&#xff0c;包括模拟SQL查询、完整的Java代码实现以及详细解释。 ## 1. 模拟SQL查询 假设我们有一个组织表(organization)和用户表(user)&#xff0c;以下是模拟查询SQL&#xff1a; sql -- 获取各组织及其用户数量&a…...

天机学堂day10作业,完善兑换优惠券功能

UserCouponServiceImpl /*** 兑换码兑换优惠券* param code*/TransactionalOverridepublic void exchangeCoupon(String code) {//1、校验code是否为空if (StringUtils.isBlank(code)) {throw new BadRequestException("非法参数&#xff01;");}//2、解析兑换码&…...

Python编程的真谛:超越语法,理解编程本质

你是否也曾陷入这样的误区&#xff1a;学了无数的 Python 语法、刷了几十套题&#xff0c;写起代码却仍然卡顿、举步维艰&#xff1f;这时候你才发现&#xff0c;真正阻碍进步的&#xff0c;从不是语法&#xff0c;而是你对“编程本质”的理解。 如果你只是死记硬背Python的语…...

C语言 函数补充

目录 static和extern函数 1.static和extern函数 static和extern都是C语言中的关键字 static 是 静态的 的意思&#xff0c;可以用来: - 修饰局部变量- 修饰全局变量- 修饰函数 extern 是用来声明外部符号的。 在讲解 static 和 extern 之前再讲一下: 作用域和生命周期。 …...

【AI图像创作变现】04实操路径—插图/绘本/创意图集

引言 如果说头像是“一个角色的起点”&#xff0c;那么插图、绘本和图集就是“这个角色能走多远”。相比于头像这种单图任务&#xff0c;插图类创作更强调批量性、叙事性与风格统一性&#xff0c;它既可以承载故事&#xff0c;也可以构成一套完整的内容产品结构。 这类任务特…...

Lesar: 面向 Lustre/Scade 语言的形式化模型检查工具

在《同步反应式系统》的第一课中&#xff0c;介绍了同步数据流语言 Lustre 生态中的形式化模型检查器 Lesar 的用法。Lesar 可对 lustre v4 语言以及 Scade 语言中部分数据流核心特性进行模型检查。 Lesar 介绍 Lesar 是 Verimag 研发维护的形式化方法模型检查工具。该工具的理…...

告别 “幻觉” 回答:RAG 中知识库与生成模型的 7 种对齐策略

一、引言 大语言模型&#xff08;LLM&#xff09;在文本生成领域展现出惊人能力&#xff0c;但 “幻觉” 问题&#xff08;生成虚构或偏离事实的内容&#xff09;始终是落地应用的核心挑战。检索增强生成&#xff08;RAG&#xff09;通过将外部知识库与 LLM 结合&#xff0c;形…...

【Web应用服务器_Tomcat】一、Tomcat基础与核心功能详解

在 Java Web 应用开发领域&#xff0c;Apache Tomcat 是一座不可或缺的基石。作为一款开源、轻量级的 Servlet 容器和 Web 服务器&#xff0c;Tomcat 以其稳定可靠、易于部署和高度可定制性&#xff0c;被广泛应用于各类 Web 应用的部署与运行。 一、Tomcat 简介​ Tomcat 是…...

Cesium实现地形可视域分析

Cesium实现可视化分析 一、地形可视域主要实现技术(Ray + 地形碰撞检测) Cesium 本身的 Ray 类可以用来执行非常精确的射线检测,我们可以结合地形高度(sample)来逐点检测光线是否与 terrain 相交,从而判断是否可见。 1.1 优势 实时判断每条射线是否被 terrain 遮挡地形…...

Java—— 常见API介绍 第五期

JDK8以后新增的时间相关类 Date类ZoneId&#xff1a;时区Instant&#xff1a;时间戳ZoneDateTime&#xff1a;带时区的时间 日期格式化类 SimpleDateFormat DateTimeFormatter&#xff1a;用于时间的格式化和解析 日历类 Calendar LocalDate&#xff1a;年、月、日LocalTime…...

ViewPager FragmentPagerAdapter在系统杀死应用后重建时UI不刷新的问题

解决方案 通过重写getItemId方法&#xff0c;返回Fragment的hashCode&#xff1a; Override public long getItemId(int position) {/*** 恢复状态重建时&#xff0c;新的 Fragment 不刷新UI。* 原因&#xff1a;instantiateItem 中通过 mFragmentManager.findFragmentByTag(…...

第3讲、大模型如何理解和表示单词:词嵌入向量原理详解

1. 引言 大型语言模型&#xff08;Large Language Models&#xff0c;简称LLM&#xff09;如GPT-4、Claude和LLaMA等近年来取得了突破性进展&#xff0c;能够生成流畅自然的文本、回答复杂问题、甚至编写代码。但这些模型究竟是如何理解人类语言的&#xff1f;它们如何表示和处…...

关于STM32f1新建工程

创建文件夹 首先创建一个存放工程的文件夹&#xff0c;建议建立在D&#xff0c;E盘 新建工程 在kiel5里面 找到刚刚建立的文件夹&#xff0c;然后在此文件夹里面新建一个文件夹用来存放本次工程&#xff0c;文件夹可以根据工程内容所编写&#xff0c;然后给自己工程也就是…...

Linux:进程间通信---匿名管道

文章目录 1. 进程间通信1.1 什么是进程间通信&#xff1f;1.2 为什么进程要进行进程间通信&#xff1f;1.3 怎么实现进程间通信&#xff1f; 2. 匿名管道2.1 匿名管道的原理2.2 匿名管道的系统接口2.3 匿名管道的使用2.4 匿名管道的运用场景 序&#xff1a;在上一篇文章中我们知…...

python代做推荐系统深度学习知识图谱c#代码代编神经网络算法创新

以下是针对推荐系统、深度学习、知识图谱和神经网络算法创新的代码框架及开发建议&#xff0c;适用于C#和Python的跨语言协作项目。以下内容分为几个部分&#xff0c;涵盖技术选型、代码示例和创新方向。 1. 推荐系统&#xff08;Python C#&#xff09; Python部分&#xff0…...

【动手学大模型开发】VSCode 连接远程服务器

Visual Studio Code&#xff08;VSCode&#xff09;是一款由微软开发的免费、开源的现代化代码编辑器。它以其轻量级、高性能和广泛的编程语言支持而受到开发者的青睐。VSCode 的核心特点包括&#xff1a; 跨平台&#xff1a;支持 Windows、macOS 和 Linux 操作系统。扩展市场…...

PostgreSQL 漏洞信息详解

PostgreSQL 漏洞信息详解 PostgreSQL 作为一款开源关系型数据库&#xff0c;其安全漏洞会被社区及时发现和修复。以下是 PostgreSQL 漏洞相关的重要信息和资源。 一、主要漏洞信息来源 1. 官方安全公告 PostgreSQL 安全信息页面&#xff1a;https://www.postgresql.org/sup…...

华为L410上制作内网镜像模板:在客户端配置模板内容

华为L410上制作内网镜像模板&#xff1a;在客户端配置模板内容 在本教程中&#xff0c;我们将继续在华为L410上配置内网镜像模板&#xff0c;具体介绍如何在客户端设置以便于在首次开机时自动安装软件。我们将主要使用WeChat作为示例。 1. 制作镜像模板&#xff0c;开启 rc.l…...

分布式队列对消息语义的处理

在分布式系统中&#xff0c;消息的处理语义&#xff08;Message Processing Semantics&#xff09;是确保系统可靠性和一致性的关键。有三种语义&#xff1a; 在分布式系统中&#xff0c;消息的处理语义&#xff08;Message Processing Semantics&#xff09;是确保系统可靠性和…...

《免费开放”双刃剑:字节跳动Coze如何撬动AI生态霸权与暗涌危机?》

战略动机分析 降低技术门槛为数据采集接口 Coze平台宣称**“30秒无代码生成AI Bot”&#xff0c;大幅降低了企业开发AI应用的技术门槛。任何不懂编程的业务人员都可以通过可视化流程和提示词&#xff0c;在半分钟内搭建聊天机器人或智能代理。这种极低门槛意味着更多企业和个人…...

AI 开发工具提示词集体开源!解锁 Cursor、Cline、Windsurf 等工具的核心逻辑

✨ 前言&#xff1a;提示词&#xff0c;AI 编程工具的灵魂 随着大模型编程能力的迅速提升&#xff0c;AI 编程工具如雨后春笋般涌现&#xff0c;涵盖了从代码编辑器&#xff08;如 Cursor、Windsurf、Cline&#xff09;到应用生成服务&#xff08;如 Lovable、Bolt.new、V0&am…...

MYSQL 常用字符串函数 和 时间函数详解

一、字符串函数 1、​CONCAT(str1, str2, …) 拼接多个字符串。 SELECT CONCAT(Hello, , World); -- 输出 Hello World2、SUBSTRING(str, start, length)​​ 或 ​SUBSTR() 截取字符串。 SELECT SUBSTRING(MySQL, 3, 2); -- 输出 SQ3、LENGTH(str)​​ 与 ​CHAR_LENGTH…...

Ubuntu 下 Nginx 1.28.0 源码编译安装与 systemd 管理全流程指南

一、环境与依赖准备 为确保编译顺利&#xff0c;我们首先更新系统并安装必要的编译工具和库&#xff1a; sudo apt update sudo apt install -y build-essential \libpcre3 libpcre3-dev \zlib1g zlib1g-dev \libssl-dev \wgetbuild-essential&#xff1a;提供 gcc、make 等基…...

线程怎么创建?Java 四种方式一网打尽

&#x1f680; Java 中线程的 4 种创建方式详解 创建方式实现方式是否推荐场景说明1. 继承 Thread 类class MyThread extends Thread❌ 不推荐简单学习、单线程场景2. 实现 Runnable 接口class MyRunnable implements Runnable✅ 推荐更适合多线程共享资源3. 实现 Callable 接…...

高效使用DeepSeek对“情境+ 对象 +问题“型课题进行开题!

目录 思路"情境 对象 问题"型 课题选题的类型有哪些呢&#xff1f;这要从课题题目的构成说起。通过对历年来国家社会科学基金立项项目进行分析&#xff0c;小编发现&#xff0c;课题选题类型非常丰富&#xff0c;但一般是围绕限定词、研究对象和研究问题进行不同的组…...

【GCC bug】libstdc++.so.6: version `GLIBCXX_3.4.29‘ not found

在 conda 环境安装 gcc/gxx 之后&#xff0c;运行开始遇到了以下的报错 File "/mnt/data/home/xxxx/miniforge3/envs/GAGAvatar/lib/python3.12/site-packages/google/protobuf/internal/wire_format.py", line 13, in <module>from google.protobuf import de…...

python卸载报错:No Python 3.12 installation was detected已解决

问题背景 在卸载Python 3.12.5时&#xff0c;遇到了一个棘手的问题&#xff1a;运行安装包python.exe点击Uninstall后&#xff0c;系统提示No Python 3.12 installation was detected. 尝试了网上各种方法&#xff08;包括注册表清理、修复repair&#xff0c;卸载unins…...

【Hive入门】Hive分区与分区表完全指南:从原理到企业级实践

引言 在大数据时代&#xff0c;高效管理海量数据成为企业面临的核心挑战。Hive作为Hadoop生态系统中最受欢迎的数据仓库解决方案&#xff0c;其分区技术是优化数据查询和管理的关键手段。本文将全面解析Hive分区技术的原理、实现方式及企业级最佳实践&#xff0c;帮助您构建高性…...

AI之FastAPI+ollama调用嵌入模型OllamaBgeEmbeddings

以下是对该 FastAPI 代码的逐行解析和详细说明: 代码结构概览 from fastapi import Depends # 导入依赖注入模块def get_embedder():return OllamaBgeEmbeddings(base_url="http://ollama-cluster:11434",timeout=30,max_retries=5)@app.post("/embed")…...

RK3588芯片NPU的使用:yolov8-pose例子图片检测在安卓系统部署与源码深度解析(rknn api)

一、本文的目标 将yolo8-pose例子适配安卓端,提供选择图片后进行姿态识别功能。通过项目学习源码和rknn api。二、开发环境说明 主机系统:Windows 11目标设备:搭载RK3588芯片的安卓开发板核心工具:Android Studio Koala | 2024.1.1 Patch 2,NDK 27.0三、适配(迁移)安卓 …...

【HTTP/3:互联网通信的量子飞跃】

HTTP/3&#xff1a;互联网通信的量子飞跃 如果说HTTP/1.1是乡村公路&#xff0c;HTTP/2是现代高速公路系统&#xff0c;那么HTTP/3就像是一种革命性的"传送门"技术&#xff0c;它彻底重写了数据传输的底层规则&#xff0c;让信息几乎可以瞬间抵达目的地&#xff0c;…...

2024 年:Kubernetes 包管理的新前沿

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;历代文学&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编程&#xff0c;高并发设计&#xf…...

SIEMENS PLC 程序 GRAPH 程序解读 车型入库

1、程序载图1 2、程序截图2 3、程序解释 这是一个基于西门子 GRAPH 编程的车型 1 入库顺序控制流程图&#xff0c;通过状态机结构&#xff08;状态框 S 与转移条件 T&#xff09;描述完整工作流程&#xff0c;具体如下&#xff1a; 整体流程概述 初始化&#xff1a;从 S1&am…...

c++11新特性随笔

1.统一初始化特性 c98中不支持花括号进行初始化&#xff0c;编译时会报错&#xff0c;在11当中初始化可以通过{}括号进行统一初始化。 c98编译报错 c11: #include <iostream> #include <set> #include <string> #include <vector>int main() {std:…...

微信小程序文章管理系统开发实现

概述 在内容为王的互联网时代&#xff0c;高效的文章管理系统成为各类平台的刚需。幽络源平台今日分享一款基于SSM框架开发的微信小程序文章管理系统完整解决方案&#xff0c;该系统实现了多角色内容管理、智能分类、互动交流等功能。 主要内容 一、用户端功能模块 ​​多角…...

3种FSC标签你用对了吗?

如果你留意过产品上的FSC小树标识&#xff0c;也许会发现它们很相似但又各不相同。 根据产品使用的FSC认证材料的不同比例&#xff0c;共有三种不同类型的FSC标签&#xff1a; 1、FSC 100% 所有使用的材料均来自负责任管理的FSC认证森林。 标签文本为&#xff1a;“ From well-…...

NLP高频面试题(五十四)——深度学习归一化详解

引言:大模型训练中的归一化需求 随着人工智能技术的快速发展,**大模型(Large Language Models, LLMs)**的规模与能力都呈爆发式增长。诸如GPT-4、BERT、PaLM等模型参数量从最初的百万级到如今的千亿、万亿级别,训练难度和效率问题日益显著。在超大模型的训练过程中,梯度…...

第5.5章:ModelScope-Agent:支持多种API无缝集成的开源框架

5.5.1 ModelScope-Agent概述 ModelScope-Agent&#xff0c;由阿里巴巴旗下ModelScope社区开发&#xff0c;是一个开源的、模块化的框架&#xff0c;旨在帮助开发者基于大型语言模型快速构建功能强大、灵活性高的智能代理。它的核心优势在于支持与多种API和外部系统的无缝集成&…...

筑牢数字防线:商城系统安全的多维守护策略

一、构建网络安全防护屏障​ 网络安全是商城系统安全的第一道防线。企业应采用先进的防火墙技术&#xff0c;实时监控和过滤进出网络的流量&#xff0c;阻止非法访问和恶意攻击。入侵检测与防御系统&#xff08;IDS/IPS&#xff09;也是不可或缺的安全组件&#xff0c;它能够及…...

PTC加热片详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 三、程序设计 main文件 jdq.h文件 jdq.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 PTC是正温度系数热敏电阻的英文简称&#xff0c;其电阻值随着PTC热敏电阻本体温度的升高呈现阶跃性的增加。温度越高&…...

OpenCV 图形API(64)图像结构分析和形状描述符------在图像中查找轮廓函数findContours()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在二值图像中查找轮廓。 该函数使用[253]中的算法从二值图像检索轮廓。轮廓是形状分析以及对象检测和识别的有用工具。请参阅 OpenCV 示例目录中…...

GIS开发笔记(15)基于osg和osgearth实现三维地图上添加路网数据(矢量shp)

一、实现效果 二、实现原理 准备路网图层数据(.shp、.prj、.dbf、.cpg),设置样式、贴地,添加图层到地球节点。 三、参考代码 {// 获取当前可执行程序所在的目录QString exeDir = QCoreApplication::applicationDirPath();// 构造 Shapefile 文件的完整路径...

Golang日志模块之xlog

基于douyu的xlog 依赖 github.com/douyu/jupiter/pkg/xlog go.uber.org/zap gopkg.in/natefinch/lumberjack.v2log相关结构体 types/log.go type Log struct {Env string toml:"env"InfoLogFileName string toml:"infoLogFileName"Error…...