Redis中6种缓存更新策略

Redis作为一款高性能的内存数据库,已经成为缓存层的首选解决方案。然而,使用缓存时最大的挑战在于保证缓存数据与底层数据源的一致性。缓存更新策略直接影响系统的性能、可靠性和数据一致性,选择合适的策略至关重要。

本文将介绍Redis中6种缓存更新策略。

策略一:Cache-Aside(旁路缓存)策略

工作原理

Cache-Aside是最常用的缓存模式,由应用层负责缓存和数据库的交互逻辑:

  1. 读取数据:先查询缓存,命中则直接返回;未命中则查询数据库,将结果写入缓存并返回
  2. 更新数据:先更新数据库,再删除缓存(或更新缓存)

代码示例

@Service
public class UserServiceCacheAside {@Autowiredprivate RedisTemplate<String, User> redisTemplate;@Autowiredprivate UserRepository userRepository;private static final String CACHE_KEY_PREFIX = "user:";private static final long CACHE_EXPIRATION = 30; // 缓存过期时间(分钟)public User getUserById(Long userId) {String cacheKey = CACHE_KEY_PREFIX + userId;// 1. 查询缓存User user = redisTemplate.opsForValue().get(cacheKey);// 2. 缓存命中,直接返回if (user != null) {return user;}// 3. 缓存未命中,查询数据库user = userRepository.findById(userId).orElse(null);// 4. 将数据库结果写入缓存(设置过期时间)if (user != null) {redisTemplate.opsForValue().set(cacheKey, user, CACHE_EXPIRATION, TimeUnit.MINUTES);}return user;}public void updateUser(User user) {// 1. 先更新数据库userRepository.save(user);// 2. 再删除缓存String cacheKey = CACHE_KEY_PREFIX + user.getId();redisTemplate.delete(cacheKey);// 或者选择更新缓存// redisTemplate.opsForValue().set(cacheKey, user, CACHE_EXPIRATION, TimeUnit.MINUTES);}
}

优缺点分析

优点

  • 实现简单,控制灵活
  • 适合读多写少的业务场景
  • 只缓存必要的数据,节省内存空间

缺点

  • 首次访问会有一定延迟(缓存未命中)
  • 存在并发问题:如果先删除缓存后更新数据库,可能导致数据不一致
  • 需要应用代码维护缓存一致性,增加了开发复杂度

适用场景

  • 读多写少的业务场景
  • 对数据一致性要求不是特别高的应用
  • 分布式系统中需要灵活控制缓存策略的场景

策略二:Read-Through(读穿透)策略

工作原理

Read-Through策略将缓存作为主要数据源的代理,由缓存层负责数据加载:

  1. 应用程序只与缓存层交互
  2. 当缓存未命中时,由缓存管理器负责从数据库加载数据并存入缓存
  3. 应用程序无需关心缓存是否存在,缓存层自动处理加载逻辑

代码示例

首先定义缓存加载器接口:

public interface CacheLoader<K, V> {V load(K key);
}

实现Read-Through缓存管理器:

@Component
public class ReadThroughCacheManager<K, V> {@Autowiredprivate RedisTemplate<String, V> redisTemplate;private final ConcurrentHashMap<String, CacheLoader<K, V>> loaders = new ConcurrentHashMap<>();public void registerLoader(String cachePrefix, CacheLoader<K, V> loader) {loaders.put(cachePrefix, loader);}public V get(String cachePrefix, K key, long expiration, TimeUnit timeUnit) {String cacheKey = cachePrefix + key;// 1. 查询缓存V value = redisTemplate.opsForValue().get(cacheKey);// 2. 缓存命中,直接返回if (value != null) {return value;}// 3. 缓存未命中,通过加载器获取数据CacheLoader<K, V> loader = loaders.get(cachePrefix);if (loader == null) {throw new IllegalStateException("No cache loader registered for prefix: " + cachePrefix);}// 使用加载器从数据源加载数据value = loader.load(key);// 4. 将加载的数据存入缓存if (value != null) {redisTemplate.opsForValue().set(cacheKey, value, expiration, timeUnit);}return value;}
}

使用示例:

@Service
public class UserServiceReadThrough {private static final String CACHE_PREFIX = "user:";private static final long CACHE_EXPIRATION = 30;@Autowiredprivate ReadThroughCacheManager<Long, User> cacheManager;@Autowiredprivate UserRepository userRepository;@PostConstructpublic void init() {// 注册用户数据加载器cacheManager.registerLoader(CACHE_PREFIX, this::loadUserFromDb);}private User loadUserFromDb(Long userId) {return userRepository.findById(userId).orElse(null);}public User getUserById(Long userId) {// 直接通过缓存管理器获取数据,缓存逻辑由管理器处理return cacheManager.get(CACHE_PREFIX, userId, CACHE_EXPIRATION, TimeUnit.MINUTES);}
}

优缺点分析

优点

  • 封装性好,应用代码无需关心缓存逻辑
  • 集中处理缓存加载,减少冗余代码
  • 适合只读或读多写少的数据

缺点

  • 缓存未命中时引发数据库请求,可能导致数据库负载增加
  • 无法直接处理写操作,需要与其他策略结合使用
  • 需要额外维护一个缓存管理层

适用场景

  • 读操作频繁的业务系统
  • 需要集中管理缓存加载逻辑的应用
  • 复杂的缓存预热和加载场景

策略三:Write-Through(写穿透)策略

工作原理

Write-Through策略由缓存层同步更新底层数据源:

  1. 应用程序更新数据时先写入缓存
  2. 然后由缓存层负责同步写入数据库
  3. 只有当数据成功写入数据库后才视为更新成功

代码示例

首先定义写入接口:

public interface CacheWriter<K, V> {void write(K key, V value);
}

实现Write-Through缓存管理器:

@Component
public class WriteThroughCacheManager<K, V> {@Autowiredprivate RedisTemplate<String, V> redisTemplate;private final ConcurrentHashMap<String, CacheWriter<K, V>> writers = new ConcurrentHashMap<>();public void registerWriter(String cachePrefix, CacheWriter<K, V> writer) {writers.put(cachePrefix, writer);}public void put(String cachePrefix, K key, V value, long expiration, TimeUnit timeUnit) {String cacheKey = cachePrefix + key;// 1. 获取对应的缓存写入器CacheWriter<K, V> writer = writers.get(cachePrefix);if (writer == null) {throw new IllegalStateException("No cache writer registered for prefix: " + cachePrefix);}// 2. 同步写入数据库writer.write(key, value);// 3. 更新缓存redisTemplate.opsForValue().set(cacheKey, value, expiration, timeUnit);}
}

使用示例:

@Service
public class UserServiceWriteThrough {private static final String CACHE_PREFIX = "user:";private static final long CACHE_EXPIRATION = 30;@Autowiredprivate WriteThroughCacheManager<Long, User> cacheManager;@Autowiredprivate UserRepository userRepository;@PostConstructpublic void init() {// 注册用户数据写入器cacheManager.registerWriter(CACHE_PREFIX, this::saveUserToDb);}private void saveUserToDb(Long userId, User user) {userRepository.save(user);}public void updateUser(User user) {// 通过缓存管理器更新数据,会同步更新数据库和缓存cacheManager.put(CACHE_PREFIX, user.getId(), user, CACHE_EXPIRATION, TimeUnit.MINUTES);}
}

优缺点分析

优点

  • 保证数据库与缓存的强一致性
  • 将缓存更新逻辑封装在缓存层,简化应用代码
  • 读取缓存时命中率高,无需回源到数据库

缺点

  • 实时写入数据库增加了写操作延迟
  • 增加系统复杂度,需要处理事务一致性
  • 对数据库写入压力大的场景可能成为性能瓶颈

适用场景

  • 对数据一致性要求高的系统
  • 写操作不是性能瓶颈的应用
  • 需要保证缓存与数据库实时同步的场景

策略四:Write-Behind(写回)策略

工作原理

Write-Behind策略将写操作异步化处理:

  1. 应用程序更新数据时只更新缓存
  2. 缓存维护一个写入队列,将更新异步批量写入数据库
  3. 通过批量操作减轻数据库压力

代码示例

实现异步写入队列和处理器:

@Component
public class WriteBehindCacheManager<K, V> {@Autowiredprivate RedisTemplate<String, V> redisTemplate;private final BlockingQueue<CacheUpdate<K, V>> updateQueue = new LinkedBlockingQueue<>();private final ConcurrentHashMap<String, CacheWriter<K, V>> writers = new ConcurrentHashMap<>();public void registerWriter(String cachePrefix, CacheWriter<K, V> writer) {writers.put(cachePrefix, writer);}@PostConstructpublic void init() {// 启动异步写入线程Thread writerThread = new Thread(this::processWriteBehindQueue);writerThread.setDaemon(true);writerThread.start();}public void put(String cachePrefix, K key, V value, long expiration, TimeUnit timeUnit) {String cacheKey = cachePrefix + key;// 1. 更新缓存redisTemplate.opsForValue().set(cacheKey, value, expiration, timeUnit);// 2. 将更新放入队列,等待异步写入数据库updateQueue.offer(new CacheUpdate<>(cachePrefix, key, value));}private void processWriteBehindQueue() {List<CacheUpdate<K, V>> batch = new ArrayList<>(100);while (true) {try {// 获取队列中的更新,最多等待100msCacheUpdate<K, V> update = updateQueue.poll(100, TimeUnit.MILLISECONDS);if (update != null) {batch.add(update);}// 继续收集队列中可用的更新,最多收集100个或等待200msupdateQueue.drainTo(batch, 100 - batch.size());if (!batch.isEmpty()) {// 按缓存前缀分组批量处理Map<String, List<CacheUpdate<K, V>>> groupedUpdates = batch.stream().collect(Collectors.groupingBy(CacheUpdate::getCachePrefix));for (Map.Entry<String, List<CacheUpdate<K, V>>> entry : groupedUpdates.entrySet()) {String cachePrefix = entry.getKey();List<CacheUpdate<K, V>> updates = entry.getValue();CacheWriter<K, V> writer = writers.get(cachePrefix);if (writer != null) {// 批量写入数据库for (CacheUpdate<K, V> u : updates) {try {writer.write(u.getKey(), u.getValue());} catch (Exception e) {// 处理异常,可以重试或记录日志log.error("Failed to write-behind for key {}: {}", u.getKey(), e.getMessage());}}}}batch.clear();}} catch (InterruptedException e) {Thread.currentThread().interrupt();break;} catch (Exception e) {log.error("Error in write-behind process", e);}}}@Data@AllArgsConstructorprivate static class CacheUpdate<K, V> {private String cachePrefix;private K key;private V value;}
}

使用示例:

@Service
public class UserServiceWriteBehind {private static final String CACHE_PREFIX = "user:";private static final long CACHE_EXPIRATION = 30;@Autowiredprivate WriteBehindCacheManager<Long, User> cacheManager;@Autowiredprivate UserRepository userRepository;@PostConstructpublic void init() {// 注册用户数据写入器cacheManager.registerWriter(CACHE_PREFIX, this::saveUserToDb);}private void saveUserToDb(Long userId, User user) {userRepository.save(user);}public void updateUser(User user) {// 更新仅写入缓存,异步写入数据库cacheManager.put(CACHE_PREFIX, user.getId(), user, CACHE_EXPIRATION, TimeUnit.MINUTES);}
}

优缺点分析

优点

  • 显著提高写操作性能,减少响应延迟
  • 通过批量操作减轻数据库压力
  • 平滑处理写入峰值,提高系统吞吐量

缺点

  • 存在数据一致性窗口期,不适合强一致性要求的场景
  • 系统崩溃可能导致未写入的数据丢失
  • 实现复杂,需要处理失败重试和冲突解决

适用场景

  • 高并发写入场景,如日志记录、统计数据
  • 对写操作延迟敏感但对一致性要求不高的应用
  • 数据库写入是系统瓶颈的场景

策略五:刷新过期(Refresh-Ahead)策略

工作原理

Refresh-Ahead策略预测性地在缓存过期前进行更新:

  1. 缓存设置正常的过期时间
  2. 当访问接近过期的缓存项时,触发异步刷新
  3. 用户始终访问的是已缓存的数据,避免直接查询数据库的延迟

代码示例

@Component
public class RefreshAheadCacheManager<K, V> {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate ThreadPoolTaskExecutor refreshExecutor;private final ConcurrentHashMap<String, CacheLoader<K, V>> loaders = new ConcurrentHashMap<>();// 刷新阈值,当过期时间剩余不足阈值比例时触发刷新private final double refreshThreshold = 0.75; // 75%public void registerLoader(String cachePrefix, CacheLoader<K, V> loader) {loaders.put(cachePrefix, loader);}@SuppressWarnings("unchecked")public V get(String cachePrefix, K key, long expiration, TimeUnit timeUnit) {String cacheKey = cachePrefix + key;// 1. 获取缓存项和其TTLV value = (V) redisTemplate.opsForValue().get(cacheKey);Long ttl = redisTemplate.getExpire(cacheKey, TimeUnit.MILLISECONDS);if (value != null) {// 2. 如果缓存存在但接近过期,触发异步刷新if (ttl != null && ttl > 0) {long expirationMs = timeUnit.toMillis(expiration);if (ttl < expirationMs * (1 - refreshThreshold)) {refreshAsync(cachePrefix, key, cacheKey, expiration, timeUnit);}}return value;}// 3. 缓存不存在,同步加载return loadAndCache(cachePrefix, key, cacheKey, expiration, timeUnit);}private void refreshAsync(String cachePrefix, K key, String cacheKey, long expiration, TimeUnit timeUnit) {refreshExecutor.execute(() -> {try {loadAndCache(cachePrefix, key, cacheKey, expiration, timeUnit);} catch (Exception e) {// 异步刷新失败,记录日志但不影响当前请求log.error("Failed to refresh cache for key {}: {}", cacheKey, e.getMessage());}});}private V loadAndCache(String cachePrefix, K key, String cacheKey, long expiration, TimeUnit timeUnit) {CacheLoader<K, V> loader = loaders.get(cachePrefix);if (loader == null) {throw new IllegalStateException("No cache loader registered for prefix: " + cachePrefix);}// 从数据源加载V value = loader.load(key);// 更新缓存if (value != null) {redisTemplate.opsForValue().set(cacheKey, value, expiration, timeUnit);}return value;}
}

使用示例:

@Service
public class ProductServiceRefreshAhead {private static final String CACHE_PREFIX = "product:";private static final long CACHE_EXPIRATION = 60; // 1小时@Autowiredprivate RefreshAheadCacheManager<String, Product> cacheManager;@Autowiredprivate ProductRepository productRepository;@PostConstructpublic void init() {// 注册产品数据加载器cacheManager.registerLoader(CACHE_PREFIX, this::loadProductFromDb);}private Product loadProductFromDb(String productId) {return productRepository.findById(productId).orElse(null);}public Product getProduct(String productId) {return cacheManager.get(CACHE_PREFIX, productId, CACHE_EXPIRATION, TimeUnit.MINUTES);}
}

线程池配置

@Configuration
public class ThreadPoolConfig {@Beanpublic ThreadPoolTaskExecutor refreshExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);executor.setThreadNamePrefix("cache-refresh-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;}
}

优缺点分析

优点

  • 用户始终访问缓存数据,避免因缓存过期导致的延迟
  • 异步刷新减轻了数据库负载峰值
  • 缓存命中率高,用户体验更好

缺点

  • 实现复杂度高,需要额外的线程池管理
  • 预测算法可能不准确,导致不必要的刷新
  • 对于很少访问的数据,刷新可能是浪费

适用场景

  • 对响应时间要求苛刻的高流量系统
  • 数据更新频率可预测的场景
  • 数据库资源有限但缓存容量充足的系统

策略六:最终一致性(Eventual Consistency)策略

工作原理

最终一致性策略基于分布式事件系统实现数据同步:

  1. 数据变更时发布事件到消息队列
  2. 缓存服务订阅相关事件并更新缓存
  3. 即使某些操作暂时失败,最终系统也会达到一致状态

代码示例

首先定义数据变更事件:

@Data
@AllArgsConstructor
public class DataChangeEvent {private String entityType;private String entityId;private String operation; // CREATE, UPDATE, DELETEprivate String payload;   // JSON格式的实体数据
}

实现事件发布者:

@Component
public class DataChangePublisher {@Autowiredprivate KafkaTemplate<String, DataChangeEvent> kafkaTemplate;private static final String TOPIC = "data-changes";public void publishChange(String entityType, String entityId, String operation, Object entity) {try {// 将实体序列化为JSONString payload = new ObjectMapper().writeValueAsString(entity);// 创建事件DataChangeEvent event = new DataChangeEvent(entityType, entityId, operation, payload);// 发布到KafkakafkaTemplate.send(TOPIC, entityId, event);} catch (Exception e) {log.error("Failed to publish data change event", e);throw new RuntimeException("Failed to publish event", e);}}
}

实现事件消费者更新缓存:

@Component
@Slf4j
public class CacheUpdateConsumer {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final long CACHE_EXPIRATION = 30;@KafkaListener(topics = "data-changes")public void handleDataChangeEvent(DataChangeEvent event) {try {String cacheKey = buildCacheKey(event.getEntityType(), event.getEntityId());switch (event.getOperation()) {case "CREATE":case "UPDATE":// 解析JSON数据Object entity = parseEntity(event.getPayload(), event.getEntityType());// 更新缓存redisTemplate.opsForValue().set(cacheKey, entity, CACHE_EXPIRATION, TimeUnit.MINUTES);log.info("Updated cache for {}: {}", cacheKey, event.getOperation());break;case "DELETE":// 删除缓存redisTemplate.delete(cacheKey);log.info("Deleted cache for {}", cacheKey);break;default:log.warn("Unknown operation: {}", event.getOperation());}} catch (Exception e) {log.error("Error handling data change event: {}", e.getMessage(), e);// 失败处理:可以将失败事件放入死信队列等}}private String buildCacheKey(String entityType, String entityId) {return entityType.toLowerCase() + ":" + entityId;}private Object parseEntity(String payload, String entityType) throws JsonProcessingException {// 根据实体类型选择反序列化目标类Class<?> targetClass = getClassForEntityType(entityType);return new ObjectMapper().readValue(payload, targetClass);}private Class<?> getClassForEntityType(String entityType) {switch (entityType) {case "User": return User.class;case "Product": return Product.class;// 其他实体类型default: throw new IllegalArgumentException("Unknown entity type: " + entityType);}}
}

使用示例:

@Service
@Transactional
public class UserServiceEventDriven {@Autowiredprivate UserRepository userRepository;@Autowiredprivate DataChangePublisher publisher;public User createUser(User user) {// 1. 保存用户到数据库User savedUser = userRepository.save(user);// 2. 发布创建事件publisher.publishChange("User", savedUser.getId().toString(), "CREATE", savedUser);return savedUser;}public User updateUser(User user) {// 1. 更新用户到数据库User updatedUser = userRepository.save(user);// 2. 发布更新事件publisher.publishChange("User", updatedUser.getId().toString(), "UPDATE", updatedUser);return updatedUser;}public void deleteUser(Long userId) {// 1. 从数据库删除用户userRepository.deleteById(userId);// 2. 发布删除事件publisher.publishChange("User", userId.toString(), "DELETE", null);}
}

优缺点分析

优点

  • 支持分布式系统中的数据一致性
  • 削峰填谷,减轻系统负载峰值
  • 服务解耦,提高系统弹性和可扩展性

缺点

  • 一致性延迟,只能保证最终一致性
  • 实现和维护更复杂,需要消息队列基础设施
  • 可能需要处理消息重复和乱序问题

适用场景

  • 大型分布式系统
  • 可以接受短暂不一致的业务场景
  • 需要解耦数据源和缓存更新逻辑的系统

缓存更新策略选择指南

选择合适的缓存更新策略需要考虑以下因素:

1. 业务特性考量

业务特征推荐策略
读多写少Cache-Aside 或 Read-Through
写密集型Write-Behind
高一致性需求Write-Through
响应时间敏感Refresh-Ahead
分布式系统最终一致性

2. 资源限制考量

资源约束推荐策略
内存限制Cache-Aside(按需缓存)
数据库负载高Write-Behind(减轻写压力)
网络带宽受限Write-Behind 或 Refresh-Ahead

3. 开发复杂度考量

复杂度要求推荐策略
简单实现Cache-Aside
中等复杂度Read-Through 或 Write-Through
高复杂度但高性能Write-Behind 或 最终一致性

结论

缓存更新是Redis应用设计中的核心挑战,没有万能的策略适用于所有场景。根据业务需求、数据特性和系统资源,选择合适的缓存更新策略或组合多种策略才是最佳实践。

在实际应用中,可以根据不同数据的特性选择不同的缓存策略,甚至在同一个系统中组合多种策略,以达到性能和一致性的最佳平衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/904532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目优先级频繁变动,如何应对?

项目优先级频繁变动是许多公司和团队在工作中常遇到的挑战。 这种情况通常由业务需求变化、市场压力或高层决策调整等因素引起&#xff0c;常常让团队成员感到困惑和不安。首先&#xff0c;制定明确的优先级管理框架是应对项目优先级变动的基础&#xff0c; 通过清晰的优先级排…

屏蔽力 | 在复杂世界中从内耗到成长的转变之道

注&#xff1a;本文为“屏蔽力”相关文章合辑。 略作重排&#xff0c;未全整理。 世上的事再复杂&#xff0c;不外乎这三种 原创 小鹿 读者 2022 年 12 月 02 日 18 : 27 甘肃 文 / 小鹿 在这世上&#xff0c;每天都有大事小事、琐事烦事。我们总为世事奔波忙碌&#xff0c;…

[数据处理] 3. 数据集读取

&#x1f44b; 你好&#xff01;这里有实用干货与深度分享✨✨ 若有帮助&#xff0c;欢迎&#xff1a;​ &#x1f44d; 点赞 | ⭐ 收藏 | &#x1f4ac; 评论 | ➕ 关注 &#xff0c;解锁更多精彩&#xff01;​ &#x1f4c1; 收藏专栏即可第一时间获取最新推送&#x1f514;…

IIS配置SSL

打开iis 如果搜不到iis&#xff0c;要先开 再搜就打得开了 cmd中找到本机ip 用http访问本机ip 把原本的http绑定删了 再用http访问本机ip就不行了 只能用https访问了

RabbitMQ的交换机

一、三种交换机模式 核心区别对比​​ ​​特性​​​​广播模式&#xff08;Fanout&#xff09;​​​​路由模式&#xff08;Direct&#xff09;​​​​主题模式&#xff08;Topic&#xff09;​​​​路由规则​​无条件复制到所有绑定队列精确匹配 Routing Key通配符匹配…

(2025,AR,NAR,GAN,Diffusion,模型对比,数据集,评估指标,性能对比)文本到图像的生成和编辑:综述

【本文为我在去年完成的综述&#xff0c;因某些原因未能及时投稿&#xff0c;但本文仍能为想要全面了解文本到图像的生成和编辑的学习者提供可靠的参考。目前本文已投稿 ACM Computing Surveys。 完整内容可在如下链接获取&#xff0c;或在 Q 群群文件获取。 中文版为论文初稿&…

MCU怎么运行深度学习模型

Gitee仓库 git clone https://gitee.com/banana-peel-x/freedom-learn.git项目场景&#xff1a; 解决面试时遗留的问题&#xff0c;面试官提了两个问题&#xff1a;1.单片机能跑深度学习的模型吗&#xff1f; 2.为什么FreeRTOS要采用SVC去触发第一个任务&#xff0c;只用Pend…

多模态学习(一)——从 Image-Text Pair 到 Instruction-Following 格式

前言 在多模态任务中&#xff08;例如图像问答、图像描述等&#xff09;&#xff0c;为了使用指令微调&#xff08;Instruction Tuning&#xff09;提升多模态大模型的能力&#xff0c;我们需要构建成千上万条**指令跟随&#xff08;instruction-following&#xff09;**格式的…

MySQL基础关键_011_视图

目 录 一、说明 二、操作 1.创建视图 2.创建可替换视图 3.修改视图 4.删除视图 5.对视图内容的增、删、改 &#xff08;1&#xff09;增 &#xff08;2&#xff09;改 &#xff08;3&#xff09;删 一、说明 只能将 DQL 语句创建为视图&#xff1b;作用&#xff1a; …

『深夜_MySQL』数据库操作 字符集与检验规则

2.库的操作 2.1 创建数据库 语法&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification]….]create_spcification:[DEFAULT] CHARACTER SET charset_nam[DEFAULT] COLLATE collation_name说明&#xff1a; 大写的表示关键字 …

Spark jdbc写入崖山等国产数据库失败问题

随着互联网、信息产业的大发展、以及地缘政治的变化,网络安全风险日益增长,网络安全关乎国家安全。因此很多的企业,开始了国产替代的脚步,从服务器芯片,操作系统,到数据库,中间件,逐步实现信息技术自主可控,规避外部技术制裁和风险。 就数据库而言,目前很多的国产数据…

数字化转型-4A架构之应用架构

系列文章 数字化转型-4A架构&#xff08;业务架构、应用架构、数据架构、技术架构&#xff09;数字化转型-4A架构之业务架构 前言 应用架构AA&#xff08;Application Architecture&#xff09;是规划支撑业务的核心系统与功能模块&#xff0c;实现端到端协同。 一、什么是应…

格雷狼优化算法`GWO 通过模拟和优化一个信号处理问题来最大化特定频率下的功率

这段代码是一个Python程序,它使用了多个科学计算库,包括`random`、`numpy`、`matplotlib.pyplot`、`scipy.signal`和`scipy.signal.windows`。程序的主要目的是通过模拟和优化一个信号处理问题来最大化特定频率下的功率。 4. **定义类`class_model`**: - 这个类包含了信号…

中级网络工程师知识点1

1.1000BASE-CX:铜缆,最大传输距离为25米 1000BASE-LX:传输距离可达3000米 1000BASE-ZX:超过10km 2.RSA加密算法的安全性依赖于大整数分解问题的困难性 3.网络信息系统的可靠性测度包括有效性,康毁性,生存性 4.VLAN技术所依据的协议是IEEE802.1q IEEE802.15标准是针…

2025年五一数学建模A题【支路车流量推测】原创论文讲解

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2025年五一数学建模A题【支路车流量推测】完整的成品论文。 给大家看一下目录吧&#xff1a; 摘 要&#xff1a; 一、问题重述 二&#xff0e;问题分析 2.1问题一 2.2问题二 2.3问题三 2.4问题四 2.5 …

性能优化实践:渲染性能优化

性能优化实践&#xff1a;渲染性能优化 在Flutter应用开发中&#xff0c;渲染性能直接影响用户体验。本文将从渲染流程分析入手&#xff0c;深入探讨Flutter渲染性能优化的关键技术和最佳实践。 一、Flutter渲染流程解析 1.1 渲染流水线 Flutter的渲染流水线主要包含以下几…

linux基础学习--linux磁盘与文件管理系统

linux磁盘与文件管理系统 1.认识linux系统 1.1 磁盘组成与分区的复习 首先了解磁盘的物理组成,主要有: 圆形的碟片(主要记录数据的部分)。机械手臂,与在机械手臂上的磁头(可擦写碟片上的内容)。主轴马达,可以转动碟片,让机械手臂的磁头在碟片上读写数据。 数据存储…

DIFY教程第五弹:科研论文翻译与SEO翻译应用

科研论文翻译 我可以在工作流案例中结合聊天大模型来实现翻译工具的功能&#xff0c;具体的设计如下 在开始节点中接收一个输入信息 content 然后在 LLM 模型中我们需要配置一个 CHAT 模型&#xff0c;这里选择了 DeepSeek-R1 64K 的聊天模型&#xff0c;注意需要在这里设置下…

【Redis】哨兵机制和集群

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【中间件】企业级中间件剖析 一、哨兵机制 Redis的主从复制模式下&#xff0c;一旦主节点由于故障不能提供服务&#xff0c;需要人工的进行主从切换&#xff0c;同时需要大量的客户端需要被通知切换到…

注意力机制(Attention)

1. 注意力认知和应用 AM&#xff1a; Attention Mechanism&#xff0c;注意力机制。 根据眼球注视的方向&#xff0c;采集显著特征部位数据&#xff1a; 注意力示意图&#xff1a; 注意力机制是一种让模型根据任务需求动态地关注输入数据中重要部分的机制。通过注意力机制&…