为什么需要微服务?单体架构的困境与演进

引子:一个电商系统的架构抉择 2020年3月,某创业公司CTO王明面临一个艰难的技术决策: 现状: 团队规模:15个研发 业务现状:日订单量从1万增长到10万 核心痛点:每次发布需要2小时,任何一个小功能的上线都要全量发布,导致上线频率从每周3次降到每周1次 技术选型的两个方向: 继续单体架构:优化现有系统,加机器,做好模块化 切换微服务架构:拆分服务,引入Spring Cloud,重构系统 王明的困惑: “我们真的需要微服务吗?” “微服务能解决什么问题?” “微服务会带来什么代价?” 让我们通过两个完全不同的世界,来理解微服务架构的本质。 一、场景A:单体架构实现(初创期的最优解) 1.1 单体架构的完整代码实现 /** * 电商系统 - 单体架构实现 * 特点:所有功能在一个进程内,共享一个数据库 */ @SpringBootApplication public class ECommerceMonolithApplication { public static void main(String[] args) { SpringApplication.run(ECommerceMonolithApplication.class, args); } } /** * 订单服务(单体架构版本) * 依赖:用户服务、商品服务、库存服务、支付服务 * 特点:所有依赖都在同一个进程内,方法调用 */ @Service @Slf4j @Transactional(rollbackFor = Exception.class) public class OrderService { @Autowired private UserService userService; // 本地方法调用 @Autowired private ProductService productService; // 本地方法调用 @Autowired private InventoryService inventoryService; // 本地方法调用 @Autowired private PaymentService paymentService; // 本地方法调用 @Autowired private OrderRepository orderRepository; // 同一个数据库 /** * 创建订单 * 优势: * 1. 本地方法调用,性能极高(纳秒级) * 2. 本地事务,ACID保证强一致性 * 3. 调试方便,堆栈清晰 * * 问题: * 1. 单点故障:任何一个模块崩溃,整个系统不可用 * 2. 部署耦合:改一行代码,整个系统重启 * 3. 技术栈绑定:整个系统必须用同一种语言、框架 * 4. 资源竞争:所有模块共享JVM内存、CPU */ public Order createOrder(CreateOrderRequest request) { // ========== 1. 用户验证(本地方法调用,1ms) ========== User user = userService.getUserById(request.getUserId()); if (user == null) { throw new BusinessException("用户不存在"); } if (user.getStatus() != UserStatus.ACTIVE) { throw new BusinessException("用户状态异常"); } // ========== 2. 商品查询(本地方法调用,2ms) ========== Product product = productService.getProductById(request.getProductId()); if (product == null) { throw new BusinessException("商品不存在"); } if (product.getStatus() != ProductStatus.ON_SALE) { throw new BusinessException("商品已下架"); } // ========== 3. 库存扣减(本地方法调用,3ms) ========== boolean deductSuccess = inventoryService.deduct( product.getId(), request.getQuantity() ); if (!deductSuccess) { throw new BusinessException("库存不足"); } // ========== 4. 创建订单(本地数据库写入,5ms) ========== Order order = Order.builder() .orderNo(generateOrderNo()) .userId(user.getId()) .productId(product.getId()) .productName(product.getName()) .quantity(request.getQuantity()) .price(product.getPrice()) .amount(product.getPrice().multiply( new BigDecimal(request.getQuantity()) )) .status(OrderStatus.UNPAID) .createTime(LocalDateTime.now()) .build(); order = orderRepository.save(order); // ========== 5. 调用支付(本地方法调用,10ms) ========== boolean paymentSuccess = paymentService.pay( order.getOrderNo(), order.getAmount() ); if (!paymentSuccess) { throw new BusinessException("支付失败"); } // ========== 6. 更新订单状态(本地数据库更新,2ms) ========== order.setStatus(OrderStatus.PAID); order.setPayTime(LocalDateTime.now()); order = orderRepository.save(order); log.info("订单创建成功: orderNo={}, amount={}", order.getOrderNo(), order.getAmount()); // 总耗时约23ms(都是本地调用) return order; } /** * 生成订单号 */ private String generateOrderNo() { return "ORD" + System.currentTimeMillis() + ThreadLocalRandom.current().nextInt(1000); } } /** * 用户服务 */ @Service public class UserService { @Autowired private UserRepository userRepository; public User getUserById(Long userId) { return userRepository.findById(userId).orElse(null); } } /** * 商品服务 */ @Service public class ProductService { @Autowired private ProductRepository productRepository; public Product getProductById(Long productId) { return productRepository.findById(productId).orElse(null); } } /** * 库存服务 */ @Service public class InventoryService { @Autowired private InventoryRepository inventoryRepository; /** * 扣减库存 * 优势:本地事务,强一致性保证 */ public boolean deduct(Long productId, Integer quantity) { Inventory inventory = inventoryRepository.findByProductId(productId); if (inventory == null || inventory.getStock() < quantity) { return false; } inventory.setStock(inventory.getStock() - quantity); inventoryRepository.save(inventory); return true; } } /** * 支付服务 */ @Service public class PaymentService { @Autowired private PaymentRepository paymentRepository; /** * 支付 * 优势:本地事务,要么都成功,要么都失败 */ public boolean pay(String orderNo, BigDecimal amount) { // 调用第三方支付(这里模拟) boolean paySuccess = callThirdPartyPayment(orderNo, amount); if (paySuccess) { // 记录支付流水 Payment payment = Payment.builder() .orderNo(orderNo) .amount(amount) .status(PaymentStatus.SUCCESS) .payTime(LocalDateTime.now()) .build(); paymentRepository.save(payment); } return paySuccess; } private boolean callThirdPartyPayment(String orderNo, BigDecimal amount) { // 模拟第三方支付调用 return true; } } /** * 数据库实体:订单 */ @Entity @Table(name = "t_order") @Data @Builder public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String orderNo; private Long userId; private Long productId; private String productName; private Integer quantity; private BigDecimal price; private BigDecimal amount; @Enumerated(EnumType.STRING) private OrderStatus status; private LocalDateTime createTime; private LocalDateTime payTime; } /** * 数据库实体:用户、商品、库存、支付记录 * (省略具体实现) */ 1.2 单体架构的项目结构 ecommerce-monolith/ ├── src/main/java/com/example/ecommerce/ │ ├── ECommerceMonolithApplication.java # 启动类 │ ├── controller/ # 控制器层 │ │ ├── OrderController.java │ │ ├── UserController.java │ │ ├── ProductController.java │ │ └── InventoryController.java │ ├── service/ # 服务层 │ │ ├── OrderService.java # 订单服务 │ │ ├── UserService.java # 用户服务 │ │ ├── ProductService.java # 商品服务 │ │ ├── InventoryService.java # 库存服务 │ │ └── PaymentService.java # 支付服务 │ ├── repository/ # 数据访问层 │ │ ├── OrderRepository.java │ │ ├── UserRepository.java │ │ ├── ProductRepository.java │ │ ├── InventoryRepository.java │ │ └── PaymentRepository.java │ ├── entity/ # 实体层 │ │ ├── Order.java │ │ ├── User.java │ │ ├── Product.java │ │ ├── Inventory.java │ │ └── Payment.java │ └── config/ # 配置类 │ ├── DataSourceConfig.java │ └── TransactionConfig.java ├── src/main/resources/ │ ├── application.yml # 配置文件 │ └── db/migration/ # 数据库脚本 │ └── V1__init_schema.sql └── pom.xml # Maven配置 部署方式: 1. 打包:mvn clean package → ecommerce-monolith.jar(200MB) 2. 部署:java -jar ecommerce-monolith.jar 3. 运行:单个JVM进程,占用2GB内存 4. 数据库:MySQL单实例,5张表在同一个库 1.3 单体架构的核心特点 维度 特点 优势 劣势 部署 单个war/jar包 部署简单,运维成本低 改一行代码,全量重启 调用方式 本地方法调用 性能极高(纳秒级) 单点故障,一损俱损 事务 本地事务(ACID) 强一致性,简单可靠 无法独立扩展单个模块 技术栈 统一技术栈 团队技能统一,学习成本低 技术升级困难,框架绑定 开发效率 代码在同一个工程 IDE调试方便,定位问题快 代码库膨胀,启动变慢 团队协作 共享代码库 代码复用容易 代码冲突频繁,发布排队 二、场景B:微服务架构实现(规模化后的必然选择) 2.1 微服务架构的完整代码实现 /** * 订单服务(微服务架构版本) * 特点:独立进程,独立数据库,通过RPC调用其他服务 */ @SpringBootApplication @EnableDiscoveryClient // 服务注册 @EnableFeignClients // 远程调用 public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } /** * 订单服务实现 * 依赖:远程调用用户服务、商品服务、库存服务、支付服务 */ @Service @Slf4j public class OrderService { @Autowired private UserServiceClient userServiceClient; // 远程调用(HTTP/gRPC) @Autowired private ProductServiceClient productServiceClient; // 远程调用 @Autowired private InventoryServiceClient inventoryServiceClient; // 远程调用 @Autowired private PaymentServiceClient paymentServiceClient; // 远程调用 @Autowired private OrderRepository orderRepository; // 独立数据库 @Autowired private RocketMQTemplate rocketMQTemplate; // 消息队列 /** * 创建订单(微服务版本) * * 优势: * 1. 服务独立部署:订单服务可以独立发布,不影响其他服务 * 2. 技术栈自由:订单服务用Java,用户服务可以用Go,商品服务可以用Python * 3. 独立扩展:订单服务压力大,可以只扩容订单服务 * 4. 故障隔离:支付服务挂了,不影响订单创建(降级返回"支付中") * * 挑战: * 1. 网络调用:性能下降(本地纳秒级 → 远程毫秒级) * 2. 分布式事务:无法保证强一致性(ACID → BASE) * 3. 调用链路长:5个服务,任何一个超时都影响整体 * 4. 运维复杂:5个服务 × 3个环境 = 15套部署 */ public Order createOrder(CreateOrderRequest request) { // ========== 1. 远程调用用户服务(网络调用,10ms + 超时风险) ========== try { UserDTO user = userServiceClient.getUserById(request.getUserId()); if (user == null || user.getStatus() != UserStatus.ACTIVE) { throw new BusinessException("用户不存在或状态异常"); } } catch (FeignException e) { log.error("调用用户服务失败: {}", e.getMessage()); throw new BusinessException("用户服务不可用"); } // ========== 2. 远程调用商品服务(网络调用,15ms + 超时风险) ========== ProductDTO product; try { product = productServiceClient.getProductById(request.getProductId()); if (product == null || product.getStatus() != ProductStatus.ON_SALE) { throw new BusinessException("商品不存在或已下架"); } } catch (FeignException e) { log.error("调用商品服务失败: {}", e.getMessage()); throw new BusinessException("商品服务不可用"); } // ========== 3. 远程调用库存服务(网络调用,20ms + 超时风险) ========== boolean deductSuccess; try { deductSuccess = inventoryServiceClient.deduct( product.getId(), request.getQuantity() ); if (!deductSuccess) { throw new BusinessException("库存不足"); } } catch (FeignException e) { log.error("调用库存服务失败: {}", e.getMessage()); throw new BusinessException("库存服务不可用"); } // ========== 4. 创建订单(本地数据库写入,5ms) ========== Order order = Order.builder() .orderNo(generateOrderNo()) .userId(request.getUserId()) .productId(product.getId()) .productName(product.getName()) .quantity(request.getQuantity()) .price(product.getPrice()) .amount(product.getPrice().multiply( new BigDecimal(request.getQuantity()) )) .status(OrderStatus.UNPAID) .createTime(LocalDateTime.now()) .build(); order = orderRepository.save(order); // ========== 5. 异步调用支付服务(通过消息队列,解耦) ========== // 不直接调用支付服务,而是发送消息到MQ,支付服务异步消费 PaymentMessage paymentMessage = PaymentMessage.builder() .orderNo(order.getOrderNo()) .amount(order.getAmount()) .build(); rocketMQTemplate.syncSend("PAYMENT_TOPIC", paymentMessage); log.info("订单创建成功: orderNo={}, amount={}", order.getOrderNo(), order.getAmount()); // 总耗时约50ms(网络调用 + 超时重试) // 相比单体架构的23ms,慢了2倍,但换来了独立部署、独立扩展、故障隔离 return order; } /** * 生成订单号(分布式唯一ID) * 单体架构:可以用数据库自增ID * 微服务架构:需要用雪花算法、UUID等分布式ID生成策略 */ private String generateOrderNo() { // 雪花算法生成分布式唯一ID return "ORD" + SnowflakeIdWorker.generateId(); } } /** * 用户服务客户端(Feign声明式HTTP客户端) */ @FeignClient( name = "user-service", // 服务名(从注册中心获取) fallback = UserServiceFallback.class // 降级策略 ) public interface UserServiceClient { @GetMapping("/api/users/{userId}") UserDTO getUserById(@PathVariable("userId") Long userId); } /** * 用户服务降级策略(熔断后的备选方案) */ @Component public class UserServiceFallback implements UserServiceClient { @Override public UserDTO getUserById(Long userId) { log.warn("用户服务调用失败,触发降级策略"); // 返回一个默认用户,或者抛出异常 throw new BusinessException("用户服务不可用,请稍后重试"); } } /** * 商品服务客户端 */ @FeignClient( name = "product-service", fallback = ProductServiceFallback.class ) public interface ProductServiceClient { @GetMapping("/api/products/{productId}") ProductDTO getProductById(@PathVariable("productId") Long productId); } /** * 库存服务客户端 */ @FeignClient( name = "inventory-service", fallback = InventoryServiceFallback.class ) public interface InventoryServiceClient { @PostMapping("/api/inventory/deduct") boolean deduct(@RequestParam("productId") Long productId, @RequestParam("quantity") Integer quantity); } /** * 支付服务(独立的微服务,监听MQ消息) */ @Service @Slf4j public class PaymentService { @Autowired private PaymentRepository paymentRepository; @Autowired private OrderServiceClient orderServiceClient; /** * 监听支付消息(异步处理) * 优势:解耦订单服务和支付服务,支付失败不影响订单创建 */ @RocketMQMessageListener( topic = "PAYMENT_TOPIC", consumerGroup = "payment-consumer-group" ) public class PaymentMessageListener implements RocketMQListener<PaymentMessage> { @Override public void onMessage(PaymentMessage message) { log.info("接收到支付消息: {}", message); try { // 调用第三方支付 boolean paySuccess = callThirdPartyPayment( message.getOrderNo(), message.getAmount() ); if (paySuccess) { // 记录支付流水 Payment payment = Payment.builder() .orderNo(message.getOrderNo()) .amount(message.getAmount()) .status(PaymentStatus.SUCCESS) .payTime(LocalDateTime.now()) .build(); paymentRepository.save(payment); // 回调订单服务,更新订单状态 orderServiceClient.updateOrderStatus( message.getOrderNo(), OrderStatus.PAID ); log.info("支付成功: orderNo={}", message.getOrderNo()); } else { log.error("支付失败: orderNo={}", message.getOrderNo()); // 支付失败,可以重试或者发送通知 } } catch (Exception e) { log.error("支付处理异常: orderNo={}, error={}", message.getOrderNo(), e.getMessage()); // 异常时,消息会重新入队,重试机制 throw new RuntimeException("支付处理失败", e); } } } private boolean callThirdPartyPayment(String orderNo, BigDecimal amount) { // 模拟第三方支付调用 return true; } } 2.2 微服务架构的项目结构 microservices-ecommerce/ ├── order-service/ # 订单服务 │ ├── src/main/java/com/example/order/ │ │ ├── OrderServiceApplication.java # 启动类 │ │ ├── controller/OrderController.java │ │ ├── service/OrderService.java │ │ ├── repository/OrderRepository.java │ │ ├── entity/Order.java │ │ ├── client/ # Feign客户端 │ │ │ ├── UserServiceClient.java │ │ │ ├── ProductServiceClient.java │ │ │ ├── InventoryServiceClient.java │ │ │ └── PaymentServiceClient.java │ │ └── config/ # 配置类 │ ├── src/main/resources/ │ │ └── application.yml # 订单服务配置 │ └── pom.xml # 独立的Maven配置 │ ├── user-service/ # 用户服务 │ ├── src/main/java/com/example/user/ │ │ ├── UserServiceApplication.java │ │ ├── controller/UserController.java │ │ ├── service/UserService.java │ │ ├── repository/UserRepository.java │ │ └── entity/User.java │ ├── src/main/resources/ │ │ └── application.yml │ └── pom.xml │ ├── product-service/ # 商品服务 │ ├── src/main/java/com/example/product/ │ │ ├── ProductServiceApplication.java │ │ ├── controller/ProductController.java │ │ ├── service/ProductService.java │ │ ├── repository/ProductRepository.java │ │ └── entity/Product.java │ ├── src/main/resources/ │ │ └── application.yml │ └── pom.xml │ ├── inventory-service/ # 库存服务 │ ├── src/main/java/com/example/inventory/ │ │ ├── InventoryServiceApplication.java │ │ ├── controller/InventoryController.java │ │ ├── service/InventoryService.java │ │ ├── repository/InventoryRepository.java │ │ └── entity/Inventory.java │ ├── src/main/resources/ │ │ └── application.yml │ └── pom.xml │ ├── payment-service/ # 支付服务 │ ├── src/main/java/com/example/payment/ │ │ ├── PaymentServiceApplication.java │ │ ├── service/PaymentService.java │ │ ├── repository/PaymentRepository.java │ │ ├── entity/Payment.java │ │ └── listener/PaymentMessageListener.java │ ├── src/main/resources/ │ │ └── application.yml │ └── pom.xml │ ├── common/ # 公共模块 │ ├── src/main/java/com/example/common/ │ │ ├── dto/ # 数据传输对象 │ │ ├── exception/ # 异常定义 │ │ └── util/ # 工具类 │ └── pom.xml │ ├── gateway/ # API网关(Spring Cloud Gateway) │ ├── src/main/java/com/example/gateway/ │ │ ├── GatewayApplication.java │ │ └── config/GatewayConfig.java │ └── pom.xml │ └── registry/ # 服务注册中心(Nacos) └── nacos-server/ 部署方式: 1. 打包:每个服务独立打包 → order-service.jar, user-service.jar... 2. 部署:每个服务独立部署(可以部署在不同的机器上) 3. 运行:5个JVM进程,每个占用1GB内存(总共5GB) 4. 数据库:5个独立的MySQL数据库(或5个独立的Schema) 2.3 微服务架构的核心特点 维度 特点 优势 劣势 部署 独立部署单元 改一行代码,只重启一个服务 运维复杂度高,需要容器编排 调用方式 远程调用(HTTP/gRPC) 故障隔离,服务独立演进 性能下降(纳秒→毫秒),网络不可靠 事务 分布式事务(BASE) 独立扩展,高可用 最终一致性,业务逻辑复杂 技术栈 多语言异构 技术自由,选择最合适的技术 技能要求高,学习成本大 开发效率 代码分散在多个工程 独立迭代,避免冲突 调试困难,链路追踪复杂 团队协作 按服务划分团队 团队自治,减少沟通成本 接口约定复杂,版本管理困难 三、数据对比:单体 vs 微服务 3.1 性能对比 指标 单体架构 微服务架构 差异分析 接口响应时间 23ms 50ms 微服务慢2倍(网络调用开销) QPS 5000 3000 微服务下降40%(网络+序列化) CPU使用率 60% 70% 微服务高10%(序列化+网络) 内存占用 2GB(单进程) 5GB(5进程) 微服务多2.5倍 启动时间 120s 30s/服务 微服务单个服务更快 关键发现: ...

2025-11-03 · maneng

服务拆分第一性原理:从领域驱动到康威定律

引子:一次失败的微服务拆分 2019年某月,某金融科技公司CTO李明决定将单体应用拆分为微服务。 拆分方案(按技术层拆分): 前端服务:负责所有页面渲染 业务服务:负责所有业务逻辑 数据服务:负责所有数据访问 3个月后的结果: 部署次数:从每周1次降到每月1次(更慢了!) 数据库连接:3个服务共享同一个数据库(还是耦合) 代码冲突:业务服务有50个类,15个人修改,冲突率40%(比单体更高) 故障影响:数据服务挂了,整个系统不可用(单点依旧存在) 李明的困惑: “我们明明拆分了,为什么比单体还糟糕?” “什么才是正确的拆分方式?” “服务边界应该如何划分?” 这个案例揭示了一个核心问题:拆分微服务的本质不是"拆分技术层",而是"拆分业务领域"。 让我们从第一性原理出发,系统化解答这个问题。 一、服务拆分的本质问题 1.1 什么是服务边界? 服务边界的定义: 物理边界:独立的进程、独立的数据库、独立的部署单元 逻辑边界:独立的业务职责、独立的团队所有权、独立的变更频率 好的服务边界的三个特征: 高内聚:服务内部的功能紧密相关(订单创建、订单查询、订单取消都在订单服务内) 低耦合:服务之间的依赖最小化(订单服务不依赖评论服务) 独立演进:服务可以独立开发、测试、部署(订单服务升级,不影响商品服务) 1.2 拆分的三个核心目标 目标1:独立部署 单体架构的问题: 改订单服务的一个Bug,整个系统重启 部署时间:120分钟 微服务的解决方案: 改订单服务的Bug,只重启订单服务 部署时间:15分钟 目标2:独立扩展 单体架构的问题: 订单服务压力大,整体扩容,浪费80%资源 微服务的解决方案: 订单服务压力大,只扩容订单服务 目标3:独立演进 单体架构的问题: 整个系统必须用同一技术栈(Java + Spring) 微服务的解决方案: 订单服务用Java,推荐服务用Python,搜索服务用Go 1.3 拆分的代价 不要忘记:拆分微服务是有代价的! 代价维度 单体架构 微服务架构 增加幅度 网络调用延迟 0ms(本地调用) 10-50ms +∞ 事务复杂度 ACID(本地事务) BASE(分布式事务) +10倍 运维复杂度 1个服务 100+服务 +100倍 问题定位难度 单进程堆栈 链路追踪 +5倍 核心原则:只有当拆分的收益 > 拆分的成本时,才应该拆分! ...

2025-11-03 · maneng

MySQL第一性原理:为什么我们需要数据库?

引言 “如果你不能简单地解释一件事,说明你还没有真正理解它。” —— 理查德·费曼 作为一名后端开发者,你一定写过这样的代码: @Autowired private UserRepository userRepository; public User findUser(Long id) { return userRepository.findById(id); } 这行代码背后,数据库帮你做了什么? 持久化存储:数据写入磁盘,重启不丢失 快速检索:1亿条数据中找到目标行,只需10微秒 并发控制:1万个并发请求,数据不会错乱 事务保证:转账操作要么全成功,要么全失败 故障恢复:系统崩溃后,数据可以完整恢复 但你有没有想过: 为什么不用文件存储数据?(txt、csv、json) 为什么不用内存存储数据?(HashMap、Redis) 为什么一定要用MySQL这样的关系型数据库? 今天,我们从第一性原理出发,通过对比文件、内存、MySQL三种存储方案,深度剖析数据库解决的核心问题。 本文不会教你怎么写SQL,而是回答为什么需要数据库。 一、引子:用户注册功能的三种实现 让我们从一个最简单的需求开始:用户注册功能。 需求: 用户注册时,存储用户名和密码 检查用户名是否已存在 用户登录时,验证用户名和密码 按注册时间范围查询用户 性能要求: 支持100万用户 注册和登录响应时间 < 100ms 支持1000并发 我们将用三种方式实现,看看它们的差异。 1.1 场景A:文件存储(users.txt) 实现思路:将用户数据存储在文本文件中,每行一个用户,逗号分隔字段。 /** * 用户服务 - 文件存储实现 */ public class FileUserService { private static final String FILE_PATH = "users.txt"; /** * 注册用户(追加到文件末尾) */ public void register(String username, String password) { // 1. 检查用户名是否已存在 if (exists(username)) { throw new RuntimeException("用户名已存在"); } // 2. 追加到文件 try (FileWriter fw = new FileWriter(FILE_PATH, true)) { String line = username + "," + hashPassword(password) + "," + System.currentTimeMillis() + "\n"; fw.write(line); } catch (IOException e) { throw new RuntimeException("注册失败", e); } } /** * 检查用户名是否存在(全文件扫描) */ public boolean exists(String username) { try (BufferedReader br = new BufferedReader(new FileReader(FILE_PATH))) { String line; while ((line = br.readLine()) != null) { // O(n) 全表扫描 String[] parts = line.split(","); if (parts[0].equals(username)) { return true; } } } catch (IOException e) { e.printStackTrace(); } return false; } /** * 登录验证(全文件扫描) */ public boolean login(String username, String password) { String hashedPassword = hashPassword(password); try (BufferedReader br = new BufferedReader(new FileReader(FILE_PATH))) { String line; while ((line = br.readLine()) != null) { // O(n) 全表扫描 String[] parts = line.split(","); if (parts[0].equals(username) && parts[1].equals(hashedPassword)) { return true; } } } catch (IOException e) { e.printStackTrace(); } return false; } /** * 按注册时间范围查询(全文件扫描+过滤) */ public List<User> findByRegisteredDateRange(long startTime, long endTime) { List<User> result = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(FILE_PATH))) { String line; while ((line = br.readLine()) != null) { // O(n) 全表扫描 String[] parts = line.split(","); long registeredTime = Long.parseLong(parts[2]); if (registeredTime >= startTime && registeredTime <= endTime) { result.add(new User(parts[0], parts[1], registeredTime)); } } } catch (IOException e) { e.printStackTrace(); } return result; } private String hashPassword(String password) { // 简化版,实际应该用BCrypt return Integer.toString(password.hashCode()); } } 文件内容示例: ...

2025-11-03 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...