关于redis:第三阶段-Day12-Redis命令-SpringBoot整合redis-AoP实现Redis缓存

2次阅读

共计 5965 个字符,预计需要花费 15 分钟才能阅读完成。

  1. Redis 入门案例

=============

1.1 Redis 常见用法

1.1.1 setex 学习

`/**
     * 2. 需要:
     *      1. 向 redis 中插入数据  k-v
     *      2. 为 key 设定超时工夫  60 秒后生效.
     *      3. 线程 sleep 3 秒
     *      4. 获取 key 的残余的存活工夫.
     *
     *   问题形容: 数据肯定会被删除吗??????
     *   问题阐明: 如果应用 redis 并且须要增加超时工夫时 个别须要满足原子性要求.
     *   原子性:   操作时要么胜利 要么失败. 然而必须同时实现.
     */
    @Test
    public void test02() throws InterruptedException {Jedis jedis = new Jedis("192.168.126.129",6379);
        jedis.setex("宝可梦", 60, "小火龙 妙蛙种子");
        System.out.println(jedis.get("宝可梦"));

       /* Jedis jedis = new Jedis("192.168.126.129",6379);
        jedis.set("宝可梦", "小火龙 妙蛙种子");
        int a = 1/0;    // 可能会出异样
        jedis.expire("宝可梦", 60);
        Thread.sleep(3000);
        System.out.println(jedis.ttl("宝可梦"));*/
    }` 

1.1.2 setnx

`/**
     * 3. 需要如果发现 key 曾经存在时 不批改数据. 如果 key 不存在时才会批改数据.
     *
     */
    @Test
    public void test03() throws InterruptedException {Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.setnx("aaaa", "测试 nx 的办法");
        /*if(jedis.exists("aaa")){System.out.println("key 曾经存在 不做批改");
        }else {jedis.set("aaa", "测试数据");
        }*/
        System.out.println(jedis.get("aaaa"));
    }` 


1.1.3 set 超时工夫原子性操作

 `/**
     * 需要:
     *  1. 要求用户赋值时, 如果数据存在则不赋值.  setnx
     *  2. 要求在赋值操作时, 必须设定超时的工夫 并且要求满足原子性 setex
     */
    @Test
    public void test04() throws InterruptedException {Jedis jedis = new Jedis("192.168.126.129", 6379);
        SetParams setParams = new SetParams();
        setParams.nx().ex(20);
        jedis.set("bbbb", "实现业务操作 AAAA", setParams);
        System.out.println(jedis.get("bbbb"));

    }` 

1.1.4 list 汇合练习

 `@Test
    public void testList() throws InterruptedException {Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.lpush("list", "1","2","3");
        System.out.println(jedis.rpop("list"));
    }` 

1.1.5 redis 事务管制

 `@Test
    public void testTx() throws InterruptedException {Jedis jedis = new Jedis("192.168.126.129", 6379);
        //1. 开启事务
        Transaction transaction = jedis.multi();
        try {transaction.set("aa", "aa");
            // 提交事务
            transaction.exec();}catch (Exception e){e.printStackTrace();
            // 回滚事务
            transaction.discard();}
    }` 


2. 秒杀业务逻辑—分布式锁机制

6988 —1 块 1 部手机 20 显示抢购胜利 并且领取了 1 块钱…
问题:
1.tomcat 服务器有多台
2. 数据库数据只有 1 份
3. 必然会呈现高并发的景象.
如何实现抢购…

2.1 惯例锁操作

2.1.1 超卖的起因

2.1.2 同步锁的问题

阐明: 同步锁只能解决 tomcat 外部的问题, 不能解决多个 tomcat 并发问题

2.1.3 分布式锁机制

思维:
1. 锁应该应用第三方操作 , 锁应该专用.
2. 准则: 如果锁被人正在应用时, 其余的用户不能操作.
3. 策略: 用户向 redis 中保留一个 key, 如果 redis 中有 key 示意有人正在应用这把锁 其余用户不容许操作. 如果 redis 中没有 key , 则示意我能够应用这把锁.
4. 危险: 如何解决死锁问题. 设定超时工夫.

  1. SpringBoot 整合 Redis

=====================

3.1 编辑配置文件 redis.pro

阐明: 因为该配置被其余的我的项目独特应用, 则应该写到 jt-common 中.

3.2 编辑配置类

阐明: 编辑 redis 配置类. 将 Jedis 对象交给 Spring 容器进行治理.

`@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {@Value("${redis.host}")
    private String host;
    @Value("${redis.port}")
    private Integer port;

    @Bean
    public Jedis jedis(){return new Jedis(host,port);
    }
}` 

3.3 对象与 JSON 转化 ObjectMapper 介绍

3.3.1 简略对象转化

`/**
     * 测试简略对象的转化
     */
    @Test
    public void test01() throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("商品详情信息")
                .setCreated(new Date()).setUpdated(new Date());
        // 对象转化为 json
        String json = objectMapper.writeValueAsString(itemDesc);
        System.out.println(json);

        //json 转化为对象
        ItemDesc itemDesc2 = objectMapper.readValue(json, ItemDesc.class);
        System.out.println(itemDesc2.getItemDesc());
    }` 


3.3.2 汇合对象转化

 `/**
     * 测试汇合对象的转化
     */
    @Test
    public void test02() throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("商品详情信息 1")
                .setCreated(new Date()).setUpdated(new Date());
        ItemDesc itemDesc2 = new ItemDesc();
        itemDesc2.setItemId(100L).setItemDesc("商品详情信息 2")
                .setCreated(new Date()).setUpdated(new Date());
        List<ItemDesc> lists = new ArrayList<>();
        lists.add(itemDesc);
        lists.add(itemDesc2);
        //[{key:value},{}]
        String json = objectMapper.writeValueAsString(lists);
        System.out.println(json);

        // 将 json 串转化为对象
        List<ItemDesc> list2 = objectMapper.readValue(json, lists.getClass());
        System.out.println(list2);
    }` 

3.4 编辑工具 API

`package com.jt.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.pojo.ItemDesc;
import org.springframework.util.StringUtils;

public class ObjectMapperUtil {

    /**
     * 1. 将用户传递的数据转化为 json 串
     * 2. 将用户传递的 json 串转化为对象
     */
    private static final ObjectMapper MAPPER = new ObjectMapper();

     //1. 将用户传递的数据转化为 json 串
    public static String toJSON(Object object){if(object == null) {throw new RuntimeException("传递的数据为 null. 请查看");
        }

        try {String json = MAPPER.writeValueAsString(object);
            return json;
        } catch (JsonProcessingException e) {
            // 将查看异样, 转化为运行时异样
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    // 需要: 要求用户传递什么样的类型, 我返回什么样的对象  泛型的常识
    public static <T> T toObj(String json,Class<T> target){if(StringUtils.isEmpty(json) || target ==null){throw new RuntimeException("参数不能为 null");
        }
        try {return  MAPPER.readValue(json, target);
        } catch (JsonProcessingException e) {e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}` 

3.5 商品分类的缓存实现

3.5.1 实现步骤

1. 定义 Redis 中的 key key 必须惟一不能反复. 存 取 key =“ITEM_CAT_PARENTID::70”
2. 依据 key 去 redis 中进行查问 有数据 没有数据
3. 没有数据 则查询数据库获取记录 之后将数据保留到 redis 中 不便后续应用.
4. 有数据 示意用户不是第一次查问 能够将缓存数据间接返回即可.

3.5.2 编辑 ItemCatController

3.5.3 编辑 ItemCatService

`@Override
    public List<EasyUITree> findItemCatListCache(Long parentId) {
        //0. 定义公共的返回值对象
        List<EasyUITree> treeList = new ArrayList<>();
        //1. 定义 key
        String key = "ITEM_CAT_PARENTID::"+parentId;
        //2. 检索 redis 服务器, 是否含有该 key

        // 记录时间
        Long startTime = System.currentTimeMillis();
        if(jedis.exists(key)){
            // 数据存在
            String json = jedis.get(key);
            Long endTime = System.currentTimeMillis();
            // 须要将 json 串转化为对象
            treeList = ObjectMapperUtil.toObj(json,treeList.getClass());
            System.out.println("从 redis 中获取数据 耗时:"+(endTime-startTime)+"毫秒");
        }else{
            //3. 数据不存在  查询数据库
            treeList = findItemCatList(parentId);
            Long endTime = System.currentTimeMillis();
            //3. 将数据保留到缓存中
            String json = ObjectMapperUtil.toJSON(treeList);
            jedis.set(key, json);
            System.out.println("查询数据库 耗时:"+(endTime-startTime)+"毫秒");
        }
        return treeList;
    }` 

3.5.4 应用 Redis 的速度差

  1. AOP 实现 Redis 缓存

================

4.1 如何了解 AOP

名称: 面向切面编程
作用: 升高零碎中代码的耦合性, 并且在不扭转原有代码的条件下对原有的办法进行性能的扩大.
公式: AOP = 切入点表达式 + 告诉办法

4.2 告诉类型

1. 前置告诉 指标办法执行之前执行
2. 后置告诉 指标办法执行之后执行
3. 异样告诉 指标办法执行过程中抛出异样时执行
4. 最终告诉 无论什么时候都要执行的告诉
特点: 上述的四大告诉类型 不能干涉指标办法是否执行.个别用来做程序运行状态的记录. 监控

5. 盘绕告诉 在指标办法执行前后都要执行的告诉办法 该办法能够控制目标办法是否运行.joinPoint.proceed(); 性能作为弱小的.

4.3 切入点表达式

了解: 切入点表达式就是一个程序是否进入告诉的一个判断 (IF)
作用: 当程序运行过程中 ,满足了切入点表达式时才会去执行告诉办法,实现业务的扩大.
品种(写法):

  1. bean(bean 的名称 bean 的 ID) 只能拦挡具体的某个 bean 对象 只能匹配一个对象

lg: bean(“itemServiceImpl”)

  1. within(包名. 类名) within(“com.jt.service.*”) 能够匹配多个对象

粗粒度的匹配准则 按类匹配

 3. execution(返回值类型 包名. 类名. 办法名(参数列表))   最为弱小的用法
      lg : execution(* com.jt.service..*.*(..))
              返回值类型任意  com.jt.service 包下的所有的类的所有的办法都会被拦挡.
      4.@annotation(包名. 注解名称)  依照注解匹配.
正文完
 0