Spring Cloud+Redis+Kafka高并发电商微服务系统源码深度解读

Spring Cloud+Redis+Kafka高并发电商微服务系统源码深度解读

面试场景

面试官:(严肃,30多岁,技术经理,身穿格子衫,手拿保温杯)

谢飞机:(搞笑角色,26岁,自称5年开发经验,实际只会CRUD,穿着印有"代码改变世界"的T恤)


第一轮:微服务架构基础

面试官:谢同学,听说你做过电商微服务项目?那我们先聊聊架构设计。如果让你从零搭建一个电商平台,你会怎么拆分服务?

谢飞机:啊!这个我熟!按照业务边界拆分嘛!用户服务、商品服务、订单服务、支付服务、库存服务、购物车服务,再来个网关服务统一入口,完美!

面试官:(微微点头)嗯,划分得还挺合理。那你说说这些服务之间怎么通信?

谢飞机:这个简单!用OpenFeign啊!写个接口,加个@FeignClient注解,就能调其他服务了,像调本地方法一样方便!

面试官:那服务注册和发现呢?用户服务怎么知道订单服务的地址?

谢飞机:呃......我一般在配置文件里写死IP和端口,这样最快!

面试官:(冷笑)写死地址?那你服务扩容的时候怎么办?手动改配置重启?

谢飞机:啊......好像是......不太好。那用注册中心?

面试官:对,比如Nacos或Eureka。服务启动时自动注册上去,其他服务通过服务名调用,动态发现实例地址。你来说说Nacos服务注册的原理?

谢飞机:就是......启动的时候发个请求给Nacos服务器,把IP、端口、服务名这些信息告诉它?

面试官:嗯,基本思路对了。那心跳机制呢?

谢飞机:心跳?我好像听说过......服务要定期给Nacos发个包证明自己还活着,不然就被踢出去了?

面试官:(点头)没错。Nacos默认5秒发一次心跳,15秒没收到标记为不健康,30秒没收到就剔除。这是服务健康检测的基础。那如果Nacos挂了怎么办?

谢飞机:呃......重启?或者......搭个集群?

面试官:集群是对的。Nacos支持集群部署,通过Raft协议保证数据一致性。你还得考虑配置中心,动态更新配置不用重启服务。

谢飞机:配置中心......我好像在Spring Cloud Config见过,但没用过,都是改配置文件重启......

面试官:看来实战经验还有欠缺。继续,API网关在微服务架构中起什么作用?

谢飞机:网关嘛,就是统一入口!路由转发、身份验证、限流熔断,都在网关层处理,后端服务专心处理业务!

面试官:回答得不错。那如果用户请求商品详情页,需要同时调用商品服务、库存服务、评价服务,你会怎么做?

谢飞机:那......按顺序调?先查商品,再查库存,再查评价?

面试官:那会很慢。有没有并行调用的方式?

谢飞机:呃......线程池?CompletableFuture?

面试官:对!可以结合CompletableFuture并行调用多个服务,再组合结果。或者使用响应式编程的Spring WebFlux。你用过吗?

谢飞机:WebFlux听说过,但没用过,太复杂了,我们还是用传统的同步调用!

面试官:嗯,响应式编程学习曲线确实陡峭。那第一轮就先到这里,下一轮我们聊聊数据层。


第二轮:缓存与数据一致性

面试官:电商系统中商品详情页访问量巨大,数据库扛不住,你会怎么设计?

谢飞机:加Redis缓存啊!把商品信息、库存、评价都塞进Redis,用户请求先查缓存,没有再查数据库,然后把数据回填到缓存,经典的Cache-Aside模式!

面试官:(赞许)嗯,说到了Cache-Aside。那缓存key会怎么设计?

谢飞机:product:detail:{id},这样一看就知道是商品详情,id是商品编号,清晰明了!

面试官:很好。那如果恶意请求一个不存在的商品ID,会怎么样?

谢飞机:呃......每次都查数据库,查不到返回null,但这样数据库压力大?

面试官:对,这叫缓存穿透。怎么解决?

谢飞机:啊......我听说过布隆过滤器!但具体怎么实现没写过......好像是个数组加哈希算法?

面试官:算是沾边。布隆过滤器可以用Bitmap+多个哈希函数实现,提前判断key是否存在,不存在的直接拦截。也可以缓存null值,但TTL要设置短一点。那缓存击穿呢?热点key过期瞬间大量请求打到数据库。

谢飞机:呃......永不过期?

面试官:可以,热点数据设置永不过期,后台异步更新。或者用互斥锁,只让一个请求查数据库,其他请求等待或重试。那缓存雪崩呢?大量key同时过期。

谢飞机:给过期时间加个随机数!让它们不要同时过期!

面试官:(点头)对,可以设置基础TTL+随机偏移量,比如10分钟到15分钟之间随机。还有Redis持久化方案,你知道RDB和AOF的区别吗?

谢飞机:RDB是快照,定时保存;AOF是日志,每次写操作都记下来!RDB快但可能丢数据,AOF慢但数据更安全!

面试官:回答得很到位!那你线上用哪种?

谢飞机:我们为了性能......都关了持久化!

面试官:(扶额)你这是拿生产环境当玩具?宕机就丢数据,还做什么电商?至少要开AOF everysec,配合Redis Cluster+哨兵模式保证高可用!

谢飞机:啊......我以为性能最重要......

面试官:性能重要,但数据安全更重要!接下来聊聊分布式场景下的数据一致性。用户下单扣库存,Redis扣了但数据库没扣,怎么保证一致性?

谢飞机:呃......先扣数据库再扣缓存?

面试官:那如果缓存扣了数据库失败,数据不一致了。听说过分布式事务吗?

谢飞机:分布式事务......Seata?好像听过,但没用过!

面试官:Seata是阿里开源的分布式事务解决方案,支持AT、TCC、SAGA等模式。电商场景常用AT模式,对业务代码侵入小。除了分布式事务,还可以用本地消息表或RocketMQ事务消息保证最终一致性。

谢飞机:事务消息......听着好高级......

面试官:这是电商核心,必须掌握。下一轮我们聊聊高并发场景。


第三轮:高并发与系统优化

面试官:大促期间,瞬时下单量达到百万级,怎么保证系统稳定?

谢飞机:上Kafka!把订单消息扔进Kafka,后端慢慢消费,削峰填谷嘛!

面试官:(点头)嗯,知道削峰填谷。那Kafka丢消息怎么办?

谢飞机:呃......Producer设置ack=all,Broker多副本同步,Consumer手动提交offset,应该就不会丢了吧?

面试官:思路是对的。ack=all表示所有副本都确认才算成功,min.insync.replicas保证至少几个副本同步。那如果消费失败怎么办?

谢飞机:重试!无限重试!

面试官:(打断)无限重试会把队列堵死!最多重试3次,再失败进死信队列,人工处理或定时任务补偿!

谢飞机:死信队列......听说过,没用过!

面试官:这是必须的!那你来说说订单处理的完整流程?

谢飞机:用户下单→扣库存→创建订单→支付→发货......

面试官:太笼统了!详细说!

谢飞机:呃......用户提交订单→校验库存→锁定库存→创建订单记录→调用支付→支付成功→扣减真实库存→发货?

面试官:嗯,基本流程对了。那库存锁定怎么实现?

谢飞机:用Redis的DECR命令原子扣减,返回正数说明成功!

面试官:那如果用户下单后不支付怎么办?

谢飞机:30分钟自动取消?定时任务扫描超时订单?

面试官:对,可以用延时队列(Redisson或RocketMQ延时消息),或者定时任务扫描。取消后释放锁定的库存。那限流怎么实现?

谢飞机:用Sentinel!可以限流、熔断、降级,像小区保安,人多了不让进!

面试官:(点头)很好,Sentinel是Spring Cloud Alibaba的组件,支持QPS限流、线程数限流,还有热点参数限流。那你来写个限流注解的例子?

谢飞机:@RateLimiter......permitPerSecond......我记不清了!

面试官 :@SentinelResource(value = "orderCreate", blockHandler = "handleBlock"),配合控制台配置规则就可以。看来实战代码写得还不够多。

谢飞机:(挠头)我们公司配置都是运维配的......

面试官:了解原理也很重要。最后一个问题,用户支付成功后,要发短信通知、发优惠券、更新积分、发物流通知,这些操作都必须成功吗?

谢飞机:当然!一个都不能少!

面试官:那如果短信服务挂了,用户就不能支付成功?

谢飞机:呃......好像......不太对......

面试官:这些非核心操作应该异步处理,不影响主流程!支付成功后发事件到Kafka,由消费者异步处理这些通知,失败也不影响订单状态!

谢飞机:异步......对对对!我想起来了!

面试官:看来你脑子里有概念,但理解还不够深入。微服务架构的核心就是服务解耦、异步处理、弹性伸缩。今天的面试就到这里,你回家等通知吧!

谢飞机:好的好的,谢谢面试官!我回去好好学习!

(谢飞机心里想:这面试官真严厉,不过好像学到了不少东西,回去得查查资料补补......)


答案详细解析

第一轮:微服务架构基础

1. 服务拆分原则

业务场景:电商系统庞大,如果采用单体架构会导致维护困难、部署缓慢、扩展性差。微服务架构通过"高内聚、低耦合"原则拆分服务。

技术点:

  • 按业务边界拆分:用户服务、商品服务、订单服务、支付服务、库存服务、购物车服务等
  • 避免过度拆分:将用户登录和注册拆成两个服务会导致调用链过长
  • 服务职责清晰:订单服务只负责订单生命周期,不直接操作库存(通过库存服务接口)

实现代码示例:

java 复制代码
// 用户服务启动类
@SpringBootApplication
@EnableDiscoveryClient  // 启用服务发现
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

// 订单服务调用用户服务
@FeignClient(name = "user-service", path = "/api/user")
public interface UserServiceClient {
    @GetMapping("/{userId}")
    UserDTO getUserById(@PathVariable("userId") Long userId);
}
2. 服务注册与发现原理

业务场景:微服务动态扩缩容,服务实例地址会变化,需要服务注册中心来统一管理。

技术点:

  • 服务注册:启动时向注册中心发送注册请求,包含服务名、IP、端口等信息
  • 心跳机制:定期(默认5秒)发送心跳证明存活,15秒未收到标记不健康,30秒未收到剔除
  • 服务发现:消费者从注册中心获取服务实例列表,进行负载均衡调用
  • 健康检查:Spring Boot Actuator提供/health端点检查服务健康状态

核心源码:

java 复制代码
// Nacos服务注册自动配置
@Configuration
public class NacosServiceRegistryAutoConfiguration {
    
    @Bean
    public ServiceRegistry<NacosRegistration> nacosServiceRegistry(
            NacosDiscoveryProperties nacosDiscoveryProperties) {
        return new NacosServiceRegistry(nacosDiscoveryProperties);
    }
}

// 心跳发送机制
public class BeatReactor {
    public void addBeatInfo(String serviceName, String ip, int port, BeatInfo beatInfo) {
        // 启动心跳线程,定期发送心跳
        executorService.schedule(() -> sendBeat(beatInfo), 0, TimeUnit.SECONDS);
    }
}
3. API网关作用

业务场景:所有外部请求需要统一入口,处理鉴权、限流、路由等横切关注点。

技术点:

  • 统一入口:所有外部请求先经过网关,再路由到具体微服务
  • 身份验证:统一做JWT校验、OAuth2认证
  • 限流熔断:保护后端服务不被流量击垮
  • 路由转发:根据URL路径或请求头转发到对应服务
  • 响应式编程:Spring Cloud Gateway基于WebFlux,非阻塞IO

网关配置示例:

yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service  # lb表示负载均衡
          predicates:
            - Path=/api/product/**
          filters:
            - StripPrefix=1  # 去掉/api前缀
      default-filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 100
            redis-rate-limiter.burstCapacity: 200

第二轮:缓存与数据一致性

4. 缓存穿透、击穿、雪崩

业务场景:电商系统热点数据缓存失效或被恶意攻击,导致数据库压力激增。

技术点:

缓存穿透:查询不存在的key,大量请求穿透到数据库

  • 解决方案1:缓存空值,设置短TTL(如1分钟)
  • 解决方案2:布隆过滤器,提前拦截无效key

缓存击穿:热点key过期瞬间大量请求打到数据库

  • 解决方案1:热点数据永不过期,后台异步更新
  • 解决方案2:互斥锁(SETNX),只允许一个请求查数据库

缓存雪崩:大量key同时过期,数据库瞬间压力巨大

  • 解决方案1:过期时间加随机数(如10-15分钟)
  • 解决方案2:使用多级缓存(Local+Redis)

布隆过滤器实现:

java 复制代码
@Component
public class BloomFilterUtil {
    private BloomFilter<Long> bloomFilter;
    
    @PostConstruct
    public void init() {
        // 预计插入100万数据,误判率0.01%
        bloomFilter = BloomFilter.create(Funnels.longFunnel(), 1000000, 0.0001);
        
        // 初始化已存在的商品ID
        List<Long> productIds = productService.getAllProductIds();
        productIds.forEach(bloomFilter::put);
    }
    
    public boolean mightContain(Long productId) {
        return bloomFilter.mightContain(productId);
    }
}

// 商品查询服务
@Service
public class ProductService {
    @Autowired
    private BloomFilterUtil bloomFilterUtil;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public ProductDTO getProduct(Long productId) {
        // 布隆过滤器拦截
        if (!bloomFilterUtil.mightContain(productId)) {
            return null;
        }
        
        String key = "product:detail:" + productId;
        ProductDTO product = (ProductDTO) redisTemplate.opsForValue().get(key);
        
        if (product != null) {
            return product;
        }
        
        // 缓存未命中,查数据库
        product = productMapper.selectById(productId);
        if (product != null) {
            redisTemplate.opsForValue().set(key, product, 30, TimeUnit.MINUTES);
        } else {
            // 缓存空值,防止穿透
            redisTemplate.opsForValue().set(key, NULL_VALUE, 1, TimeUnit.MINUTES);
        }
        
        return product;
    }
}
5. Redis持久化策略

业务场景:Redis宕机后需要恢复数据,必须配置持久化策略。

技术点:

  • RDB(Redis Database):快照持久化,定时保存数据到dump.rdb

    • 优点:文件小,恢复快,适合备份
    • 缺点:可能丢失最后一次快照后的数据
    • 配置:save 900 1 (15分钟内至少1个key变化就保存)
  • AOF(Append Only File):日志持久化,记录每次写操作

    • 优点:数据安全,最多丢失1秒数据
    • 缺点:文件大,恢复慢,影响性能
    • 配置:appendfsync everysec (每秒同步一次)

生产环境推荐配置:

yaml 复制代码
# redis.conf
# 开启AOF
appendonly yes
# 每秒同步
appendfsync everysec
# 开启RDB备份
save 900 1
save 300 10
save 60 10000
# 混合持久化(Redis 4.0+)
aof-use-rdb-preamble yes
6. 分布式事务解决方案

业务场景:订单创建扣库存、扣余额,多个服务间需要保证数据一致性。

技术点:

Seata AT模式(最常用):

  • 一阶段:本地事务提交,自动记录Undo Log
  • 二阶段:如果全局事务成功,异步删除Undo Log;失败则回滚
  • 优点:对业务代码无侵入,易于使用

本地消息表:

  • 执行业务时同时插入消息记录到本地表
  • 定时任务扫描消息表,发送到消息队列
  • 消费者处理业务,成功后标记消息已消费
  • 优点:最终一致性强,实现简单

RocketMQ事务消息:

  • 发送半消息(对消费者不可见)
  • 执行本地事务,成功则提交消息,失败则回滚
  • 消费者消费消息,执行业务逻辑

Seata实现示例:

java 复制代码
// 订单服务
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
public void createOrder(OrderDTO orderDTO) {
    // 1. 创建订单
    orderMapper.insert(order);
    
    // 2. 调用库存服务扣库存(自动加入全局事务)
    inventoryService.deductStock(orderDTO.getProductId(), orderDTO.getQuantity());
    
    // 3. 调用账户服务扣余额
    accountService.deductBalance(orderDTO.getUserId(), orderDTO.getAmount());
}

// 库存服务
@GlobalTransactional  // 分支事务
public void deductStock(Long productId, Integer quantity) {
    inventoryMapper.deduct(productId, quantity);
}

第三轮:高并发与系统优化

7. Kafka削峰填谷

业务场景:大促期间订单量激增,直接写数据库会导致数据库崩溃。

技术点:

  • 生产者:快速接收订单请求,发送到Kafka主题
  • 消费者:异步消费消息,按自身处理能力慢慢写数据库
  • 扩容:压力过大时增加消费者实例(注意分区数)
  • 消息可靠性:ack=all,副本数≥3,手动提交offset

Kafka配置:

yaml 复制代码
spring:
  kafka:
    producer:
      bootstrap-servers: localhost:9092
      # 消息确认机制
      acks: all  # 所有副本都确认才算成功
      retries: 3  # 重试次数
      # 序列化器
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
      # 批量发送
      batch-size: 16384
      linger-ms: 10
      
    consumer:
      bootstrap-servers: localhost:9092
      # 消费组
      group-id: order-consumer-group
      # 手动提交offset
      enable-auto-commit: false
      # 从最早的消息开始消费
      auto-offset-reset: earliest
      # 序列化器
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

消费者代码:

java 复制代码
@Service
public class OrderConsumer {
    
    @KafkaListener(topics = "order-topic", groupId = "order-consumer-group")
    public void consumeOrder(ConsumerRecord<String, String> record, Acknowledgment ack) {
        try {
            OrderDTO order = JSON.parseObject(record.value(), OrderDTO.class);
            
            // 处理订单逻辑
            orderService.processOrder(order);
            
            // 手动提交offset
            ack.acknowledge();
        } catch (Exception e) {
            log.error("处理订单失败", e);
            // 重试3次后进死信队列
            if (retryCount >= 3) {
                sendToDeadLetterQueue(record);
                ack.acknowledge();
            } else {
                throw e;  // 触发重试
            }
        }
    }
}
8. 库存扣减与超卖问题

业务场景:高并发场景下多个用户同时购买同一商品,可能导致超卖。

技术点:

  • 原子扣减:使用Redis DECR命令,保证原子性
  • 分布式锁:Redis SETNX或Redisson分布式锁
  • 预扣库存:下单时预扣,支付成功后才真正扣减
  • 超时取消:未支付订单自动释放库存

Redis原子扣减:

java 复制代码
@Service
public class InventoryService {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    /**
     * 原子扣减库存
     * @param productId 商品ID
     * @param quantity 扣减数量
     * @return 扣减成功返回true,库存不足返回false
     */
    public boolean deductStock(Long productId, Integer quantity) {
        String key = "stock:" + productId;
        
        // Lua脚本保证原子性
        String luaScript = """
            local stock = redis.call('get', KEYS[1])
            if tonumber(stock) >= tonumber(ARGV[1]) then
                redis.call('decrby', KEYS[1], ARGV[1])
                return 1
            else
                return 0
            end
        """;
        
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(luaScript);
        redisScript.setResultType(Long.class);
        
        Long result = redisTemplate.execute(
            redisScript, 
            Collections.singletonList(key), 
            String.valueOf(quantity)
        );
        
        return result != null && result == 1;
    }
}
9. 限流熔断机制

业务场景:大促期间流量激增,需要限制QPS防止系统崩溃。

技术点:

  • Sentinel:阿里巴巴开源,支持QPS限流、线程数限流、热点参数限流
  • 限流算法:令牌桶、漏桶、滑动窗口
  • 熔断降级:调用失败率高时自动熔断,快速失败
  • 系统自适应:根据系统负载自动调整限流阈值

Sentinel限流配置:

java 复制代码
@RestController
public class OrderController {
    
    @Autowired
    private OrderService orderService;
    
    /**
     * 创建订单接口,限流:100 QPS
     */
    @PostMapping("/order")
    @SentinelResource(
        value = "createOrder",
        blockHandler = "handleCreateOrderBlock",  // 限流降级方法
        fallback = "handleCreateOrderFallback"    // 异常降级方法
    )
    public Result createOrder(@RequestBody OrderDTO orderDTO) {
        orderService.createOrder(orderDTO);
        return Result.success();
    }
    
    /**
     * 限流降级方法
     */
    public Result handleCreateOrderBlock(OrderDTO orderDTO, BlockException ex) {
        log.warn("创建订单被限流", ex);
        return Result.error("系统繁忙,请稍后再试");
    }
    
    /**
     * 异常降级方法
     */
    public Result handleCreateOrderFallback(OrderDTO orderDTO, Throwable ex) {
        log.error("创建订单异常", ex);
        return Result.error("订单创建失败");
    }
}

Sentinel规则配置(控制台或代码):

java 复制代码
@Component
public class SentinelRuleInitializer implements ApplicationRunner {
    
    @Override
    public void run(ApplicationArguments args) {
        List<FlowRule> rules = new ArrayList<>();
        
        // 创建订单接口限流规则
        FlowRule rule = new FlowRule();
        rule.setResource("createOrder");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);  // QPS限流
        rule.setCount(100);  // 限流阈值100 QPS
        rule.setLimitApp("default");
        
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}
10. 异步事件处理

业务场景:支付成功后需要发短信、发券、更新积分等,这些操作不应影响主流程。

技术点:

  • 事件驱动架构:支付成功后发布事件,其他服务订阅事件
  • 消息队列解耦:将非核心操作异步化
  • 最终一致性:允许短暂延迟,保证数据最终一致
  • 死信队列:处理失败的消息,人工介入或重试

事件驱动实现:

java 复制代码
// 支付服务
@Service
public class PaymentService {
    
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    
    @Transactional
    public void processPayment(PaymentDTO payment) {
        // 1. 更新支付状态
        paymentMapper.updateStatus(payment.getId(), PaymentStatus.SUCCESS);
        
        // 2. 发布支付成功事件
        PaymentSuccessEvent event = new PaymentSuccessEvent(
            payment.getOrderId(), 
            payment.getUserId(), 
            payment.getAmount()
        );
        
        kafkaTemplate.send("payment-success-topic", JSON.toJSONString(event));
    }
}

// 消息服务消费者
@Service
public class NotificationConsumer {
    
    @KafkaListener(topics = "payment-success-topic")
    public void handlePaymentSuccess(String message) {
        PaymentSuccessEvent event = JSON.parseObject(message, PaymentSuccessEvent.class);
        
        // 发送短信通知
        smsService.sendSms(event.getUserId(), "支付成功!");
        
        // 发放优惠券
        couponService.grantCoupon(event.getUserId());
        
        // 更新积分
        pointsService.addPoints(event.getUserId(), event.getAmount());
        
        // 发送物流通知
        logisticsService.notifyShipment(event.getOrderId());
    }
}

总结

通过谢飞机的面试场景,我们深入解析了电商微服务架构中的核心技术:

  1. 微服务架构:服务拆分、注册发现、API网关、服务间通信
  2. 缓存策略:缓存穿透/击穿/雪崩解决方案、Redis持久化
  3. 数据一致性:分布式事务(Seata)、本地消息表、事务消息
  4. 高并发设计:Kafka削峰填谷、库存原子扣减、限流熔断
  5. 异步处理:事件驱动、消息队列、最终一致性

这些技术点在实际的电商系统中都有广泛应用,掌握这些原理和实现方式,能够帮助我们设计和构建稳定、高性能的微服务系统。希望这篇文章能够帮助大家更好地理解电商微服务架构的核心技术!


参考资料:

  • Spring Cloud官方文档
  • Spring Boot实战
  • Redis设计与实现
  • Kafka权威指南
  • 阿里巴巴Java开发手册
相关推荐
lpfasd1232 小时前
Spring Boot 4.0 新特性全解析 + 实操指南
java·spring boot·后端
C++chaofan2 小时前
JUC 并发编程从入门到精通(超详细笔记 + 实战案例)
java·jvm·spring boot·redis·后端·并发·juc
万象.2 小时前
redis通用命令与数据结构
数据结构·数据库·redis
小马爱打代码2 小时前
Spring Boot Actuator 学习笔记
spring boot·笔记·学习
java_logo2 小时前
Docker 拉取部署 OpenJDK 全指南:替代方案、实操步骤与最佳实践
spring cloud·docker·openjdk·openjdk部署·docker部署openjdk·openjdk部署文档·openjdk部署教程
syounger3 小时前
从本地到云:如何做出正确的 SAP ERP 云化选择
运维·微服务
lpfasd1233 小时前
Spring AI 集成国内大模型实战:千问/豆包(含多模态)+ Spring Boot 4.0.1 全攻略
人工智能·spring boot·spring
予枫的编程笔记3 小时前
【Java 进阶3】Kafka从入门到实战:全面解析分布式消息队列的核心与应用
java·分布式·kafka
利刃大大12 小时前
【SpringBoot】Spring事务 && @Transactional详解 && Spring事务失效问题
spring boot·spring·事务