网站建设卖给别人可以吗,郑州网站seo服务,青岛公司logo设计,国外优秀人像摄影网站二级缓存机制原理详解1. 整体架构MyBatis-Plus二级缓存采用装饰器模式实现#xff0c;核心组件包括#xff1a;Cache接口#xff1a;定义缓存基本操作PerpetualCache#xff1a;基础缓存实现#xff08;HashMap#xff09;装饰器#xff1a;如LruCache、Fif…二级缓存机制原理详解1. 整体架构MyBatis-Plus二级缓存采用装饰器模式实现核心组件包括Cache接口定义缓存基本操作PerpetualCache基础缓存实现HashMap装饰器如LruCache、FifoCache等TransactionalCache事务缓存管理器2. 工作流程初始化阶段解析Mapper XML中的cache配置创建基础缓存实例根据配置添加装饰器查询流程
sequenceDiagramparticipant Clientparticipant SqlSessionparticipant Executorparticipant Cacheparticipant DBClient-SqlSession: 执行查询SqlSession-Executor: query()Executor-Cache: 检查缓存alt 缓存命中Cache--Executor: 返回缓存结果else 缓存未命中Executor-DB: 执行查询DB--Executor: 返回结果Executor-Cache: 缓存结果endExecutor--SqlSession: 返回结果SqlSession--Client: 返回结果
更新流程
sequenceDiagramparticipant Clientparticipant SqlSessionparticipant Executorparticipant Cacheparticipant DBClient-SqlSession: 执行更新SqlSession-Executor: update()Executor-DB: 执行SQLDB--Executor: 返回影响行数Executor-Cache: 清除相关缓存Executor--SqlSession: 返回结果SqlSession--Client: 返回结果
3. 关键实现细节缓存键生成基于Mapper ID 方法参数 SQL 分页等生成唯一键事务支持通过TransactionalCacheManager管理事务提交/回滚时的缓存操作序列化默认使用JVM序列化可配置为其他序列化方式生产案例详细实现步骤案例1电商商品缓存系统基础配置
!-- mybatis-config.xml --
configurationsettingssetting namecacheEnabled valuetrue/!-- 配置缓存序列化方式 --setting namedefaultCacheType valuecom.example.MyCustomCache//settings
/configuration
Mapper配置
!-- ProductMapper.xml --
mapper namespacecom.example.mapper.ProductMappercache typeorg.mybatis.caches.redis.RedisCacheevictionLRUflushInterval300000size1024readOnlyfalse/select idselectById resultTypeProduct useCachetrueSELECT * FROM product WHERE id #{id}/select
/mapper
服务层实现
Service
public class ProductServiceImpl implements ProductService {Autowiredprivate ProductMapper productMapper;// 带缓存穿透保护的查询public Product getProductWithCache(Long id) {// 1. 先查缓存Product product productMapper.selectById(id);if (product ! null) {return product;}// 2. 缓存不存在查数据库product productMapper.selectFromDb(id);if (product null) {// 防止缓存穿透缓存空对象product new Product();product.setId(id);product.setName(NULL_OBJECT);productMapper.cacheNullObject(product);} else {// 放入缓存productMapper.cacheProduct(product);}return product;}Transactionalpublic void updateProduct(Product product) {// 1. 更新数据库productMapper.updateById(product);// 2. 清除缓存productMapper.clearCache(product.getId());// 3. 异步重建缓存CompletableFuture.runAsync(() - {Product freshProduct productMapper.selectFromDb(product.getId());productMapper.cacheProduct(freshProduct);});}
}
自定义Redis缓存实现
public class CustomRedisCache implements Cache {private final String id;private final RedisTemplateString, Object redisTemplate;public CustomRedisCache(String id) {this.id id;this.redisTemplate SpringContextHolder.getBean(redisTemplate);}Overridepublic String getId() {return this.id;}Overridepublic void putObject(Object key, Object value) {// 自定义序列化逻辑redisTemplate.opsForValue().set(generateRedisKey(key), serialize(value),30, TimeUnit.MINUTES // 设置TTL);}// 其他方法实现...
}
案例2多级缓存策略配置多级缓存
Configuration
public class CacheConfig {Beanpublic Cache productCache() {// 一级缓存本地缓存CaffeineCaffeineCache localCache new CaffeineCache(localProductCache,Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(5, TimeUnit.MINUTES).build());// 二级缓存Redis缓存RedisCache redisCache new RedisCache(redisProductCache);// 构建多级缓存return new MultiLevelCache(localCache, redisCache);}
}
多级缓存实现
public class MultiLevelCache implements Cache {private final Cache[] caches;public MultiLevelCache(Cache... caches) {this.caches caches;}Overridepublic Object getObject(Object key) {// 按顺序查询缓存for (Cache cache : caches) {Object value cache.getObject(key);if (value ! null) {// 填充上级缓存for (Cache upperCache : getUpperCaches(cache)) {upperCache.putObject(key, value);}return value;}}return null;}// 其他方法实现...
}
生产环境注意事项缓存一致性解决方案使用消息队列实现缓存更新
RabbitListener(queues cache.update.queue)
public void handleCacheUpdate(CacheUpdateMessage message) {if (message.getType().equals(PRODUCT)) {productMapper.clearCache(message.getId());}
}
监控指标采集
public class MonitoredCache implements Cache {private final Cache delegate;private final CacheMetrics metrics;Overridepublic Object getObject(Object key) {long start System.currentTimeMillis();try {Object value delegate.getObject(key);metrics.recordHit(value ! null);metrics.recordLatency(System.currentTimeMillis() - start);return value;} catch (Exception e) {metrics.recordError();throw e;}}// 其他方法...
}
缓存预热策略
PostConstruct
public void preloadHotProducts() {ListLong hotProductIds productMapper.selectHotProductIds();hotProductIds.parallelStream().forEach(id - {Product product productMapper.selectById(id);// 主动放入缓存productMapper.cacheProduct(product);});
}
通过以上详细实现可以构建一个高性能、高可用的二级缓存系统适用于各种生产环境场景。下面是springboot用法?xml version1.0 encodingUTF-8?
projectparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion3.1.4/version/parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.3.1/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency/dependencies
/projectspring:datasource:url: jdbc:mysql://localhost:3306/testusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverredis:host: localhostport: 6379password: database: 0mybatis-plus:configuration:cache-enabled: trueConfiguration
public class RedisCacheConfig {Beanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) {RedisTemplateString, Object template new RedisTemplate();template.setConnectionFactory(factory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new GenericJackson2JsonRedisSerializer());return template;}Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory factory) {RedisCacheConfiguration config RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));return RedisCacheManager.builder(factory).cacheDefaults(config).transactionAware().build();}
}CacheNamespace(implementation RedisCache.class, eviction RedisCache.class)
public interface UserMapper extends BaseMapperUser {Options(useCache true)Select(SELECT * FROM user WHERE id #{id})User selectUserById(Long id);CacheEvictUpdate(UPDATE user SET name#{name} WHERE id#{id})int updateUserName(Param(id) Long id, Param(name) String name);
}Service
public class UserService {Autowiredprivate UserMapper userMapper;Cacheable(key #id, unless #result null)public User getUserById(Long id) {return userMapper.selectById(id);}TransactionalCacheEvict(key #user.id)public void updateUser(User user) {userMapper.updateById(user);}CacheEvict(allEntries true)public void clearAllCache() {// 清空所有缓存}
}Configuration
MapperScan(com.example.mapper)
public class MyBatisPlusConfig {Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration - {configuration.setCacheEnabled(true);configuration.setLocalCacheScope(LocalCacheScope.SESSION);};}
}
CacheNamespaceMyBatis注解作用在Mapper接口级别声明启用二级缓存核心属性implementation指定自定义缓存实现类默认PerpetualCacheeviction指定缓存淘汰策略LRU/FIFO等flushInterval缓存刷新间隔毫秒size缓存最大容量示例javaCopy CodeCacheNamespace(implementation RedisCache.class, eviction FifoCache.class, flushInterval 60000) public interface UserMapper {...} OptionsMyBatis注解作用为单个SQL语句提供额外配置选项常用属性useCache是否使用二级缓存默认trueflushCache执行后是否清空缓存默认falsetimeout查询超时时间秒示例javaCopy CodeOptions(useCache true, flushCache false, timeout 10) Select(SELECT * FROM users WHERE id #{id}) User findById(Long id); CacheEvictSpring缓存注解作用方法执行后清除指定缓存关键属性value/cacheNames目标缓存名称key要清除的缓存键支持SpELallEntries是否清空整个缓存区域beforeInvocation是否在方法执行前清除典型使用场景javaCopy CodeCacheEvict(value userCache, key #user.id) public void updateUser(User user) { // 更新操作后会清除userCache中该用户的缓存 } 三者关系示意图CacheNamespace定义Mapper的缓存策略Options控制单个SQL语句的缓存行为CacheEvict在Service层维护缓存一致性生产建议对于读写频繁的数据建议组合使用CacheEvict和Cacheable分布式环境建议使用Redis等集中式缓存实现注意设置合理的缓存过期时间防止脏数据