写点什么

缓存失效下的熔断和降级策略

  • 2024-07-31
    北京
  • 本文字数:1861 字

    阅读完需:约 6 分钟

更多软件测试学习资料戳

缓存击穿是指某个热点数据在缓存过期的瞬间,有大量并发请求同时访问该数据,导致所有请求直接打到数据库,造成数据库压力骤增。为了解决缓存击穿问题,可以采取以下几种处理方法:

一、处理方法

  1. 互斥锁(Mutex)


    在缓存失效时,通过加锁机制确保只有一个线程能访问数据库并更新缓存,其他线程等待锁释放后从缓存中读取数据。


public class CacheService {    private final Object lock = new Object();
public String getData(String key) { String value = cache.get(key); if (value == null) { synchronized (lock) { value = cache.get(key); if (value == null) { value = database.get(key); cache.set(key, value); } } } return value; }}
复制代码

提前更新缓存

在缓存过期前主动更新缓存,即提前在缓存过期之前重新加载数据,确保缓存始终有值。

public class CacheService {    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public CacheService() { scheduler.scheduleAtFixedRate(this::updateCache, 0, 1, TimeUnit.MINUTES); }
private void updateCache() { String key = "someKey"; String value = database.get(key); cache.set(key, value); }}
复制代码

延迟双删策略

在更新缓存时,先删除缓存,再更新数据库,最后再次删除缓存,确保缓存数据一致性。

public void updateData(String key, String value) {    cache.delete(key);    database.update(key, value);    try {        Thread.sleep(1000); // 等待缓存失效时间    } catch (InterruptedException e) {        Thread.currentThread().interrupt();    }    cache.delete(key);}
复制代码

热点数据永不过期

对于热点数据,设置一个很长的过期时间,甚至不设置过期时间,定期手动更新缓存。

public class CacheService {    public void setHotData(String key, String value) {        cache.set(key, value, Long.MAX_VALUE);    }}
复制代码

布隆过滤器

使用布隆过滤器来判断某个数据是否存在,从而避免缓存穿透导致的数据库查询。

private BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 100000);
public String getData(String key) { if (!bloomFilter.mightContain(key)) { return "Default Value"; // 数据不存在,直接返回默认值 } String value = cache.get(key); if (value == null) { value = database.get(key); cache.set(key, value); } return value;}
复制代码


二、测试方法

  1. 单元测试


编写单元测试验证各个处理方法的逻辑正确性。

@Testpublic void testCacheHit() {    CacheService service = new CacheService();    String key = "testKey";    String value = "testValue";    cache.set(key, value);    assertEquals(value, service.getData(key));}
复制代码

集成测试

模拟高并发场景,验证在缓存失效时各个处理方法的有效性。

@Testpublic void testHighConcurrency() throws InterruptedException {    CacheService service = new CacheService();    String key = "testKey";    CountDownLatch latch = new CountDownLatch(100);    for (int i = 0; i < 100; i++) {        new Thread(() -> {            try {                service.getData(key);            } finally {                latch.countDown();            }        }).start();    }    latch.await();    assertNotNull(cache.get(key));}
复制代码

负载测试

使用负载测试工具(如 JMeter、Gatling)模拟高并发请求,测试系统在缓存失效情况下的性能。

jmeter -n -t cache_test.jmx -l result.jtl
复制代码

故障注入测试

使用故障注入工具(如 Chaos Monkey)模拟缓存服务器宕机或延迟,验证系统的缓存击穿处理策略。

chaos-monkey-aws attack --instance-id i-xxxxxx --type terminate
复制代码

结论

缓存击穿是分布式系统中常见的问题,通过合理的处理方法(如互斥锁、提前更新缓存、延迟双删、热点数据永不过期、布隆过滤器等)可以有效地防止缓存击穿造成的系统性能问题。通过单元测试、集成测试、负载测试和故障注入测试,可以验证这些方法的有效性,确保系统的稳定性和高可用性。


用户头像

社区:ceshiren.com 微信:ceshiren2023 2022-08-29 加入

微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料、实事更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬

评论

发布
暂无评论
缓存失效下的熔断和降级策略_测试_测吧(北京)科技有限公司_InfoQ写作社区