缓存中间件(一)

缓存中间件的概念并不难理解,我们知道数据被存储在内存中时查询速度会非常慢,而查询缓存中的数据的查询时间几乎可以忽略不计。为何不将数据全部存储在缓存中呢?因为缓存的容量小。

缓存中间件就像书桌旁的抽屉

  • 把每天都要用的东西(高频读取的数据)放抽屉里,不用每次都跑大仓库(数据库)找,拿取更快;
  • 只有抽屉里没有(缓存未命中),才去仓库拿,顺便把东西放回抽屉(写入缓存),下次用更方便

缓存中间件的设置,本质上是利用空间换时间的平衡。现在我们利用java代码来模拟缓存中间件的运行逻辑。

java代码模拟缓存中间件:

1.创建实体类对象:
java 复制代码
public class User {
    private String name;
    private String phone;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

我们创建了一个User类,设置了两个属性:name和phone及其get、set方法。

2.创建CacheManger类来模拟缓存中间键:
java 复制代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//模拟缓存中间件
public class CacheManger {
    //所有的缓存都是key-value形式键值对的形式
    //简单的key-value形式的缓存
    private static Map<String,String>cache = new HashMap<>();

    //处理简单形式的缓存
    //新增缓存
    public static void put(String key,String value){
        cache.put(key,value);
    }
    //查询缓存
    public static String get(String key){
        return cache.get(key);
    }
    //删除缓存
    public static void remove(String key){
        cache.remove(key);
    }

}

我们看到CacheManger对象中设置了一个Map类型的对象,这是缓存通常使用的基本类型(key-value键值对类型)。

处理方法也很简单:put、get和remove方法分别新增获取和删除键值对。

3.创建UserList类来模拟内存:
java 复制代码
import java.util.ArrayList;
import java.util.List;

public class UserList {
    //用来模拟从磁盘中找
    //模拟内存
    public static List<User>users = new ArrayList<User>();
    static {
        User user = new User();
        user.setName("张三");
        user.setPhone("123456");

        User user2 = new User();
        user2.setName("里斯");
        user2.setPhone("123");

        users.add(user);
        users.add(user2);
    }

    public static String getPhoneByUserName(String userName){
        for(User user : users){
            if(user.getName().equals(userName)){
                return user.getPhone();
            }
        }
        return null;
    }
}

这里static代码块内已经将"张三"和"里斯"两个键值对存储在模拟内存中了。

4.创建Main方法模拟缓存逻辑:
java 复制代码
import java.util.List;

public class Main {
    public static void main(String[] args) {
    //要查询张三的手机号
//        putAllCache();
        getPhoneByUserName("张三");
        getPhoneByUserName("里斯");
    }
    public static String getPhoneByUserName(String userName){
        //先查看缓存,缓存中没有再从列表中查
        String phone = CacheManger.get(userName);
        //如果缓存中没有,就从内存中找,从内存中找到后存放到缓存中间件中
        if(phone==null){
            System.out.println("缓存未命中");
            phone = UserList.getPhoneByUserName(userName);
            //放入缓存
            CacheManger.put(userName, phone);
        }
        System.out.println("缓存命中");
        return phone;
    }
    //缓存预热
    public static void putAllCache(){
        //将所有的UserList放到缓存中
        List<User> users = UserList.users;
        for(User user : users){
            CacheManger.put(user.getName(), user.getPhone());
        }
    }
}

缓存命中:表示缓存中没有想要查找的数据。

缓存未命中:表示缓存中没有想要查找的数据,代码会自动从内存中获取想要查找的值,并将其存贮在缓存中。

注意:不论缓存中是否有想要查找的值,缓存最后一定会命中。

由此,当执行此代码时,结果是:

因为一开始缓存中没有需要查找的相关数据,显示未命中。最后将从内存中查找到的数据存放在缓存中,结果就是想要查找的手机号以键值对的形式被存储在模拟缓存中,结果一定是缓存命中。

而当将 putAllCache();(缓存预热) 这一句注释取消后,结果就是:

可以推断出缓存预热就是将内存中所有存储的值放入缓存中。

相关推荐
晚安code36 分钟前
Redis 内存淘汰策略实战:什么时候淘汰、怎么选、怎么防缓存击穿
java·redis·缓存
CDN36012 小时前
CDN 缓存策略优化实操:出海业务提升缓存命中率,TTL、缓存 Key、刷新配置与踩坑总结
缓存·cdn加速·cdn防护·360cdn
mit6.82417 小时前
保持缓存的有效性
缓存
AI多Agent协作实战派1 天前
AI多Agent协作系统实战(四十六):改了十次规则,AI员工还是老样子——会话缓存的坑
java·spring·缓存
做一个AK梦2 天前
Redis 深入浅出
java·数据库·redis·缓存
Java牛马2 天前
Caffeine 缓存及其应用相关总结
java·redis·缓存·caffeine·数据一致性·本地缓存
xiaojiaohuazi2 天前
国产安陆EG4S20 FPGA实现千兆以太网TCP/IP:AD7606C 8通道1 MSPS采集、SDRAM缓存与Python上位机
tcp/ip·缓存·fpga开发
Nil2082 天前
leetcode 146LRU缓存
算法·leetcode·缓存
BK贝壳2 天前
Python底层:1亿个布尔值缓存失效标记,list爆内存numpy爆拷贝,bool-hybrid-array混合存储实测
数据结构·python·缓存·性能优化·list·numpy
mmsx2 天前
置灰按钮为什么自己又“亮“了?一次状态缓存“双写冲突“的排查记录
java·缓存·bug·livedata