Skip to content

业务常见问题与解决方案

4314字约14分钟

2025-08-16

高并发问题

1. 秒杀系统设计

问题描述

  • 高并发访问导致系统崩溃
  • 超卖问题(库存为负数)
  • 重复下单问题
  • 系统响应缓慢

解决方案

前端限流
// 按钮点击限流
let canClick = true;

function handleClick() {
    if (!canClick) return;
    canClick = false;

    // 执行下单逻辑
    submitOrder().finally(() => {
        setTimeout(() => {
            canClick = true;
        }, 1000);
    });
}
后端限流
@RestController
public class SeckillController {
    
    // 使用Redis限流
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @PostMapping("/seckill")
    public Result seckill(@RequestParam Long productId, @RequestParam Long userId) {
        // 1. 用户限流(每个用户每秒只能请求一次)
        String userKey = "seckill:user:" + userId;
        if (!redisTemplate.opsForValue().setIfAbsent(userKey, "1", 1, TimeUnit.SECONDS)) {
            return Result.error("请求过于频繁,请稍后再试");
        }
        
        // 2. 商品限流(每个商品每秒最多处理100个请求)
        String productKey = "seckill:product:" + productId;
        Long count = redisTemplate.opsForValue().increment(productKey);
        if (count == 1) {
            redisTemplate.c(productKey, 1, TimeUnit.SECONDS);
        }
        if (count > 100) {
            return Result.error("商品太火爆,请稍后再试");
        }
        
        // 3. 执行秒杀逻辑
        return seckillService.doSeckill(productId, userId);
    }
}
库存扣减(防超卖)
@Service
public class SeckillService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Transactional
    public Result doSeckill(Long productId, Long userId) {
        // 使用Redis原子操作扣减库存
        String stockKey = "stock:" + productId;
        Long stock = redisTemplate.opsForValue().decrement(stockKey);
        
        if (stock < 0) {
            // 库存不足,回滚
            redisTemplate.opsForValue().increment(stockKey);
            return Result.error("库存不足");
        }
        
        // 检查是否重复下单
        String orderKey = "order:" + productId + ":" + userId;
        if (redisTemplate.hasKey(orderKey)) {
            // 重复下单,回滚库存
            redisTemplate.opsForValue().increment(stockKey);
            return Result.error("您已下单,请勿重复操作");
        }
        
        try {
            // 创建订单
            Order order = createOrder(productId, userId);
            
            // 标记已下单
            redisTemplate.opsForValue().set(orderKey, order.getId().toString(), 24, TimeUnit.HOURS);
            
            return Result.success(order);
        } catch (Exception e) {
            // 异常回滚库存
            redisTemplate.opsForValue().increment(stockKey);
            throw e;
        }
    }
}

2. 接口幂等性设计

问题描述

  • 用户重复点击导致重复提交
  • 网络重试导致重复请求
  • 分布式环境下重复处理

解决方案

唯一标识符
@RestController
public class OrderController {
    
    @PostMapping("/createOrder")
    public Result createOrder(@RequestBody OrderRequest request, 
                            @RequestHeader("X-Request-Id") String requestId) {
        
        // 检查请求ID是否已处理
        String processedKey = "processed:" + requestId;
        if (redisTemplate.hasKey(processedKey)) {
            // 幂等返回,不重复处理
            return Result.success("订单已创建");
        }
        
        try {
            // 处理业务逻辑
            Order order = orderService.createOrder(request);
            
            // 标记请求已处理
            redisTemplate.opsForValue().set(processedKey, "1", 24, TimeUnit.HOURS);
            
            return Result.success(order);
        } catch (Exception e) {
            // 异常时删除标记,允许重试
            redisTemplate.delete(processedKey);
            throw e;
        }
    }
}
数据库唯一约束
-- 订单表添加唯一约束
ALTER TABLE orders ADD UNIQUE KEY uk_user_product_time (user_id, product_id, create_time);

-- 或者使用业务字段组合
ALTER TABLE orders ADD UNIQUE KEY uk_request_id (request_id);
分布式锁
@Service
public class OrderService {
    
    @Autowired
    private RedissonClient redissonClient;
    
    public Order createOrder(OrderRequest request) {
        String lockKey = "order:lock:" + request.getRequestId();
        RLock lock = redissonClient.getLock(lockKey);
        
        try {
            // 尝试获取锁,等待5秒,持有锁30秒
            if (lock.tryLock(5, 30, TimeUnit.SECONDS)) {
                // 检查是否已处理
                if (orderRepository.existsByRequestId(request.getRequestId())) {
                    return orderRepository.findByRequestId(request.getRequestId());
                }
                
                // 创建订单
                Order order = new Order();
                // ... 设置订单属性
                return orderRepository.save(order);
            } else {
                throw new RuntimeException("获取锁失败");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("获取锁被中断");
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

性能优化问题

1. 数据库查询优化

问题描述

  • 慢查询导致接口响应慢
  • 大量数据查询内存溢出
  • 复杂关联查询性能差

解决方案

分页查询优化
@Service
public class UserService {
    
    // 传统分页(性能差)
    public Page<User> getUsersTraditional(int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userRepository.findAll(pageable);
    }
    
    // 游标分页(性能好)
    public List<User> getUsersByCursor(Long lastId, int size) {
        if (lastId == null) {
            return userRepository.findTopByOrderByIdAsc(size);
        } else {
            return userRepository.findByIdGreaterThanOrderByIdAsc(lastId, size);
        }
    }
    
    // 时间分页
    public List<User> getUsersByTime(Date lastTime, int size) {
        if (lastTime == null) {
            return userRepository.findTopByOrderByCreateTimeDesc(size);
        } else {
            return userRepository.findByCreateTimeBeforeOrderByCreateTimeDesc(lastTime, size);
        }
    }
}
批量操作优化
@Service
public class BatchService {
    
    // 批量插入
    public void batchInsert(List<User> users) {
        int batchSize = 1000;
        for (int i = 0; i < users.size(); i += batchSize) {
            int end = Math.min(i + batchSize, users.size());
            List<User> batch = users.subList(i, end);
            userRepository.saveAll(batch);
        }
    }
    
    // 批量更新
    @Transactional
    public void batchUpdate(List<Long> userIds, String status) {
        int batchSize = 500;
        for (int i = 0; i < userIds.size(); i += batchSize) {
            int end = Math.min(i + batchSize, userIds.size());
            List<Long> batch = userIds.subList(i, end);
            userRepository.updateStatusByIds(batch, status);
        }
    }
    
    // 使用JdbcTemplate批量操作
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public void batchInsertWithJdbc(List<User> users) {
        String sql = "INSERT INTO users (name, email, create_time) VALUES (?, ?, ?)";
        
        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                User user = users.get(i);
                ps.setString(1, user.getName());
                ps.setString(2, user.getEmail());
                ps.setTimestamp(3, new Timestamp(user.getCreateTime().getTime()));
            }
            
            @Override
            public int getBatchSize() {
                return users.size();
            }
        });
    }
}

2. 缓存优化

问题描述

  • 缓存穿透(查询不存在的数据)
  • 缓存雪崩(大量缓存同时失效)
  • 缓存击穿(热点数据失效)

解决方案

缓存穿透防护
@Service
public class UserService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public User getUserById(Long id) {
        String key = "user:" + id;
        
        // 1. 查询缓存
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user != null) {
            return user;
        }
        
        // 2. 查询数据库
        user = userRepository.findById(id).orElse(null);
        
        if (user != null) {
            // 3. 缓存存在的数据
            redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS);
        } else {
            // 4. 缓存空值,防止缓存穿透
            redisTemplate.opsForValue().set(key, new NullValue(), 5, TimeUnit.MINUTES);
        }
        
        return user;
    }
    
    // 布隆过滤器防穿透
    @Autowired
    private BloomFilter<Long> userBloomFilter;
    
    public User getUserByIdWithBloomFilter(Long id) {
        // 1. 布隆过滤器检查
        if (!userBloomFilter.mightContain(id)) {
            return null;
        }
        
        // 2. 查询缓存和数据库
        return getUserById(id);
    }
}
缓存雪崩防护
@Service
public class CacheService {
    
    // 随机过期时间
    public void setWithRandomExpire(String key, Object value, long baseExpire, TimeUnit unit) {
        // 基础过期时间 + 随机偏移(±10%)
        long randomOffset = (long) (baseExpire * 0.1 * (Math.random() - 0.5));
        long expireTime = baseExpire + randomOffset;
        
        redisTemplate.opsForValue().set(key, value, expireTime, unit);
    }
    
    // 缓存预热
    @PostConstruct
    public void cacheWarmUp() {
        // 系统启动时预热热点数据
        List<User> hotUsers = userRepository.findHotUsers();
        for (User user : hotUsers) {
            setWithRandomExpire("user:" + user.getId(), user, 1, TimeUnit.HOURS);
        }
    }
    
    // 定时刷新缓存
    @Scheduled(fixedRate = 30 * 60 * 1000) // 30分钟
    public void refreshCache() {
        List<User> hotUsers = userRepository.findHotUsers();
        for (User user : hotUsers) {
            String key = "user:" + user.getId();
            if (redisTemplate.hasKey(key)) {
                // 延长过期时间
                redisTemplate.expire(key, 1, TimeUnit.HOURS);
            }
        }
    }
}
缓存击穿防护
@Service
public class HotDataService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 互斥锁防击穿
    public Object getHotDataWithLock(String key, Supplier<Object> dataLoader) {
        // 1. 查询缓存
        Object data = redisTemplate.opsForValue().get(key);
        if (data != null) {
            return data;
        }
        
        // 2. 获取分布式锁
        String lockKey = "lock:" + key;
        RLock lock = redissonClient.getLock(lockKey);
        
        try {
            if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
                // 3. 双重检查
                data = redisTemplate.opsForValue().get(key);
                if (data != null) {
                    return data;
                }
                
                // 4. 加载数据
                data = dataLoader.get();
                redisTemplate.opsForValue().set(key, data, 1, TimeUnit.HOURS);
                
                return data;
            } else {
                // 5. 获取锁失败,等待一段时间后重试
                Thread.sleep(100);
                return getHotDataWithLock(key, dataLoader);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("获取锁被中断");
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
    
    // 逻辑过期防击穿
    public Object getHotDataWithLogicExpire(String key, Supplier<Object> dataLoader) {
        // 1. 查询缓存
        Object data = redisTemplate.opsForValue().get(key);
        if (data != null) {
            // 2. 检查逻辑过期时间
            String expireKey = "expire:" + key;
            Long expireTime = (Long) redisTemplate.opsForValue().get(expireKey);
            
            if (expireTime != null && System.currentTimeMillis() < expireTime) {
                return data;
            }
            
            // 3. 逻辑过期,异步更新
            CompletableFuture.runAsync(() -> {
                try {
                    Object newData = dataLoader.get();
                    redisTemplate.opsForValue().set(key, newData);
                    redisTemplate.opsForValue().set(expireKey, 
                        System.currentTimeMillis() + 3600000, 1, TimeUnit.HOURS);
                } catch (Exception e) {
                    log.error("异步更新缓存失败", e);
                }
            });
            
            return data;
        }
        
        // 4. 缓存不存在,同步加载
        data = dataLoader.get();
        redisTemplate.opsForValue().set(key, data);
        redisTemplate.opsForValue().set(expireKey, 
            System.currentTimeMillis() + 3600000, 1, TimeUnit.HOURS);
        
        return data;
    }
}

数据一致性问题

1. 分布式事务

问题描述

  • 跨服务数据不一致
  • 部分成功部分失败
  • 数据最终一致性难以保证

解决方案

2PC(两阶段提交)
@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
    
    // 2PC实现
    @Transactional
    public Result createOrderWith2PC(OrderRequest request) {
        String xid = UUID.randomUUID().toString();
        
        try {
            // 第一阶段:准备阶段
            if (!inventoryService.prepare(xid, request.getProductId(), request.getQuantity())) {
                return Result.error("库存准备失败");
            }
            
            if (!paymentService.prepare(xid, request.getUserId(), request.getAmount())) {
                // 回滚库存
                inventoryService.rollback(xid);
                return Result.error("支付准备失败");
            }
            
            // 第二阶段:提交阶段
            if (!inventoryService.commit(xid)) {
                paymentService.rollback(xid);
                return Result.error("库存提交失败");
            }
            
            if (!paymentService.commit(xid)) {
                inventoryService.rollback(xid);
                return Result.error("支付提交失败");
            }
            
            // 创建订单
            Order order = createOrder(request);
            return Result.success(order);
            
        } catch (Exception e) {
            // 异常回滚
            inventoryService.rollback(xid);
            paymentService.rollback(xid);
            throw e;
        }
    }
}
TCC(Try-Confirm-Cancel)
@Service
public class OrderTCCService {
    
    // Try阶段:资源预留
    @Transactional
    public boolean tryCreateOrder(String xid, OrderRequest request) {
        try {
            // 1. 预留库存
            if (!inventoryService.tryReserve(xid, request.getProductId(), request.getQuantity())) {
                return false;
            }
            
            // 2. 预留资金
            if (!paymentService.tryReserve(xid, request.getUserId(), request.getAmount())) {
                // 回滚库存预留
                inventoryService.cancelReserve(xid);
                return false;
            }
            
            // 3. 创建预订单
            Order order = new Order();
            order.setStatus(OrderStatus.PENDING);
            order.setXid(xid);
            // ... 设置其他属性
            orderRepository.save(order);
            
            return true;
        } catch (Exception e) {
            // 异常回滚
            inventoryService.cancelReserve(xid);
            paymentService.cancelReserve(xid);
            throw e;
        }
    }
    
    // Confirm阶段:确认执行
    @Transactional
    public boolean confirmCreateOrder(String xid) {
        try {
            // 1. 确认库存扣减
            if (!inventoryService.confirmReserve(xid)) {
                return false;
            }
            
            // 2. 确认支付
            if (!paymentService.confirmReserve(xid)) {
                return false;
            }
            
            // 3. 确认订单
            Order order = orderRepository.findByXid(xid);
            order.setStatus(OrderStatus.CONFIRMED);
            orderRepository.save(order);
            
            return true;
        } catch (Exception e) {
            log.error("确认订单失败", e);
            return false;
        }
    }
    
    // Cancel阶段:取消操作
    @Transactional
    public boolean cancelCreateOrder(String xid) {
        try {
            // 1. 取消库存预留
            inventoryService.cancelReserve(xid);
            
            // 2. 取消资金预留
            paymentService.cancelReserve(xid);
            
            // 3. 取消订单
            Order order = orderRepository.findByXid(xid);
            if (order != null) {
                order.setStatus(OrderStatus.CANCELLED);
                orderRepository.save(order);
            }
            
            return true;
        } catch (Exception e) {
            log.error("取消订单失败", e);
            return false;
        }
    }
}
最终一致性(消息队列)
@Service
public class OrderEventService {
    
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    
    // 创建订单(本地事务)
    @Transactional
    public Order createOrder(OrderRequest request) {
        // 1. 创建订单
        Order order = new Order();
        // ... 设置订单属性
        order = orderRepository.save(order);
        
        // 2. 发送事件消息
        OrderEvent event = new OrderEvent();
        event.setOrderId(order.getId());
        event.setType(OrderEventType.CREATED);
        event.setData(request);
        
        kafkaTemplate.send("order-events", JSON.toJSONString(event));
        
        return order;
    }
    
    // 消费订单事件
    @KafkaListener(topics = "order-events")
    public void handleOrderEvent(String message) {
        try {
            OrderEvent event = JSON.parseObject(message, OrderEvent.class);
            
            switch (event.getType()) {
                case CREATED:
                    handleOrderCreated(event);
                    break;
                case CANCELLED:
                    handleOrderCancelled(event);
                    break;
                default:
                    log.warn("未知事件类型: {}", event.getType());
            }
        } catch (Exception e) {
            log.error("处理订单事件失败", e);
            // 可以发送到死信队列重试
        }
    }
    
    private void handleOrderCreated(OrderEvent event) {
        OrderRequest request = (OrderRequest) event.getData();
        
        // 1. 扣减库存
        inventoryService.decreaseStock(request.getProductId(), request.getQuantity());
        
        // 2. 扣减余额
        paymentService.decreaseBalance(request.getUserId(), request.getAmount());
        
        // 3. 更新订单状态
        Order order = orderRepository.findById(event.getOrderId()).orElse(null);
        if (order != null) {
            order.setStatus(OrderStatus.PAID);
            orderRepository.save(order);
        }
    }
}

2. 缓存与数据库一致性

问题描述

  • 缓存更新不及时
  • 缓存与数据库数据不一致
  • 并发更新导致数据错乱

解决方案

先更新数据库,再删除缓存
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 更新用户信息
    @Transactional
    public void updateUser(User user) {
        // 1. 更新数据库
        userRepository.save(user);
        
        // 2. 删除缓存
        String key = "user:" + user.getId();
        redisTemplate.delete(key);
    }
    
    // 删除用户
    @Transactional
    public void deleteUser(Long id) {
        // 1. 删除数据库
        userRepository.deleteById(id);
        
        // 2. 删除缓存
        String key = "user:" + id;
        redisTemplate.delete(key);
    }
}
延迟双删策略
@Service
public class UserService {
    
    // 延迟双删
    @Transactional
    public void updateUserWithDelayDelete(User user) {
        // 1. 删除缓存
        String key = "user:" + user.getId();
        redisTemplate.delete(key);
        
        // 2. 更新数据库
        userRepository.save(user);
        
        // 3. 延迟删除缓存(防止并发问题)
        CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(500); // 延迟500ms
                redisTemplate.delete(key);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
    }
}
缓存更新策略
@Service
public class CacheUpdateService {
    
    // 缓存更新策略
    public void updateCache(String key, Object value, long expire, TimeUnit unit) {
        // 1. 先更新缓存
        redisTemplate.opsForValue().set(key, value, expire, unit);
        
        // 2. 再更新数据库
        updateDatabase(key, value);
    }
    
    // 缓存删除策略
    public void deleteCache(String key) {
        // 1. 先删除缓存
        redisTemplate.delete(key);
        
        // 2. 再删除数据库
        deleteFromDatabase(key);
    }
    
    // 缓存读取策略
    public Object getCache(String key, Supplier<Object> dataLoader) {
        // 1. 查询缓存
        Object data = redisTemplate.opsForValue().get(key);
        if (data != null) {
            return data;
        }
        
        // 2. 查询数据库
        data = dataLoader.get();
        if (data != null) {
            // 3. 更新缓存
            redisTemplate.opsForValue().set(key, data, 1, TimeUnit.HOURS);
        }
        
        return data;
    }
}

分布式问题

1. 分布式锁

问题描述

  • 并发访问导致数据不一致
  • 锁超时导致业务异常
  • 死锁问题

解决方案

Redis分布式锁
@Service
public class RedisLockService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    // 获取锁
    public boolean tryLock(String key, String value, long expire, TimeUnit unit) {
        Boolean result = redisTemplate.opsForValue()
            .setIfAbsent(key, value, expire, unit);
        return Boolean.TRUE.equals(result);
    }
    
    // 释放锁
    public boolean releaseLock(String key, String value) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                       "return redis.call('del', KEYS[1]) else return 0 end";
        
        Long result = redisTemplate.execute(
            new DefaultRedisScript<>(script, Long.class),
            Collections.singletonList(key),
            value
        );
        
        return Long.valueOf(1).equals(result);
    }
    
    // 使用分布式锁
    public Object executeWithLock(String key, Supplier<Object> task, 
                                 long expire, TimeUnit unit) {
        String lockValue = UUID.randomUUID().toString();
        String lockKey = "lock:" + key;
        
        try {
            // 尝试获取锁
            if (!tryLock(lockKey, lockValue, expire, unit)) {
                throw new RuntimeException("获取锁失败");
            }
            
            // 执行任务
            return task.get();
            
        } finally {
            // 释放锁
            releaseLock(lockKey, lockValue);
        }
    }
}
Zookeeper分布式锁
@Service
public class ZookeeperLockService {
    
    @Autowired
    private CuratorFramework client;
    
    // 获取锁
    public InterProcessMutex getLock(String path) {
        return new InterProcessMutex(client, path);
    }
    
    // 使用锁
    public Object executeWithLock(String path, Supplier<Object> task, 
                                 long timeout, TimeUnit unit) {
        InterProcessMutex lock = getLock(path);
        
        try {
            // 尝试获取锁
            if (lock.acquire(timeout, unit)) {
                // 执行任务
                return task.get();
            } else {
                throw new RuntimeException("获取锁超时");
            }
        } catch (Exception e) {
            throw new RuntimeException("获取锁失败", e);
        } finally {
            try {
                if (lock.isAcquiredInThisProcess()) {
                    lock.release();
                }
            } catch (Exception e) {
                log.error("释放锁失败", e);
            }
        }
    }
}

2. 分布式ID生成

问题描述

  • 自增ID在分布式环境下冲突
  • UUID性能差且无序
  • 雪花算法时钟回拨问题

解决方案

雪花算法
@Component
public class SnowflakeIdGenerator {
    
    private final long workerId;
    private final long datacenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;
    
    private final long workerIdBits = 5L;
    private final long datacenterIdBits = 5L;
    private final long sequenceBits = 12L;
    
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    
    private final long workerIdShift = sequenceBits;
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
    
    public SnowflakeIdGenerator(@Value("${snowflake.worker-id:1}") long workerId,
                               @Value("${snowflake.datacenter-id:1}") long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException("Worker ID超出范围");
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException("Datacenter ID超出范围");
        }
        
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }
    
    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();
        
        // 时钟回拨检查
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨,拒绝生成ID");
        }
        
        // 同一毫秒内序列号递增
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                // 同一毫秒内序列号用完,等待下一毫秒
                timestamp = waitNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        
        lastTimestamp = timestamp;
        
        // 组合ID
        return ((timestamp - 1288834974657L) << timestampLeftShift) |
               (datacenterId << datacenterIdShift) |
               (workerId << workerIdShift) |
               sequence;
    }
    
    private long waitNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}
Redis自增ID
@Service
public class RedisIdGenerator {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    // 生成订单ID
    public String generateOrderId() {
        String key = "order:id:" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        Long sequence = redisTemplate.opsForValue().increment(key);
        
        // 设置过期时间(避免无限增长)
        redisTemplate.expire(key, 1, TimeUnit.DAYS);
        
        return String.format("O%s%06d", 
            LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE), 
            sequence);
    }
    
    // 生成用户ID
    public Long generateUserId() {
        String key = "user:id";
        return redisTemplate.opsForValue().increment(key);
    }
}

安全相关问题

1. SQL注入防护

问题描述

  • 恶意SQL注入攻击
  • 数据库信息泄露
  • 数据被恶意修改

解决方案

参数化查询
@Repository
public class UserRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    // 正确的参数化查询
    public User findByUsername(String username) {
        String sql = "SELECT * FROM users WHERE username = ?";
        try {
            return jdbcTemplate.queryForObject(sql, new Object[]{username}, new UserRowMapper());
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }
    
    // 使用NamedParameterJdbcTemplate
    public List<User> findByCondition(String username, String email) {
        String sql = "SELECT * FROM users WHERE 1=1";
        MapSqlParameterSource params = new MapSqlParameterSource();
        
        if (StringUtils.hasText(username)) {
            sql += " AND username = :username";
            params.addValue("username", username);
        }
        
        if (StringUtils.hasText(email)) {
            sql += " AND email = :email";
            params.addValue("email", email);
        }
        
        return namedParameterJdbcTemplate.query(sql, params, new UserRowMapper());
    }
}
MyBatis参数绑定
<!-- 正确的参数绑定 -->
<select id="findByCondition" resultType="User">
    SELECT * FROM users
    <where>
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="email != null and email != ''">
            AND email = #{email}
        </if>
    </where>
</select>

        <!-- 错误的字符串拼接(容易SQL注入) -->
<select id="findByConditionWrong" resultType="User">
SELECT * FROM users WHERE username = '${username}'
</select>

2. XSS防护

问题描述

  • 恶意脚本注入
  • 用户信息泄露
  • 会话劫持

解决方案

输入过滤
@Component
public class XssFilter {
    
    // HTML转义
    public String escapeHtml(String input) {
        if (input == null) {
            return null;
        }
        
        return input.replace("&", "&amp;")
                   .replace("<", "&lt;")
                   .replace(">", "&gt;")
                   .replace("\"", "&quot;")
                   .replace("'", "&#x27;");
    }
    
    // 移除危险标签
    public String removeDangerousTags(String input) {
        if (input == null) {
            return null;
        }
        
        // 移除script、iframe等危险标签
        return input.replaceAll("(?i)<script[^>]*>.*?</script>", "")
                   .replaceAll("(?i)<iframe[^>]*>.*?</iframe>", "")
                   .replaceAll("(?i)<object[^>]*>.*?</object>", "")
                   .replaceAll("(?i)<embed[^>]*>.*?</embed>", "");
    }
}
输出编码
<!-- Thymeleaf自动转义 -->
<div th:text="${user.name}"></div>
<div th:utext="${user.description}"></div>

<!-- 手动转义 -->
<div th:utext="${#strings.escapeXml(user.description)}"></div>

监控告警问题

1. 业务监控

问题描述

  • 业务异常无法及时发现
  • 性能问题难以定位
  • 缺乏业务指标监控

解决方案

业务指标监控
@Component
public class BusinessMetrics {
    
    private final MeterRegistry meterRegistry;
    
    public BusinessMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    // 订单创建成功率
    public void recordOrderSuccess() {
        Counter.builder("order.success")
               .tag("type", "create")
               .register(meterRegistry)
               .increment();
    }
    
    public void recordOrderFailure() {
        Counter.builder("order.failure")
               .tag("type", "create")
               .register(meterRegistry)
               .increment();
    }
    
    // 接口响应时间
    public Timer.Sample startTimer(String name) {
        return Timer.start(meterRegistry);
    }
    
    public void stopTimer(Timer.Sample sample, String name) {
        sample.stop(Timer.builder("api.response.time")
                       .tag("name", name)
                       .register(meterRegistry));
    }
    
    // 业务异常监控
    public void recordBusinessException(String type, String message) {
        Counter.builder("business.exception")
               .tag("type", type)
               .tag("message", message)
               .register(meterRegistry)
               .increment();
    }
}
自定义注解监控
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MonitorBusiness {
    String value() default "";
    String[] tags() default {};
}

@Aspect
@Component
public class BusinessMonitorAspect {
    
    private final MeterRegistry meterRegistry;
    
    public BusinessMonitorAspect(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    @Around("@annotation(monitor)")
    public Object around(ProceedingJoinPoint point, MonitorBusiness monitor) throws Throwable {
        Timer.Sample sample = Timer.start(meterRegistry);
        
        try {
            Object result = point.proceed();
            
            // 记录成功
            Counter.builder("business.success")
                   .tag("name", monitor.value())
                   .register(meterRegistry)
                   .increment();
            
            return result;
        } catch (Exception e) {
            // 记录失败
            Counter.builder("business.failure")
                   .tag("name", monitor.value())
                   .tag("exception", e.getClass().getSimpleName())
                   .register(meterRegistry)
                   .increment();
            
            throw e;
        } finally {
            // 记录执行时间
            sample.stop(Timer.builder("business.execution.time")
                              .tag("name", monitor.value())
                              .register(meterRegistry));
        }
    }
}

2. 告警配置

问题描述

  • 告警阈值设置不合理
  • 告警信息不准确
  • 告警风暴问题

解决方案

Prometheus告警规则
groups:
  - name: business.rules
    rules:
      # 订单成功率告警
      - alert: OrderSuccessRateLow
        expr: rate(order_success_total[5m]) / (rate(order_success_total[5m]) + rate(order_failure_total[5m])) < 0.95
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "订单成功率过低"
          description: "订单成功率低于95%,当前值: {{ $value | humanizePercentage }}"

      # 接口响应时间告警
      - alert: ApiResponseTimeHigh
        expr: histogram_quantile(0.95, rate(api_response_time_seconds_bucket[5m])) > 1
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "接口响应时间过高"
          description: "95%分位响应时间超过1秒,当前值: {{ $value }}s"

      # 业务异常告警
      - alert: BusinessExceptionHigh
        expr: rate(business_exception_total[5m]) > 10
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "业务异常频率过高"
          description: "业务异常频率超过每分钟10次,当前值: {{ $value }}"
告警抑制和分组
# 告警抑制规则
inhibit_rules:
  # 如果订单服务完全不可用,抑制订单相关的其他告警
  - source_match:
      alertname: OrderServiceDown
    target_match:
      alertname: OrderSuccessRateLow
    equal: [ 'service' ]

  # 如果数据库不可用,抑制所有业务告警
  - source_match:
      alertname: DatabaseDown
    target_match:
      severity: warning
    equal: [ 'instance' ]

# 告警分组
route:
  group_by: [ 'alertname', 'service' ]
  group_wait: 30s      # 等待30秒后发送第一个告警
  group_interval: 5m   # 5分钟后发送重复告警
  repeat_interval: 4h  # 4小时后重复告警

总结

业务常见问题的解决需要:

  1. 预防为主:设计合理的架构和流程
  2. 监控先行:建立完善的监控体系
  3. 快速响应:制定应急预案和回滚策略
  4. 持续优化:根据实际运行情况不断改进

关键原则

  • 幂等性:所有操作都要支持重复执行
  • 最终一致性:允许短暂不一致,但要保证最终一致
  • 降级策略:核心功能优先,非核心功能可降级
  • 限流保护:防止系统过载,保护核心业务

记住:没有完美的解决方案,只有最适合当前业务场景的方案。要根据实际情况选择合适的策略组合。