• Redis——(7)redis作为mybatis缓存整合&二级缓存的整合


    1.作为mybits的缓存整合 

        1)用户第一次访问的时候获取数据库的值,再次访问时直接从缓存中获取数据

          2)设置缓存过期时间

          3)项目8080端口是对外端口(向外部暴露的端口),区别于内部进程号,查内部端口用ps -ef|grep port,查外部端口用lsof -i:port

    判断进程是否正常启动

    启动会有一段时间datasource

    结果:

     

    先从缓存中拿数据,找不到再从DB中刷数据

    2.作为mybits的二级缓存的整合

     (1)springboot cache的使用:可以结合redis、ehcache等缓存

    之前的操作;1)先到redis缓存中去取值

                          2)如果找不到到db中去取值

                          3)将db中的值刷到缓存

    这3个步骤都是固定的所以就有了cache

            一级缓存是:sqlSession,sql建立连接到关闭连接的数据缓存

            二级缓存是:全局

       @CacheConfig(cacheNames="userInfoCache")  在同个redis里面必须唯一

       @Cacheable(查) :

       来划分可缓存的方法 - 即,结果存储在缓存中的方法,以便在后续调用(具有相同的参数)时,返回缓存中的值而不必实际执行该方法

    @CachePut(修改、增加) :

        当需要更新缓存而不干扰方法执行时,可以使用@CachePut注释。也就是说,始终执行该方法并将其结果放入缓存中(根据@CachePut选项)

        @CacheEvict(删除) :

         对于从缓存中删除陈旧或未使用的数据非常有用,指示缓存范围内的驱逐是否需要执行而不仅仅是一个条目驱逐

        (2)springboot cache的整合步骤:

          1)引入pom.xml依赖:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-cacheartifactId>
    4. dependency>

           2)开启缓存注解: @EnableCaching(RedisConfig类           配置类)

           3)在方法上面加入SpEL         

       @CacheConfig(cacheNames="userInfoCache")  在同个redis里面必须唯一             指定cache的名称       

    @Cacheable(查) :

       来划分可缓存的方法 -

    即,结果存储在缓存中的方法,以便在后续调用(具有相同的参数)时,返回缓存中的值而不必实际执行该方法

    @CachePut(修改、增加) :

        当需要更新缓存而不干扰方法执行时,可以使用@CachePut注释。

    也就是说,始终执行该方法并将其结果放入缓存中(根据@CachePut选项)

    @CacheEvict(删除) :

         对于从缓存中删除陈旧或未使用的数据非常有用,指示缓存范围内的驱逐是否需要执行而不仅仅是一个条目驱逐

    结果:

    1. @Service
    2. @CacheConfig(cacheNames="userInfoCache") // 本类内方法指定使用缓存时,默认的名称就是userInfoCache
    3. @Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class)
    4. public class UserService {
    5. @Autowired
    6. private UserMapper userMapper;
    7. // 因为必须要有返回值,才能保存到数据库中,如果保存的对象的某些字段是需要数据库生成的,
    8. //那保存对象进数据库的时候,就没必要放到缓存了
    9. @CachePut(key="#p0.id") //#p0表示第一个参数
    10. //必须要有返回值,否则没数据放到缓存中
    11. public User insertUser(User u){
    12. this.userMapper.insert(u);
    13. //u对象中可能只有只几个有效字段,其他字段值靠数据库生成,比如id
    14. return this.userMapper.find(u.getId());
    15. }
    16. @CachePut(key="#p0.id")
    17. public User updateUser(User u){
    18. this.userMapper.update(u);
    19. //可能只是更新某几个字段而已,所以查次数据库把数据全部拿出来全部
    20. return this.userMapper.find(u.getId());
    21. }
    22. @Nullable
    23. @Cacheable(key="#p0") // @Cacheable 会先查询缓存,如果缓存中存在,则不执行方法
    24. public User findById(String id){
    25. System.err.println("根据id=" + id +"获取用户对象,从数据库中获取");
    26. Assert.notNull(id,"id不用为空");
    27. return this.userMapper.find(id);
    28. }
    29. @CacheEvict(key="#p0") //删除缓存名称为userInfoCache,key等于指定的id对应的缓存
    30. public void deleteById(String id){
    31. this.userMapper.delete(id);
    32. }
    33. //清空缓存名称为userInfoCache(看类名上的注解)下的所有缓存
    34. //如果数据失败了,缓存时不会清除的
    35. @CacheEvict(allEntries = true)
    36. public void deleteAll(){
    37. this.userMapper.deleteAll();
    38. }
    39. @Nullable
    40. @Cacheable(value = "UserInfoList", keyGenerator = "simpleKeyGenerator") // @Cacheable 会先查询缓存,如果缓存中存在,则不执行方法
    41. public User findByIdTtl(String id){
    42. System.err.println("根据id=" + id +"获取用户对象,从数据库中获取");
    43. Assert.notNull(id,"id不用为空");
    44. return this.userMapper.find(id);
    45. }
    46. }

    提问:springboot cache 存在什么问题,

                                            第一,生成key过于简单,容易冲突       userinfoCache::3  (同一个redis只能有一个名称 ) key+参数  

                                            第二,无法设置过期时间,默认过期时间为永久不过期            (上面的3中方法)

                                            第三,配置序列化方式,默认的是序列化JDKSerialazable            jackson/json

    如果不设置序列化的化可能会造成乱码等格式的问题

         (3)springboot cache自定义项

            1)自定义KeyGenerator  

             

            2)自定义cacheManager,设置缓存过期时间

            3)自定义序列化方式,Jackson

    使用方法:(前两个)

    1. @Configuration
    2. @EnableCaching
    3. public class RedisConfig {
    4. public RedisTemplate redisTemplate(RedisConnectionFactory factory){
    5. RedisTemplate redisTemplate = new RedisTemplate<>();
    6. redisTemplate.setConnectionFactory(factory);
    7. return redisTemplate;
    8. }
    9. @Bean
    10. public KeyGenerator simpleKeyGenerator() {
    11. return (o, method, objects) -> {
    12. StringBuilder stringBuilder = new StringBuilder();
    13. stringBuilder.append(o.getClass().getSimpleName());
    14. stringBuilder.append(".");
    15. stringBuilder.append(method.getName());
    16. stringBuilder.append("[");
    17. for (Object obj : objects) {
    18. stringBuilder.append(obj.toString());
    19. }
    20. stringBuilder.append("]");
    21. return stringBuilder.toString();
    22. };
    23. }
    24. @Bean
    25. public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    26. return new RedisCacheManager(
    27. RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
    28. this.getRedisCacheConfigurationWithTtl(600), // 默认策略,未配置的 key 会使用这个
    29. this.getRedisCacheConfigurationMap() // 指定 key 策略
    30. );
    31. }
    32. /**
    33. *
    34. * 自定义某个key的过期时间
    35. */
    36. private Map getRedisCacheConfigurationMap() {
    37. Map redisCacheConfigurationMap = new HashMap<>();
    38. redisCacheConfigurationMap.put("UserInfoList", this.getRedisCacheConfigurationWithTtl(100));
    39. redisCacheConfigurationMap.put("UserInfoListAnother", this.getRedisCacheConfigurationWithTtl(18000));
    40. return redisCacheConfigurationMap;
    41. }
    42. /**
    43. *
    44. * 自定义序列化的方式
    45. */
    46. private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
    47. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
    48. ObjectMapper om = new ObjectMapper();
    49. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    50. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    51. jackson2JsonRedisSerializer.setObjectMapper(om);
    52. RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
    53. redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
    54. RedisSerializationContext
    55. .SerializationPair
    56. .fromSerializer(jackson2JsonRedisSerializer)
    57. ).entryTtl(Duration.ofSeconds(seconds));
    58. return redisCacheConfiguration;
    59. }
    60. }
    61. 相关阅读:
      8 Redis与Lua
      leetcode 1004.最大连续1的个数 III 滑动窗口
      MongoDB基础之文档DML操作
      Java并发面试题:(一)线程的5种状态及转换
      Android-Firebase快速解决合规问题第2篇,解决firebase_performance库获取软件安装列表的行为
      zigbee笔记:七、zigbee系统电源管理与睡眠唤醒
      MySQL图形管理工具的安装与使用
      Leetcode 2431.最小偶倍数
      【教3妹学编程-算法题】最大化数组末位元素的最少操作次数
      基于单片机的空气质量检测系统设计
    62. 原文地址:https://blog.csdn.net/qq_29235677/article/details/88932863