使用 redis 缓存数据

53 阅读3分钟

使用 java 开发程序时,如果我们想保存当前用户信息,让其他的方法调用。我们可以使用这几种方法:

  1. session 这个容器中
  2. 创建一个静态的 HashMap 容器用来保存信息
  3. 使用 ThreadLocal 保存信息

但是这几个方法都有一个弊端:它们只适合单机的情况,如果是在集群环境下,多台 JVM 机之间的信息是无法共享的

image-20230815132243366.png

所以在集群环境下,我们要考虑共享存储这个问题。那样就不能再 java 程序中去存储信息。我们要使用一个独立于 java 程序的 容器存储数据。 这里我们就可以使用 redis 来存储数据

缓存数据

介绍缓存数据前,我们假设一个业务场景:如果我们要查询一个商铺的信息。前端发出请求,后端向数据库发出请求,将数据查出来,返回给前端。如果我们要查询的是 100 个商铺呢 ? 是 1000 个呢 ? 如果数据更大的话,查询数据库的时间就要非常久。有什么办法可以减少查询数据库的时间吗 ?

如果我们可以将要查询的数据保存好在一个容器中,用户发起请求,直接访问这个容器,而不用去查询数据库,响应的时间是不是大大减少了。这就是我要介绍的缓存。这里我们使用 redis 这个数据库来缓存数据

1. 什么是缓存

缓存 就是数据交换的缓冲区(称作Cache),是存贮数据的临时地方,一般读写性能较高。

2.缓存的利与弊

缓存的作用:

  • 降低后端负载
  • 提高读写效率,降低响应时间

缓存的成本:

  • 数据一致性的成本
  • 代码维护的成本

3.缓存作用的模型

image.png

4. 缓存更新

  1. 缓存数据,缓存的是旧的数据,如果我们修改了数据库的数据,那么缓存的数据要不要修改呢 ? 如果不修改的话,就会出现一个数据不一致的问题。

  2. redis 缓存数据,默认是不会删除的,如果所有的数据都不删除,那么 redis 的内存是不是迟早会满。所以我们应该设置过期时间

4.1.缓存更新的策略:

  • 内存淘汰
  • 超时删除
  • 主动更新

对于高一致性的需求,我们可以采用主动更新,并以过期时间作为兜底方案

对于低一致性的需要,我们可以采用内存淘汰机制,但是最好还是加上过期时间

4.2. 操作缓存和数据库时有三个问题需要考虑

  1. 删除缓存还是更新缓存 ?
  • 更新缓存:每次更新数据库都更新缓存,无效操作较多
  • 删除缓存:更新数据库时让缓存失效,查询时在更新缓存 √
  1. 如何保证缓存与数据库的操作的同时成功或失败 ?(原子性问题
  • 单体系统,将缓存与数据库操作放在一个事务中
  1. 先操作缓存还是先操作数据库 ?(线程安全问题
  • 先删除缓存,再操作数据库
  • 先操作数据库,再删除缓存 √

4.3.主动更新的实践

  1. 读操作

    1. 缓存命中则直接返回数据
    2. 缓存未命中则查询数据库,并写入缓存,设置超时时间
  2. 写操作

    1. 先写数据库,然后删除缓存
    2. 确保数据库与缓存操作的原子性