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

做网站建设公司赚钱吗网站建设管理制度

做网站建设公司赚钱吗,网站建设管理制度,房屋中介网站建设方案,汽车配件外贸网站优化逻辑 把耗时较短的逻辑判断放入redsi中,比如库存是否足够以及是否一人一单,只要这样的逻辑完成,就代表一定能下单成功,我们就将结果返回给用户,然后我们再开一个线程慢慢执行队列中的信息 问题: 如何快…

优化逻辑

把耗时较短的逻辑判断放入redsi中,比如库存是否足够以及是否一人一单,只要这样的逻辑完成,就代表一定能下单成功,我们就将结果返回给用户,然后我们再开一个线程慢慢执行队列中的信息

问题:
如何快速校验一人一单以及库存是否充足

交验和下单是两个线程,如何将二者对应:
在redis操作完成之后,会返回一些信息给前端,同时将这些信息丢给异步队列执行,后续操作通过id来查询下单逻辑是否完成

![[Pasted image 20250717173831.png]]

整体流程

下单后判断是否充足只需要去redis根据key查询对应的value是否大于0 ,如果大于0再判断是否下过单,如果在set集合中没有这条数据,那么就将userId和优惠卷存入redis,将优惠卷id、用户id和订单id存入阻塞队列中,异步存储到数据库

![[Pasted image 20250717174050.png]]

stringRedisTemplate.opsForValue().set(SECKILL_STOCK_KEY + voucher.getId(), voucher.getStock().toString());
保存优惠卷并将保存秒杀的库存到Redis

-- 3.脚本业务
-- 3.1.判断库存是否充足 get stockKey
if(tonumber(redis.call('get', stockKey)) <= 0) then-- 3.2.库存不足,返回1return 1
end
-- 3.2.判断用户是否下单 SISMEMBER orderKey userId
if(redis.call('sismember', orderKey, userId) == 1) then-- 3.3.存在,说明是重复下单,返回2return 2
end
-- 3.6.发送消息到队列中, XADD stream.orders * k1 v1 k2 v2 ...
redis.call('xadd', 'stream.orders', '*', 'userId', userId, 'voucherId', voucherId, 'id', orderId)

只要>0就可以下单,然后判断用户是否下过单

命令结构
XADD stream.orders * k1 v1 k2 v2 ...
- stream.orders:目标流的名称。
- *:自动生成唯一的消息 ID(格式为 时间戳-序列号)。
- k1 v1 k2 v2 ...:消息的键值对数据。

Long result = stringRedisTemplate.execute(  SECKILL_SCRIPT, Collections.emptyList(),  voucherId.toString(), userId.toString(), String.valueOf(orderId)  
);

脚本参数
- SECKILL_SCRIPT:预定义的 Lua 脚本,处理秒杀业务逻辑(如库存校验、扣减)。
- Collections.emptyList():Lua 脚本中KEYS参数为空列表(无需键名参数)。
- 后续参数为ARGV数组,依次是voucherIduserIdorderId,供 Lua 脚本内部使用。

private static final ExecutorService SECKILL_ORDER_EXECUTOR=Executors.newSingleThreadExecutor();
定义了一个静态常量线程池,这是一个单线程的执行器,保证任务按顺序执行, 避免多线程并发处理同一用户订单导致的重复下单问题

// 类初始化后启动工作线程 
@PostConstruct 
private void init() { SECKILL_ORDER_EXECUTOR.submit(new VoucherOrderHandler()); }

@PostConstruct确保类初始化后立即启动订单处理线程,并会持续运行直到应用关闭

 private class VoucherOrderHandler implements Runnable{@Overridepublic void run() {while (true){try {// 1.获取队列中的订单信息VoucherOrder voucherOrder = orderTasks.take();// 2.创建订单handleVoucherOrder(voucherOrder);} catch (Exception e) {log.error("处理订单异常", e);}}}}

实现 Runnable 接口的类通常用于创建线程任务,可以通过 Thread 类或线程池执行。

  • orderTasks.take() 是阻塞调用,队列空时线程会等待
  • 确保订单按放入队列的顺序处理
  • 异常处理保证线程不会因异常终止
    proxy.createVoucherOrder(voucherOrder);
  • Spring 事务依赖 ThreadLocal,多线程环境下子线程无法获取主线程的事务上下文
  • 通过注入代理对象proxy调用事务方法,确保事务生效
    也就是说继承Runnable接口的类可以被在线程池中被调用
    而这里选择了在类初始化之后就调用
Spring 事务管理的工作原理
private void handleVoucherOrder(VoucherOrder voucherOrder) {// ...获取锁...try {// 通过代理对象调用事务方法proxy.createVoucherOrder(voucherOrder);} finally {// ...释放锁...}
}

Spring 的声明式事务是通过 AOP 代理实现的。当在方法上使用@Transactional注解时,Spring 会为该类创建一个代理对象,在调用带注解的方法时,代理会拦截调用并添加事务管理逻辑。
如果直接使用this.createVoucherOrder(voucherOrder),事务不会生效,因为AOP代理被绕过了,必须通过代理对象调用这个方法才能触发事务增强
因为:

  • Spring 事务是基于ThreadLocal实现的,不同线程有独立的ThreadLocal副本
  • 子线程(如线程池中的工作线程)无法获取主线程的事务上下文
  • 必须通过代理对象调用才能确保事务拦截器被触发

使用AopContext.currentProxy():在方法内部获取当前代理对象

总结

1. 为什么将库存校验和一人一单判断放在 Redis 中执行?

将高频、低耗时的校验逻辑放在 Redis 中执行,利用其内存级别的读写性能和原子性操作能力,可以快速完成资格校验。同时避免了直接访问数据库带来的网络延迟和 IO 开销,显著提升系统吞吐量。

2. 如何保证库存扣减和订单记录的原子性?

通过 Lua 脚本在 Redis 端实现原子操作。脚本中先校验库存和用户下单状态,若满足条件则直接扣减库存并记录订单信息,整个过程不可分割,有效防止超卖和重复下单问题。

3. 异步处理订单时,如何保证数据最终一致性?

采用消息队列实现异步解耦,主流程完成 Redis 操作后立即返回结果,同时将订单信息发送到阻塞队列。独立线程按顺序处理队列中的订单,确保数据最终一致性。即使处理过程中出现异常,也可通过重试机制保证订单最终入库。

4. 为什么使用单线程执行器处理订单队列?

使用单线程执行器(Executors.newSingleThreadExecutor())可以确保同一用户的订单按顺序处理,避免多线程并发处理导致的重复下单问题。同时保证了操作的顺序性,与 Redis 中的校验逻辑形成完整闭环。

5. 在多线程环境下,如何保证 Spring 事务生效?

在子线程中通过注入代理对象调用事务方法,而非直接使用this引用。因为 Spring 事务基于 AOP 代理和ThreadLocal实现,子线程无法直接获取主线程的事务上下文。通过代理对象调用可确保事务拦截器被触发,从而正确管理事务。

6. Redis 消息队列相比传统阻塞队列有什么优势?

Redis 的 Stream 数据结构支持持久化和多消费者组,相比 Java 内置的阻塞队列,具有更好的可靠性和扩展性。即使服务重启,未处理的消息也不会丢失,适合分布式系统下的异步通信场景。


文章转载自:

http://A3zi2FeK.tdxpf.cn
http://bdUaxgNr.tdxpf.cn
http://hlVIaAWo.tdxpf.cn
http://qLeNXsue.tdxpf.cn
http://Xq4j11ib.tdxpf.cn
http://jqwYr9cy.tdxpf.cn
http://rrtIWm4z.tdxpf.cn
http://P9i7PNEX.tdxpf.cn
http://pUxUWuw6.tdxpf.cn
http://Z1D2pCSe.tdxpf.cn
http://cMCgcHNe.tdxpf.cn
http://IIlhLrNm.tdxpf.cn
http://hYMrtaHR.tdxpf.cn
http://1bIvR2Lv.tdxpf.cn
http://jTvDNwtr.tdxpf.cn
http://QdJYWRko.tdxpf.cn
http://48ehP99F.tdxpf.cn
http://nc37DPUR.tdxpf.cn
http://ecsDpOwR.tdxpf.cn
http://q2pdE3Xo.tdxpf.cn
http://qsdg0qKZ.tdxpf.cn
http://ZLGLuQ8l.tdxpf.cn
http://DZOxKKyA.tdxpf.cn
http://ast6GzgZ.tdxpf.cn
http://eL7IK85P.tdxpf.cn
http://7JBs4LLN.tdxpf.cn
http://Sw7OZ7Fc.tdxpf.cn
http://qszIpPHS.tdxpf.cn
http://XbLqj6S9.tdxpf.cn
http://1ylBMjVC.tdxpf.cn
http://www.dtcms.com/wzjs/691352.html

相关文章:

  • 黄骅港教育网站如何做seo
  • 做网站用哪个版本的eclipse集团网站制作
  • 合肥营销网站建设联系方式网站收录提交入口官网
  • wordpress扫描附件到新浪图床为企业做网站建设优化小程序包年竞价
  • 织梦网站wap网站建设项目合同
  • 网站的域名空间个人网站如何提高访问量
  • 邢台123信息网汽车seo是什么意思
  • 重庆网站seo方法企业查询网页版
  • wordpress安全整站优化加盟
  • 长沙城乡建设网站首页wordpress的网站
  • 网页美工设计网站wordpress会员认证
  • 做企业网站 需要注意的微小店
  • 国家精品课程建设工作网站四川建设工程网
  • 做网站挣钱的人有哪些好的响应式网站有哪些
  • cn域名建设网站需要备案吗旅游网站建设要如何做
  • 网站登陆界面怎么做商场大型话题活动策划网站
  • 浙江网站建设广告语做网站好一点的公司
  • 网站企业备案和个人备案的区别h5页面制作结论和心得
  • 做网站一般用什么配置的电脑什么是推广
  • 宜春做网站国家关于网站信息建设管理文件
  • 马鞍山哪里做网站推广赚钱平台
  • 石家庄电商网站网络运维工程师周报
  • 网站没内容网页布局设计图
  • 大连做公司网站百合怎么做网站
  • 番禺网站开发哪家强网站开发实训h5总结
  • 济南网站建设策划方案外包工是临时工吗
  • 上海网站建设思创ui设计师是什么
  • iis添加网站的物理路径通州设计网站建设
  • 芜湖市网站建设门户网站的建设费用
  • 廉江网站开发公司重庆企业网站推广费用