Spring Boot 数据缓存与性能优化

Spring Boot 数据缓存与性能优化

Spring Boot 数据缓存与性能优化

在这里插入图片描述
23.1 学习目标与重点提示

学习目标:掌握Spring Boot数据缓存与性能优化的核心概念与使用方法,包括数据缓存的定义与特点、Spring Boot与数据缓存的集成、Spring Boot与数据缓存的配置、Spring Boot与数据缓存的基本方法、Spring Boot的实际应用场景,学会在实际开发中处理数据缓存与性能优化问题。
重点:数据缓存的定义与特点Spring Boot与数据缓存的集成Spring Boot与数据缓存的配置Spring Boot与数据缓存的基本方法Spring Boot的实际应用场景

23.2 数据缓存概述

数据缓存是Java开发中的重要组件。

23.2.1 数据缓存的定义

定义:数据缓存是一种存储机制,用于将常用数据存储在高速存储设备中,以便快速访问。
作用

  • 提高应用程序的性能。
  • 减少数据库的访问次数。
  • 提高用户体验。

常见的数据缓存

  • EhCache:Apache EhCache是一款开源的缓存库。
  • Caffeine:Caffeine是一款高性能的缓存库。
  • Redis:Redis是一款开源的缓存服务器。

✅ 结论:数据缓存是一种存储机制,作用是提高应用程序的性能、减少数据库的访问次数、提高用户体验。

23.2.2 数据缓存的特点

定义:数据缓存的特点是指数据缓存的特性。
特点

  • 高速访问:数据缓存提供高速访问。
  • 数据一致性:数据缓存提供数据一致性。
  • 可扩展性:数据缓存可以扩展到多个应用程序之间的缓存通信。
  • 易用性:数据缓存提供易用的编程模型。

✅ 结论:数据缓存的特点包括高速访问、数据一致性、可扩展性、易用性。

23.3 Spring Boot与数据缓存的集成

Spring Boot与数据缓存的集成是Java开发中的重要内容。

23.3.1 集成EhCache的步骤

定义:集成EhCache的步骤是指使用Spring Boot与EhCache集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置EhCache。
  4. 创建数据访问层。
  5. 创建业务层。
  6. 创建控制器类。
  7. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- EhCache依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的EhCache配置:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console # EhCache配置 spring.cache.type=ehcache spring.cache.ehcache.config=classpath:ehcache.xml 

ehcache.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?><ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><defaultCachemaxEntriesLocalHeap="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"></defaultCache><cachename="productCache"maxEntriesLocalHeap="1000"eternal="false"timeToIdleSeconds="60"timeToLiveSeconds="60"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"></cache></ehcache>

实体类:

importjavax.persistence.*;@Entity@Table(name ="product")publicclassProduct{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}

Repository接口:

importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;@RepositorypublicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{}

Service类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.cache.annotation.CacheEvict;importorg.springframework.cache.annotation.CachePut;importorg.springframework.cache.annotation.Cacheable;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductaddProduct(Product product){return productRepository.save(product);}@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductupdateProduct(Product product){return productRepository.save(product);}@Transactional@CacheEvict(value ="productCache", key ="#id")publicvoiddeleteProduct(Long id){ productRepository.deleteById(id);}@Transactional(readOnly =true)@Cacheable(value ="productCache", key ="#id")publicProductgetProductById(Long id){System.out.println("从数据库查询产品:"+ id);return productRepository.findById(id).orElse(null);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.List;@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductService productService;@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productService.addProduct(product);}@PutMapping("/{id}")publicProductupdateProduct(@PathVariableLong id,@RequestBodyProduct product){ product.setId(id);return productService.updateProduct(product);}@DeleteMapping("/{id}")publicvoiddeleteProduct(@PathVariableLong id){ productService.deleteProduct(id);}@GetMapping("/{id}")publicProductgetProductById(@PathVariableLong id){return productService.getProductById(id);}}

应用启动类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cache.annotation.EnableCaching;@SpringBootApplication@EnableCachingpublicclassProductApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ProductApplication.class, args);}@AutowiredprivateProductService productService;publicvoidrun(String... args){// 初始化数据 productService.addProduct(newProduct("P001","手机",1000.0,100)); productService.addProduct(newProduct("P002","电脑",5000.0,50)); productService.addProduct(newProduct("P003","电视",3000.0,80)); productService.addProduct(newProduct("P004","手表",500.0,200)); productService.addProduct(newProduct("P005","耳机",300.0,150));}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestGetProductById(){Product product1 = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(product1).isNotNull();assertThat(product1.getProductId()).isEqualTo("P001");Product product2 = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(product2).isNotNull();assertThat(product2.getProductId()).isEqualTo("P001");}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product savedProduct = restTemplate.postForObject("http://localhost:"+ port +"/api/products/", product,Product.class);assertThat(savedProduct).isNotNull();assertThat(savedProduct.getProductId()).isEqualTo("P006");}@TestvoidtestUpdateProduct(){Product product =newProduct("P001","手机",1500.0,120); restTemplate.put("http://localhost:"+ port +"/api/products/1", product);Product updatedProduct = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(updatedProduct).isNotNull();assertThat(updatedProduct.getPrice()).isEqualTo(1500.0);}@TestvoidtestDeleteProduct(){ restTemplate.delete("http://localhost:"+ port +"/api/products/2");Product product = restTemplate.getForObject("http://localhost:"+ port +"/api/products/2",Product.class);assertThat(product).isNull();}}

✅ 结论:集成EhCache的步骤包括创建Spring Boot项目、添加所需的依赖、配置EhCache、创建数据访问层、创建业务层、创建控制器类、测试应用。

23.4 Spring Boot与数据缓存的配置

Spring Boot与数据缓存的配置是Java开发中的重要内容。

23.4.1 配置Caffeine缓存

定义:配置Caffeine缓存是指使用Spring Boot与Caffeine缓存集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置Caffeine缓存。
  4. 创建数据访问层。
  5. 创建业务层。
  6. 创建控制器类。
  7. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- Caffeine依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的Caffeine缓存配置:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console # Caffeine缓存配置 spring.cache.type=caffeine spring.cache.caffeine.spec=maximumSize=1000,expireAfterWrite=60s 

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.List;@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductService productService;@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productService.addProduct(product);}@PutMapping("/{id}")publicProductupdateProduct(@PathVariableLong id,@RequestBodyProduct product){ product.setId(id);return productService.updateProduct(product);}@DeleteMapping("/{id}")publicvoiddeleteProduct(@PathVariableLong id){ productService.deleteProduct(id);}@GetMapping("/{id}")publicProductgetProductById(@PathVariableLong id){return productService.getProductById(id);}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestGetProductById(){Product product1 = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(product1).isNotNull();assertThat(product1.getProductId()).isEqualTo("P001");Product product2 = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(product2).isNotNull();assertThat(product2.getProductId()).isEqualTo("P001");}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product savedProduct = restTemplate.postForObject("http://localhost:"+ port +"/api/products/", product,Product.class);assertThat(savedProduct).isNotNull();assertThat(savedProduct.getProductId()).isEqualTo("P006");}@TestvoidtestUpdateProduct(){Product product =newProduct("P001","手机",1500.0,120); restTemplate.put("http://localhost:"+ port +"/api/products/1", product);Product updatedProduct = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(updatedProduct).isNotNull();assertThat(updatedProduct.getPrice()).isEqualTo(1500.0);}@TestvoidtestDeleteProduct(){ restTemplate.delete("http://localhost:"+ port +"/api/products/2");Product product = restTemplate.getForObject("http://localhost:"+ port +"/api/products/2",Product.class);assertThat(product).isNull();}}

✅ 结论:配置Caffeine缓存是指使用Spring Boot与Caffeine缓存集成的方法,步骤包括创建Spring Boot项目、添加所需的依赖、配置Caffeine缓存、创建数据访问层、创建业务层、创建控制器类、测试应用。

23.5 Spring Boot与数据缓存的基本方法

Spring Boot与数据缓存的基本方法包括使用@Cacheable、@CachePut、@CacheEvict注解。

23.5.1 使用@Cacheable注解

定义:使用@Cacheable注解是指Spring Boot与数据缓存集成的基本方法之一。
作用

  • 实现数据缓存。
  • 提高应用程序的性能。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.cache.annotation.Cacheable;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@Transactional(readOnly =true)@Cacheable(value ="productCache", key ="#id")publicProductgetProductById(Long id){System.out.println("从数据库查询产品:"+ id);return productRepository.findById(id).orElse(null);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}

✅ 结论:使用@Cacheable注解是指Spring Boot与数据缓存集成的基本方法之一,作用是实现数据缓存、提高应用程序的性能。

23.5.2 使用@CachePut注解

定义:使用@CachePut注解是指Spring Boot与数据缓存集成的基本方法之一。
作用

  • 实现数据缓存。
  • 提高应用程序的性能。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.cache.annotation.CachePut;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductaddProduct(Product product){return productRepository.save(product);}@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductupdateProduct(Product product){return productRepository.save(product);}@Transactional(readOnly =true)@Cacheable(value ="productCache", key ="#id")publicProductgetProductById(Long id){System.out.println("从数据库查询产品:"+ id);return productRepository.findById(id).orElse(null);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}

✅ 结论:使用@CachePut注解是指Spring Boot与数据缓存集成的基本方法之一,作用是实现数据缓存、提高应用程序的性能。

23.5.3 使用@CacheEvict注解

定义:使用@CacheEvict注解是指Spring Boot与数据缓存集成的基本方法之一。
作用

  • 实现数据缓存。
  • 提高应用程序的性能。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.cache.annotation.CacheEvict;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductaddProduct(Product product){return productRepository.save(product);}@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductupdateProduct(Product product){return productRepository.save(product);}@Transactional@CacheEvict(value ="productCache", key ="#id")publicvoiddeleteProduct(Long id){ productRepository.deleteById(id);}@Transactional(readOnly =true)@Cacheable(value ="productCache", key ="#id")publicProductgetProductById(Long id){System.out.println("从数据库查询产品:"+ id);return productRepository.findById(id).orElse(null);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}

✅ 结论:使用@CacheEvict注解是指Spring Boot与数据缓存集成的基本方法之一,作用是实现数据缓存、提高应用程序的性能。

23.6 Spring Boot的实际应用场景

在实际开发中,Spring Boot数据缓存与性能优化的应用场景非常广泛,如:

  • 实现产品信息的缓存。
  • 实现用户信息的缓存。
  • 实现订单信息的缓存。
  • 实现日志信息的缓存。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cache.annotation.EnableCaching;@SpringBootApplication@EnableCachingpublicclassProductApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ProductApplication.class, args);}@AutowiredprivateProductService productService;publicvoidrun(String... args){// 初始化数据 productService.addProduct(newProduct("P001","手机",1000.0,100)); productService.addProduct(newProduct("P002","电脑",5000.0,50)); productService.addProduct(newProduct("P003","电视",3000.0,80)); productService.addProduct(newProduct("P004","手表",500.0,200)); productService.addProduct(newProduct("P005","耳机",300.0,150));}}@ServiceclassProductService{@AutowiredprivateProductRepository productRepository;@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductaddProduct(Product product){return productRepository.save(product);}@Transactional@CachePut(value ="productCache", key ="#product.id")publicProductupdateProduct(Product product){return productRepository.save(product);}@Transactional@CacheEvict(value ="productCache", key ="#id")publicvoiddeleteProduct(Long id){ productRepository.deleteById(id);}@Transactional(readOnly =true)@Cacheable(value ="productCache", key ="#id")publicProductgetProductById(Long id){System.out.println("从数据库查询产品:"+ id);return productRepository.findById(id).orElse(null);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}@RestController@RequestMapping("/api/products")classProductController{@AutowiredprivateProductService productService;@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productService.addProduct(product);}@PutMapping("/{id}")publicProductupdateProduct(@PathVariableLong id,@RequestBodyProduct product){ product.setId(id);return productService.updateProduct(product);}@DeleteMapping("/{id}")publicvoiddeleteProduct(@PathVariableLong id){ productService.deleteProduct(id);}@GetMapping("/{id}")publicProductgetProductById(@PathVariableLong id){return productService.getProductById(id);}}// 测试类@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestGetProductById(){Product product1 = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(product1).isNotNull();assertThat(product1.getProductId()).isEqualTo("P001");Product product2 = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(product2).isNotNull();assertThat(product2.getProductId()).isEqualTo("P001");}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product savedProduct = restTemplate.postForObject("http://localhost:"+ port +"/api/products/", product,Product.class);assertThat(savedProduct).isNotNull();assertThat(savedProduct.getProductId()).isEqualTo("P006");}@TestvoidtestUpdateProduct(){Product product =newProduct("P001","手机",1500.0,120); restTemplate.put("http://localhost:"+ port +"/api/products/1", product);Product updatedProduct = restTemplate.getForObject("http://localhost:"+ port +"/api/products/1",Product.class);assertThat(updatedProduct).isNotNull();assertThat(updatedProduct.getPrice()).isEqualTo(1500.0);}@TestvoidtestDeleteProduct(){ restTemplate.delete("http://localhost:"+ port +"/api/products/2");Product product = restTemplate.getForObject("http://localhost:"+ port +"/api/products/2",Product.class);assertThat(product).isNull();}}

输出结果

  • 访问http://localhost:8080/api/products/1:第一次访问从数据库查询,第二次访问从缓存查询。

控制台输出:

从数据库查询产品:1 

✅ 结论:在实际开发中,Spring Boot数据缓存与性能优化的应用场景非常广泛,需要根据实际问题选择合适的缓存策略。

总结

本章我们学习了Spring Boot数据缓存与性能优化,包括数据缓存的定义与特点、Spring Boot与数据缓存的集成、Spring Boot与数据缓存的配置、Spring Boot与数据缓存的基本方法、Spring Boot的实际应用场景,学会了在实际开发中处理数据缓存与性能优化问题。其中,数据缓存的定义与特点、Spring Boot与数据缓存的集成、Spring Boot与数据缓存的配置、Spring Boot与数据缓存的基本方法、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

Read more

MySQL:事务的理解

MySQL:事务的理解

一、CURD不加控制,会有什么问题  (1)因为,MySQL里面存的是数据,所以很有可能会被多个客户访问,所以mysqld可能一次会接受到多个关于CURD的请求。(2)且mysql内部是采用多线程来完成数据存储等相关工作的,所以必然会存在对数据并发访问的场景      ——>会导致一些多请求并发可能产生的异常结果        比如同行转账,按道理是我减100,你加100,但是因为我是同行所以用的是一张数据库的表,可能我减100的时候还没做完网络或者数据库出问题等其他原因导致没有给你加100,那么整个操作就会出现一个中间过程(我减了但是你没有加),这就有问题,在这种情况下我们允许异常产生,一旦操作没有完成我们应该把减掉的100再加回来,就好像什么都没做,等待下次合适的时候再去转账。这就相当于转账之后不要有中间过程,而是在转的时候一旦出现异常就直接进行回滚,因为不回滚的话就会有问题,必须得回滚保证和初始的状态一样,这就叫我们的回滚操作。在高并发的场景下数据或多或少都会出现这样的问题,所以这也就要求mysql必须要有针对这类问题的解决方案。 二、CURD满足什么属性,能解决上述

By Ne0inhk
Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构

Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构 前言 在鸿蒙(OpenHarmony)生态迈向多端协同、涉及大量轻量级 IOT 设备(如智能穿戴、工业传感器)及微服务透传的背景下,如何实现快速、低开销的 HTTP 通讯,已成为决定应用“响应敏捷度”的关键工程要素。在鸿蒙设备这类强调内存精简与极速启动的环境下,如果应用依然无差别地引入像 Dio 这种包含复杂拦截器、适配器及多重缓存逻辑的“重型网络航母”,由于由于框架初始化开销大、内存足迹(Memory Footprint)偏深,极易由于由于“过度封装”导致边缘设备主线程的瞬间负载过高。 我们需要一种能够剥离样板代码、支持一键 JSON

By Ne0inhk
【终极对决】Kafka vs RabbitMQ:深入剖析消息中间件双雄,附选型指南与代码实战

【终极对决】Kafka vs RabbitMQ:深入剖析消息中间件双雄,附选型指南与代码实战

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[[email protected]] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? * 专栏导航: 码农阿豪系列专栏导航 面试专栏:收集了java相关高频面试题,面试实战总结🍻🎉🖥️ Spring5系列专栏:整理了Spring5重要知识点与实战演练,有案例可直接使用🚀🔧💻 Redis专栏:Redis从零到一学习分享,经验总结,案例实战💐📝💡 全栈系列专栏:海纳百川有容乃大,可能你想要的东西里面都有🤸🌱🚀 目录 * 【终极对决】Kafka vs RabbitMQ:深入剖析消息中间件双雄,附选型指南与代码实战 * 一、核心概念与架构模型图解:两种不同的设计哲学 * RabbitMQ:精密的“路由引擎” * Kafka:

By Ne0inhk
Flutter 组件 activity_files 适配鸿蒙 HarmonyOS 实战:文件活动流治理,构建高性能存储沙箱访问与资产全生命周期管理架构

Flutter 组件 activity_files 适配鸿蒙 HarmonyOS 实战:文件活动流治理,构建高性能存储沙箱访问与资产全生命周期管理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 activity_files 适配鸿蒙 HarmonyOS 实战:文件活动流治理,构建高性能存储沙箱访问与资产全生命周期管理架构 前言 在鸿蒙(OpenHarmony)生态迈向全场景分布式协同、涉及海量多媒体资产处理及严苛应用沙箱(Sandbox)隔离的背景下,如何实现一套既能穿透复杂的层级目录、又能实时追踪文件变更活动且具备极高 I/O 吞吐能力的存储治理架构,已成为决定应用性能广度与数据安全深度。在鸿蒙设备这类强调 AOT 极致性能与受限文件权限周期的环境下,如果应用依然采用陈旧的同步文件读取或缺乏活动追踪的直接 I/O,由于由于频繁的磁盘竞争,极易由于由于“主线程阻塞”或“资产状态不同步”导致用户在管理大型媒体库时发生明显的感知性卡顿。 我们需要一种能够解耦文件路径、支持异步流式追踪(Activity Tracking)且符合鸿蒙分布式文件系统安全范式的操作框架。 activity_files 为 Flutter 开发者引入了“

By Ne0inhk