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

企业网站的设计公司百度广告平台

企业网站的设计公司,百度广告平台,群晖wordpress图片,黔西南建设厅网站秒杀系统流程图 秒杀系统关键点 高并发处理: 使用网关(如 Nginx)进行流量限流,避免过载。分布式锁或 Redis 原子操作控制并发。 活动状态检查: Redis 存储活动状态(如 seckill:activity:1:status),快速…

秒杀系统流程图

在这里插入图片描述

秒杀系统关键点

  1. 高并发处理:
  • 使用网关(如 Nginx)进行流量限流,避免过载。
  • 分布式锁或 Redis 原子操作控制并发。
  1. 活动状态检查:
  • Redis 存储活动状态(如 seckill:activity:1:status),快速判断活动是否进行中。
  1. 用户资格校验:
  • Redis Set 记录参与用户(如 seckill:activity:1:users),检查是否重复参与。
  • 示例: SADD seckill:activity:1:users user123 和 SISMEMBER。
  1. 库存扣减(Redis Lua 脚本):
  • 为什么用 Lua 脚本?
    • 保证原子性,避免并发超卖。
    • 减少网络往返,提高性能。
  • Redis Key: seckill:activity:1:stock(库存)。
  • Lua 脚本示例:
local stock_key = KEYS[1]
local current_stock = tonumber(redis.call('GET', stock_key) or 0)
if current_stock <= 0 thenreturn -1  -- 库存不足
end
redis.call('DECR', stock_key)
return current_stock - 1  -- 返回剩余库存
  • Java 调用 Lua 脚本(Spring Boot + Redis):
@Autowired
private StringRedisTemplate redisTemplate;public boolean deductStock(String activityId) {String stockKey = "seckill:activity:" + activityId + ":stock";String script = "local stock_key = KEYS[1] " +"local current_stock = tonumber(redis.call('GET', stock_key) or 0) " +"if current_stock <= 0 then return -1 end " +"redis.call('DECR', stock_key) " +"return current_stock - 1";Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(stockKey));return result != null && result >= 0;
}
  1. 订单生成:
  • 异步队列(如 RabbitMQ、Kafka)处理订单生成,减轻数据库压力。
  • 示例: 将 {userId, activityId, timestamp} 发送到队列。
  1. 数据库写入:
  • 异步任务消费队列,批量插入订单到 MySQL。
  • 避免实时写库导致瓶颈。
  1. 防超卖:
  • Redis Lua 脚本确保库存不减为负。
  • 数据库加乐观锁(如 UPDATE stock SET count = count - 1 WHERE id = ? AND count > 0)。
  1. 返回响应:
  • 扣减成功后立即返回“秒杀成功”,后续操作异步完成。

完整流程伪代码

@RestController
public class SeckillController {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate RabbitTemplate rabbitTemplate;@PostMapping("/seckill/{activityId}")public String seckill(@PathVariable String activityId, @RequestParam String userId) {// 1. 检查活动状态String status = redisTemplate.opsForValue().get("seckill:activity:" + activityId + ":status");if (!"ongoing".equals(status)) {return "活动未开始或已结束";}// 2. 检查用户资格if (redisTemplate.opsForSet().isMember("seckill:activity:" + activityId + ":users", userId)) {return "已参与秒杀";}// 3. 扣减库存 (Lua 脚本)if (!deductStock(activityId)) {return "库存不足";}// 4. 标记用户参与redisTemplate.opsForSet().add("seckill:activity:" + activityId + ":users", userId);// 5. 异步生成订单rabbitTemplate.convertAndSend("seckill-queue", new OrderMessage(userId, activityId, System.currentTimeMillis()));return "秒杀成功";}
}

补充:

redis减扣后 减扣 MySQL 库存方案

1. 异步减扣 MySQL 库存(推荐)

  • 时机
    • Redis 减库存成功后,将任务发送到异步队列(如 RabbitMQ、Kafka),由后台消费者异步更新 MySQL 库存。
  • 流程
    1. 用户发起秒杀请求。
    2. Redis Lua 脚本扣减库存(原子操作)。
    3. 扣减成功后:
      • 发送消息到队列(如 {activityId, userId, timestamp})。
      • 返回“秒杀成功”给前端。
    4. 队列消费者异步处理:
      • 更新 MySQL 库存表。
      • 生成订单记录。
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;@PostMapping("/seckill/{activityId}")
public String seckill(@PathVariable String activityId, @RequestParam String userId) {// Redis 减库存if (!deductStock(activityId)) {return "库存不足";}// 异步更新 MySQLrabbitTemplate.convertAndSend("seckill-queue", new OrderMessage(activityId, userId, System.currentTimeMillis()));return "秒杀成功";
}// Lua 脚本扣库存
private boolean deductStock(String activityId) {String stockKey = "seckill:stock:" + activityId;String script = "local stock = tonumber(redis.call('GET', KEYS[1]) or 0) " +"if stock <= 0 then return 0 end " +"redis.call('DECR', KEYS[1]) " +"return 1";Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(stockKey));return result != null && result == 1;
}// 队列消费者
@Component
@RabbitListener(queues = "seckill-queue")
public class SeckillConsumer {@Autowiredprivate JdbcTemplate jdbcTemplate;@RabbitHandlerpublic void process(OrderMessage msg) {// 更新 MySQL 库存String sql = "UPDATE seckill_stock SET stock = stock - 1 WHERE activity_id = ? AND stock > 0";int updated = jdbcTemplate.update(sql, msg.getActivityId());if (updated > 0) {// 插入订单jdbcTemplate.update("INSERT INTO seckill_order (activity_id, user_id, create_time) VALUES (?, ?, ?)",msg.getActivityId(), msg.getUserId(), msg.getTimestamp());}}
}
优点
  • 高性能: Redis 减库存后立即返回,MySQL 异步处理,避免实时写库瓶颈。
  • 高并发: 适合秒杀场景,减少数据库压力。
缺点
  • 数据一致性: Redis 和 MySQL 可能短暂不一致(最终一致性)。
  • 失败处理: 队列消费失败需重试或补偿。
  • 适用场景
  • 高并发秒杀,优先保证响应速度。

2. 同步减扣 MySQL 库存

  • 时机
    • Redis 减库存成功后,在同一事务中同步更新 MySQL 库存。
  • 流程
    1. 用户发起秒杀请求。
    2. Redis Lua 脚本扣减库存。
    3. 扣减成功后:
    4. 立即更新 MySQL 库存。
    5. 生成订单。
    6. 返回“秒杀成功”。
@PostMapping("/seckill/{activityId}")
@Transactional
public String seckill(@PathVariable String activityId, @RequestParam String userId) {// Redis 减库存if (!deductStock(activityId)) {return "库存不足";}// 同步更新 MySQLint updated = jdbcTemplate.update("UPDATE seckill_stock SET stock = stock - 1 WHERE activity_id = ? AND stock > 0",activityId);if (updated == 0) {// 回滚 Redis(可选)redisTemplate.opsForValue().increment("seckill:stock:" + activityId);return "库存不足";}// 插入订单jdbcTemplate.update("INSERT INTO seckill_order (activity_id, user_id, create_time) VALUES (?, ?, ?)",activityId, userId, System.currentTimeMillis());return "秒杀成功";
}
优点
  • 强一致性: Redis 和 MySQL 库存保持同步。
  • 简单: 无需异步队列。
缺点
  • 性能瓶颈: MySQL 写操作耗时,影响并发能力。
  • 回滚复杂: 如果 MySQL 更新失败,需回滚 Redis。
  • 适用场景
  • 低并发场景,或对数据一致性要求极高。

3. 延迟减扣 MySQL 库存(定时同步)

  • 时机
    • Redis 减库存后,通过定时任务(如每分钟)批量同步 MySQL 库存。
  • 流程
    1. Redis 减库存。
    2. 记录每次扣减的日志(如 Redis List seckill:stock:log)。
    3. 定时任务读取日志,批量更新 MySQL。
  • 实现示例
// 秒杀接口
@PostMapping("/seckill/{activityId}")
public String seckill(@PathVariable String activityId, @RequestParam String userId) {if (!deductStock(activityId)) {return "库存不足";}// 记录日志redisTemplate.opsForList().leftPush("seckill:stock:log", activityId + "," + userId + "," + System.currentTimeMillis());return "秒杀成功";
}// 定时任务
@Component
@EnableScheduling
public class StockSyncTask {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate JdbcTemplate jdbcTemplate;@Scheduled(fixedRate = 60000) // 每分钟public void syncStock() {List<String> logs = redisTemplate.opsForList().range("seckill:stock:log", 0, -1);if (logs != null && !logs.isEmpty()) {Map<String, Integer> stockUpdates = new HashMap<>();for (String log : logs) {String[] parts = log.split(",");String activityId = parts[0];stockUpdates.merge(activityId, 1, Integer::sum);}// 批量更新 MySQLfor (Map.Entry<String, Integer> entry : stockUpdates.entrySet()) {jdbcTemplate.update("UPDATE seckill_stock SET stock = stock - ? WHERE activity_id = ?",entry.getValue(), entry.getKey());}redisTemplate.opsForList().trim("seckill:stock:log", logs.size(), -1); // 清空已处理日志}}
}
优点
  • 性能优化: 批量处理,减少 MySQL 频繁写。
  • 容错: 日志记录便于排查。
缺点
  • 一致性延迟: MySQL 库存更新有延迟。
  • 复杂性: 需维护日志和定时任务。
  • 适用场景
  • 中等并发,允许短暂不一致。

选择依据

方案MySQL减库存时机一致性性能复杂度适用场景
异步减扣Redis 后异步队列最终一致高并发秒杀
同步减扣Redis 后立即同步强一致低并发强一致性
延迟减扣Redis 后定时批量延迟一致中等并发可接受延迟

推荐方案

  • 高并发秒杀: 采用异步减扣。
    • Redis 负责实时库存控制,MySQL 异步更新。
    • 通过队列解耦,确保高吞吐量。
  • 关键点:
    • Redis Lua 脚本保证原子性。
    • 异步任务失败时,需重试或补偿(如记录失败日志)。
http://www.dtcms.com/wzjs/162001.html

相关文章:

  • 秦皇岛中兵建设集团网站万网官网入口
  • 搭建网站seo优化游戏性能的软件
  • 搭建网站服务青岛网络科技公司排名
  • 有一个专门做lol同人的网站seo优化方案模板
  • qq互联 网站建设不完善百度外链查询工具
  • 百度联盟怎么做自己的网站许昌网络推广外包
  • 哈尔滨高端网站设计蜗牛精灵seo
  • 门户网站建设基本情况百度关键词搜索优化
  • 网站建设新手指南汕尾网站seo
  • 上海网络营销推广方法网站优化排名易下拉系统
  • 柳州免费做网站的公司合肥网站排名提升
  • 佛山网站建设佛山谷歌官方网站注册
  • 制作网页网站2022年近期重大新闻事件
  • 哪里免费做网站google首页
  • 广州seo网站靠谱seo 网站排名
  • yahoo网站提交入口营销推广手段有什么
  • 免费中文企业网站模板百度sem推广具体做什么
  • 企业网站的建立联系方式seo线下培训机构
  • 软件开发与网站开发手机最新产品新闻
  • 上海 餐饮网站建设微平台推广
  • 跨境电商代运营公司十强网站关键词优化排名外包
  • java做网站建设后台b站推广入口2023mmm
  • 通过模版做网站搜索引擎推广的关键词
  • 深圳做手机商城网站建设2021拉新推广佣金排行榜
  • 初学php者网站首页怎么做品牌推广与传播
  • 长沙企业建站系统百度网页
  • 在线ppt制作网站有哪些站长推荐产品
  • 南京网站建设知识做任务赚佣金的正规平台
  • 做网站被骗去哪投诉百度竞价推广培训
  • 衡水网站建设公司联系电话seo技术培训海南