java
主页 > 软件编程 > java >

基于Java实现Redis多级缓存方法

2022-03-22 | 秩名 | 点击:

一、多级缓存

1. 传统缓存方案

请求到达tomcat后,先去redis中获取缓存,不命中则去mysql中获取

2. 多级缓存方案

二、JVM本地缓存

缓存是存储在内存中,数据读取速度较快,能大量减少对数据库的访问,减少数据库压力

分布式缓存,如redis
 - 优点: 存储容量大,可靠性好,可以在集群中共享
 - 缺点: 访问缓存有网络开销
 - 场景: 缓存数据量大,可靠性高,需要在集群中共享的数据

进程本地缓存, 如HashMap, GuavaCache
- 优点:读取本地内存,没有网络开销,速度更快
- 缺点:存储容量有限,可靠性低(如重启后丢失),无法在集群中共享
- 场景:性能要求高,缓存数据量少

1. 实用案例

1

2

3

4

5

<dependency>

     <groupId>com.github.ben-manes.caffeine</groupId>

     <artifactId>caffeine</artifactId>

     <version>3.0.5</version>

 </dependency>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

package com.erick.cache;

 

import com.github.benmanes.caffeine.cache.Cache;

import com.github.benmanes.caffeine.cache.Caffeine;

 

import java.time.Duration;

 

public final class CacheUtil {

    private static int expireSeconds = 2;

    public static Cache<String, String> cacheWithExpireSeconds;

 

    private static int maxPairs = 1;

    public static Cache<String, String> cacheWithMaxPairs;

 

    static {

        /*过期策略,写完60s后过期*/

        cacheWithExpireSeconds = Caffeine.newBuilder()

                .expireAfterWrite(Duration.ofSeconds(expireSeconds))

                .build();

 

        /*过期策略,达到最大值后删除

         * 1. 并不会立即删除,等一会儿才会删除

         * 2. 会将之前存储的数据删除掉*/

        cacheWithMaxPairs = Caffeine.newBuilder()

                .maximumSize(maxPairs)

                .build();

    }

 

    /*从缓存中获取数据

     * 1. 如果缓存中有,则直接从缓存中返回

     * 2. 如果缓存中没有,则去数据查询并返回结果*/

    public static String getKeyWithExpire(String key) {

        return cacheWithExpireSeconds.get(key, value -> {

            return getResultFromDB();

        });

    }

 

    public static String getKeyWithMaxPair(String key) {

        return cacheWithMaxPairs.get(key, value -> {

            return getResultFromDB();

        });

    }

 

    private static String getResultFromDB() {

        System.out.println("数据库查询");

        return "db result";

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

package com.erick.cache;

 

import java.util.concurrent.TimeUnit;

 

public class Test {

 

    @org.junit.Test

    public void test01() throws InterruptedException {

        CacheUtil.cacheWithExpireSeconds.put("name", "erick");

        System.out.println(CacheUtil.getKeyWithExpire("name"));

        TimeUnit.SECONDS.sleep(3);

        System.out.println(CacheUtil.getKeyWithExpire("name"));

    }

 

    @org.junit.Test

    public void test02() throws InterruptedException {

        CacheUtil.cacheWithMaxPairs.put("name", "erick");

        CacheUtil.cacheWithMaxPairs.put("age", "12");

 

        System.out.println(CacheUtil.getKeyWithMaxPair("name"));

        System.out.println(CacheUtil.getKeyWithMaxPair("age"));

 

        TimeUnit.SECONDS.sleep(2);

 

        System.out.println(CacheUtil.getKeyWithMaxPair("name")); // 查询不到了

        System.out.println(CacheUtil.getKeyWithMaxPair("age"));

    }

}

三、缓存一致性

1. 常见方案

1.1 设置有效期

1.2 同步双写

1.3 异步通知

2. 基于Canal的异步通知

2.1 mysql主从复制

2.2 canal 工作原理

原文链接:https://blog.csdn.net/weixin_43374578/article/details/123524351
相关文章
最新更新