【缓存策略】你知道 Write Through(直写)这个缓存策略吗?

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主

⛪️ 个人社区:个人社区

💞 个人主页:个人主页

🙉 专栏地址: ✅ Java 中级

🙉八股文专题:剑指大厂,手撕 Java 八股文

文章目录

      • [1. 缓存策略 Write Through 是什么?](#1. 缓存策略 Write Through 是什么?)
      • [2. 缓存策略 Write Through 的应用场景](#2. 缓存策略 Write Through 的应用场景)
      • [3. 缓存策略 Write Through 的优缺点](#3. 缓存策略 Write Through 的优缺点)
      • [4. 用 Java 模拟使用 Write Through 策略](#4. 用 Java 模拟使用 Write Through 策略)
        • [1. 创建缓存接口](#1. 创建缓存接口)
        • [2. 创建内存缓存实现](#2. 创建内存缓存实现)
        • [3. 创建后端存储接口](#3. 创建后端存储接口)
        • [4. 创建后端存储实现](#4. 创建后端存储实现)
        • [5. 创建 Write Through 缓存实现](#5. 创建 Write Through 缓存实现)
        • [6. 测试 Write Through 缓存](#6. 测试 Write Through 缓存)

1. 缓存策略 Write Through 是什么?

Write Through 是一种缓存策略,当数据被写入缓存时,同时也会被写入后端存储(如数据库)。这种策略确保了缓存和后端存储的数据一致性。

工作原理:

  1. 写操作
    • 当客户端向缓存写入数据时,缓存会立即将数据写入后端存储。
    • 写操作只有在后端存储成功写入后才会返回成功。
  2. 读操作
    • 当客户端从缓存读取数据时,如果数据存在于缓存中,则直接返回缓存中的数据。
    • 如果数据不存在于缓存中,则从后端存储中读取数据,然后将其写入缓存,最后返回给客户端。

2. 缓存策略 Write Through 的应用场景

Write Through 适用于以下场景:

  1. 数据一致性要求高
    • 需要确保缓存和后端存储的数据始终保持一致。
  2. 写操作较少
    • 写操作相对于读操作较少,这样可以减少写操作的性能开销。
  3. 系统容错性要求高
    • 即使缓存失效,数据仍然存在于后端存储中,不会导致数据丢失。

3. 缓存策略 Write Through 的优缺点

优点:

  1. 数据一致性
    • 保证缓存和后端存储的数据一致性,避免数据不一致的问题。
  2. 容错性
    • 即使缓存失效,数据仍然存在于后端存储中,不会导致数据丢失。
  3. 简化系统设计
    • 不需要额外的机制来同步缓存和后端存储的数据。

缺点:

  1. 写操作性能开销大
    • 每次写操作都需要同时写入缓存和后端存储,增加了写操作的延迟。
  2. 写放大
    • 写操作会被放大,因为每次写操作都需要两次写入操作。
  3. 不适合写密集型应用
    • 对于写操作频繁的应用,Write Through 可能会导致性能瓶颈。

4. 用 Java 模拟使用 Write Through 策略

下面是一个简单的 Java 示例,模拟使用 Write Through 策略的缓存系统。

1. 创建缓存接口
java 复制代码
public interface Cache<K, V> {
    V get(K key);
    void put(K key, V value);
    void remove(K key);
}
2. 创建内存缓存实现
java 复制代码
import java.util.HashMap;
import java.util.Map;

public class InMemoryCache<K, V> implements Cache<K, V> {
    private final Map<K, V> cache = new HashMap<>();

    @Override
    public V get(K key) {
        return cache.get(key);
    }

    @Override
    public void put(K key, V value) {
        cache.put(key, value);
    }

    @Override
    public void remove(K key) {
        cache.remove(key);
    }
}
3. 创建后端存储接口
java 复制代码
public interface BackendStorage<K, V> {
    V get(K key);
    void put(K key, V value);
    void remove(K key);
}
4. 创建后端存储实现
java 复制代码
import java.util.HashMap;
import java.util.Map;

public class InMemoryBackendStorage<K, V> implements BackendStorage<K, V> {
    private final Map<K, V> storage = new HashMap<>();

    @Override
    public V get(K key) {
        return storage.get(key);
    }

    @Override
    public void put(K key, V value) {
        storage.put(key, value);
    }

    @Override
    public void remove(K key) {
        storage.remove(key);
    }
}
5. 创建 Write Through 缓存实现
java 复制代码
public class WriteThroughCache<K, V> implements Cache<K, V> {
    private final Cache<K, V> cache;
    private final BackendStorage<K, V> backendStorage;

    public WriteThroughCache(Cache<K, V> cache, BackendStorage<K, V> backendStorage) {
        this.cache = cache;
        this.backendStorage = backendStorage;
    }

    @Override
    public V get(K key) {
        V value = cache.get(key);
        if (value == null) {
            value = backendStorage.get(key);
            if (value != null) {
                cache.put(key, value);
            }
        }
        return value;
    }

    @Override
    public void put(K key, V value) {
        cache.put(key, value);
        backendStorage.put(key, value);
    }

    @Override
    public void remove(K key) {
        cache.remove(key);
        backendStorage.remove(key);
    }
}
6. 测试 Write Through 缓存
java 复制代码
public class Main {
    public static void main(String[] args) {
        Cache<String, String> inMemoryCache = new InMemoryCache<>();
        BackendStorage<String, String> inMemoryBackendStorage = new InMemoryBackendStorage<>();
        Cache<String, String> writeThroughCache = new WriteThroughCache<>(inMemoryCache, inMemoryBackendStorage);

        // 测试写操作
        writeThroughCache.put("key1", "value1");
        System.out.println("Cache: " + inMemoryCache.get("key1")); // 输出: value1
        System.out.println("Backend Storage: " + inMemoryBackendStorage.get("key1")); // 输出: value1

        // 测试读操作
        System.out.println("Cache Read: " + writeThroughCache.get("key1")); // 输出: value1

        // 测试读取未缓存的数据
        inMemoryBackendStorage.put("key2", "value2");
        System.out.println("Cache Read: " + writeThroughCache.get("key2")); // 输出: value2
        System.out.println("Cache: " + inMemoryCache.get("key2")); // 输出: value2

        // 测试删除操作
        writeThroughCache.remove("key1");
        System.out.println("Cache: " + inMemoryCache.get("key1")); // 输出: null
        System.out.println("Backend Storage: " + inMemoryBackendStorage.get("key1")); // 输出: null
    }
}
  • Write Through 是一种缓存策略,确保数据在写入缓存的同时也写入后端存储,保证数据一致性。
  • 应用场景:适用于数据一致性要求高、写操作较少、系统容错性要求高的场景。
  • 优缺点:优点是数据一致性高、容错性好、系统设计简单;缺点是写操作性能开销大、写放大、不适合写密集型应用。
  • Java 模拟 :通过实现 Cache 接口和 BackendStorage 接口,创建 WriteThroughCache 类来模拟 Write Through 缓存策略。

精彩专栏推荐订阅:在下方专栏👇🏻
2023年华为OD机试真题(A卷&B卷)+ 面试指导
精选100套 Java 项目案例
面试需要避开的坑(活动)
你找不到的核心代码
带你手撕 Spring
Java 初阶

相关推荐
货拉拉技术9 分钟前
多元消息融合分发平台
javascript·后端·架构
醒过来摸鱼23 分钟前
【Golang】协程
开发语言·后端·golang
IT枫斗者27 分钟前
如何解决Java EasyExcel 导出报内存溢出
java·服务器·开发语言·网络·分布式·物联网
谷大羽27 分钟前
Kafka Stream实战教程
spring boot·后端·中间件·kafka·stream
爱编程的小生29 分钟前
Easyexcel(4-模板文件)
java·excel
求积分不加C30 分钟前
Kafka怎么发送JAVA对象并在消费者端解析出JAVA对象--示例
java·分布式·kafka·linq
2401_8576363934 分钟前
实验室管理平台:Spring Boot技术构建
java·spring boot·后端
问窗38 分钟前
微服务中Spring boot的包扫描范围
java·spring boot·微服务
是程序喵呀1 小时前
SpringMVC详解
java·spring·spring-mvc
疯一样的码农1 小时前
Apache Maven 标准文件目录布局
java·maven·apache