谷粒商城8:分布式锁使用和springcache的整合

1.分布式锁redisson使用

①分布式锁简介

谷粒商城8:分布式锁使用和springcache的整合_第1张图片

②分布式锁学习过程

谷粒商城8:分布式锁使用和springcache的整合_第2张图片

③最终分析

加入锁为原子操作:设置过期时间+设置锁
删除锁为原子操作:业务流程+删除锁
将锁的过期时间调长

④Redisson的使用

  1. 引入依赖
  2. 程序化配置
  3. 使用
    1. 创建redisson客户端
      Redisson.create(“config”)
      config中保存redis的地址
    2. 获取一把锁
      redisson.getLock(“lock”)
    3. 设置逻辑
      try{lock.lock;
      业务逻辑}
      finally{lock.unlock;}
    4. 解决问题

⑤解决问题:

  1. 锁的续期
    不配置过期时间:有配置的看门狗,即锁会自动续期,默认30s,如果在执行业务期间锁过完三分之一10s,即重新恢复到30s,执行业务结束后,自动续期不生效
    自己
    配置过期时间:则没有看门狗效应,即为设置多少过期时间,则为多少
  2. 最佳实战:
    自己设置过期时间,这样省去续期操作

⑥读写锁

  1. 实战使用
    redisson.getReadWriteLock(“rw-lock”);
    lock.writelock();
    写操作
    lock.unlock();
    lock.readlock();
    读操作
    lock.unlock();
  2. 介绍
    写操作为互斥锁,读操作为共享锁
    写时不可写和读
    读时只能读不能写

⑦信号量(分布式信号量)

谷粒商城8:分布式锁使用和springcache的整合_第3张图片

  • 信号量=多把锁
    存入一个"park":3
    每次停车 park.acquire() park-1
    每次释放 park.release() park+1

⑧闭锁

谷粒商城8:分布式锁使用和springcache的整合_第4张图片

  • 相当于固定数量的资源(用完即没)
    存入一个"door":5
    每次door.countDown() door-1
    直到door-1到0 执行door.await()之后的方法

⑨更新数据需求

  • 需求
    缓存里的数据如何保证和数据库里的数据一致?
    双写模式:数据更新时,改数据库也改缓存数据
    (卡顿容易出现脏数据)
    失效模式:数据库改完之后,删掉缓存
    (还会出现脏数据)

⑩最佳实战

  • 数据经常修改:直接读数据库
  • 数据并发几率小,容忍大程度不一致:设置缓存
    缓存数据+读写锁+过期时间

2.springche的使用

①整体结构

谷粒商城8:分布式锁使用和springcache的整合_第5张图片

②注解的使用(底层都为原子操作)

  • @Cacheable(value=“category”,key=“#root.methodName”)
    • 当前结果需要缓存
    • 缓存没有调用方法,缓存有则使用缓存
    • key自动生成 value序列化 TTL永不过期
  • 解决问题
    • key:spring.cache.redis.use-key-prefix=true设置默认加前缀为注解的value值(为cache的组)
      key="#root.methodName"指定名字为当前的方法名
    • TTL:spring.cache.redis.time-to-live=3600000设置过期时间为1个小时
    • value值:设置存储为json数据
      原理:CacheAutoConfig->RedisCacheConfig->RedisCacheManager->初始所有的缓存->每个缓存用的配置->如果有redisConfiguration则用,没有则用默认->自定义注入redisConfiguration
@EnableConfigurationProperties(CacheProperties.class)
@EnableCaching
@Configuration
public class MyCacheConfig {
    /**
     * 配置文件中的东西没有用到
     * <p>
     * 1、原来和配置文件绑定的配置类是这样的
     *  @return
     * @ConfigurationProperties(prefix="spring.cache") public class CacheProperties
     * 2、让他生效
     * @EnableConfigurationProperties(CacheProperties.class)
     */
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();


        //更改序列化机制
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        //保存value为JSON
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        //将配置文件中的所有配置都生效
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        //设置配置文件中的各项配置,如过期时间
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }
        return config;
    }
}
  • @CacheEvict(value={“category”},key = “‘getLevel1Categorys’”)
    • 为失效模式,即当前写操作成功后,删除缓存中保存的数据
  • 需求:更新一个表,删除两个缓存
    • @Caching(evict = {
      @CacheEvict(value={“category”},key = “‘getLevel1Categorys’”),
      @CacheEvict(value={“category”},key = “‘getCatelogJson’”)
      })
    • @cacheEvict(value=“category”)直接删除分区的所有缓存
  • spring-cache的不足
  1. 读模式:
    缓存穿透:查询一个null数据。缓存空数据
    解决方案:spring.cache.redis.cache-null-values=true
    缓存击穿:大量并发同时查询一个正好过期的数据
    解决方案:加锁(让一个人查数据库)默认不加锁。
    @Cacheable(value={“category”},key=“#root.methodName”,sync = true)
    sync可以解决击穿
    缓存雪崩:大量key同时过期
    解决方案:指定过期时间。spring.cache.redis.time-to-live=3600000
  2. 写模式:
    读写加锁:
    引入cannel:记录mysql更新来更新数据库
    读多写多:直接查询数据库
  3. 总结
    常规数据(读多写少一致性要求不高):完全可以使用springcache
    特殊数据:特殊涉及

你可能感兴趣的:(谷粒商城,分布式,数据库,java)