redis学习

2.学习redis缓存

2.1缓存机制的说明:

 

2.2缓存机制的原理说明

缓存机制:

缓存中的数据一定是数据库中的数据,使用主要目的是降低用户访问物理设备的频次

如果数据库的记录更新,则缓存应该同步更新

1.缓存的数据结构  K-V结构进行数据保存

2.开发语言的选择   C语言程序

3.缓存数据的运行环境在内存中,断电即擦除,将内存数据进行持久化操作

4.如果要不停的添加缓存记录,肯定会造成内存溢出,定期优化缓存机制

    1).LRU算法   2). LFU算法   3).Random算法  4).TTL算法

5.缓存也需要实现高可用机制 , 实现搭建缓存集群

2.3Redis介绍

2.3.1官网介绍

效率:读:11.2万次/秒    写:8.6万次/秒   平均:10万次/秒

口诀:1-5-8

 

 

知识扩展

1.数据库:

  关系型数据库:mysql数据库/oracle数据库   2维表  行/列  

  非关系型数据库: mongodb/hbase /redis    1维表   kye1=value1,key2=value2,key3={id:1,name="tomcat",age=18}

中间件:

50万次/秒  吞吐量

2.4redis安装

2.4.1上传安装包

 

2.4.2解压redis删除多于的

说明:tar -xvf redis-5.4.tar.gz 解压完成后删除压缩包,改名

2.4.3安装redis

说明:在redis根目录中执行如下命令

1.make 编译    

2.make install 安装

2.4.4服务器命令

1.启动 redis-server redis.conf

2.进入客户端 redis-cli -p 6379   exit/ctrl+c 退出

3.关闭redis服务    redis-cli -p 6379 shutdown

 

修改redis配置文件

进制换算

 

 

2.redis入门案例

2.1导入jar包

<!--spring整合redis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>

2.2客户端操作string类型

package com.jt.test;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

//@SpringBootTest //目的:动态获取spring容器中的数据
public class TestRedis {

    /**
     * 主要目的测试程序远程操作Redis是否有效
     * 配置redis服务:
     *      1.redis需要关闭IP绑定模式
     *      2.redis关闭保护模式
     *      3.redis最好开启后端运行
     *
     * 完成redis客户端操作
     */
    @Test
    public void test01() throws InterruptedException {
        //1.测试链接
        Jedis jedis = new Jedis("192.168.126.129",6379);
        jedis.set("a", "动态获取redis中的数据");
        System.out.println(jedis.get("a"));

        //2.测试数据是否存在
        if(jedis.exists("a")){
            jedis.set("a", "修改数据");
        }else{
            jedis.set("a", "新增数据");
        }

        //3.删除redis
        jedis.del("a");

        //4.清空所有的数据
        jedis.flushDB();
        jedis.flushAll();

        //5.为数据添加超时时间
        jedis.set("b", "设定超时时间");
        jedis.expire("b", 10);
        Thread.sleep(2000);
        System.out.println(jedis.ttl("b"));
    }

    //原子性
    @Test
    public void test02(){
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.set("c", "测试redis");
        //需求1: 如果数据不存在时,才会为数据赋值.
        jedis.setnx("d","测试setnx方法");
        System.out.println(jedis.get("d"));

        //需求2: 需要为数据添加超时时间,同时满足原子性的要求
                //jedis.set("s", "为数据添加超时时间");
                //有时程序中断了,下列的方法将不会执行.
                //jedis.expire("s", 20);
                //System.out.println(jedis.ttl("s"));
        //为数据添加超时时间
        jedis.setex("s", 20, "为数据添加超时111");
        System.out.println("获取超时时间:"+jedis.ttl("s"));
    }

    /**
     *  需求: 如果数据存在才修改,并且为数据添加超时时间,满足原子性要求
     *  SetParams:
     *          XX: 数据存在时赋值.
     *          NX: 数据不存在时赋值
     *          EX: 添加超时时间单位秒
     *          PX: 添加超时时间单位毫秒
     */
    @Test
    public void test03(){
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.flushAll();
        SetParams setParams = new SetParams();
        setParams.xx().ex(20);
        jedis.set("a", "测试方法",setParams);
        System.out.println(jedis.get("a"));
    }
}

关于list集合说明

1.3.1关于队列的应用场景

秒杀场景:马上过年了,店铺周年店庆,苹果12proMax 12000 1元秒杀? 提前预付活动费 10块   如果秒杀不成功7天之内退还

入门案例测试

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

关于事务控制

 //弱事务控制
    @Test
    public void testTx(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        Transaction transaction = jedis.multi();  //开启事务
        try {
            transaction.set("k", "k");
            transaction.set("c", "c");
            transaction.exec();
        }catch (Exception e){
            e.printStackTrace();
            transaction.discard();
        }
    }

2.springBoot整合Redis

2.1编辑Pro配置文件

2.2编辑redis配置类

2.3编写redis测试类

 

3JSON转化工具API

package com.jt.test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.pojo.ItemDesc;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TestObjectMapper {
    @Test
    public void test01() throws JsonProcessingException {
        ObjectMapper objectMapper=new ObjectMapper();
        ItemDesc itemDesc=new ItemDesc();
        //将对象转化为JSON 调用的是对象get方法获取属性/属性的值
        itemDesc.setItemId(1000L).setItemDesc("对象与jSON转化")
                .setCreated(new Date()).setUpdated(new Date());
        String json=objectMapper.writeValueAsString(itemDesc);
        System.out.println(json);
        //将JSON串中转化对象 调用的是对象的set方法为对象属性赋值
        ItemDesc itemDesc1=objectMapper.readValue(json,ItemDesc.class);
        System.out.println(itemDesc1.getItemDesc());

    }

    @Test
    public void test02() throws JsonProcessingException {
        ObjectMapper objectMapper=new ObjectMapper();
        ItemDesc itemDesc=new ItemDesc();
        //将对象转化为JSON 调用的是对象get方法获取属性/属性的值
        itemDesc.setItemId(1000L).setItemDesc("对象与jSON转化")
                .setCreated(new Date()).setUpdated(new Date());
        ItemDesc itemDesc2=new ItemDesc();
        itemDesc2.setItemId(1000L).setItemDesc("对象与jSON转化2")
                .setCreated(new Date()).setUpdated(new Date());

        List<ItemDesc> list2=new ArrayList<>();
        list2.add(itemDesc);
        list2.add(itemDesc2);
        String json=objectMapper.writeValueAsString(list2);
        System.out.println(json);
        //将JSON串中转化对象 调用的是对象的set方法为对象属性赋值
        List list=objectMapper.readValue(json,list2.getClass());
        System.out.println(list);

    }
}

封装工具API

package com.jt.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 该工具类的主要功能是实现对象与JSON串的互相转化
 * 1.对象转为JSON
 * 2.JSON转化为对象
 */
public class ObjectMapperUtil {
    private static final ObjectMapper MAPPER=new ObjectMapper();
    //1.对象转化为JSON
    public static  String toJSON(Object object){
        try {
            return MAPPER.writeValueAsString(object);
        }catch (JsonProcessingException e){
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
    }


    //2.将JSON转化为对象 要求用户传递什么类型的参数就返回什么对象
    public static <T> T toObj(String json,Class<T> target){
        try {
            return MAPPER.readValue(json, target);
        }catch (JsonProcessingException e){
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
    }
}


业务说明

商品分类信息每次展开封闭的节点。都需要查询数据库,这样的效率并不高,可以使用redis缓存来提升效率

流程:

1.用户第一次查询先查询缓存

2.缓存中没有数据(这就是第一次查询),查询数据库,将数据库记录保存到缓存中即可

3.缓存中有记录直接通过缓存获取数据之后返回即可

   /**
     * 实现商品分类的缓存操作
     * 原理说明:
     * 1.定义存取redis中的key   “业务的名称+标识符”  ITEMCAT_PARENT::0
     * 2.通过key可以获取redis中的记录
     * 3.空   查询数据库 将返回值结果保存到缓存中
     * 4.非空  直接将缓存获取之后,返回给用户即可
     *
     */
    @Autowired
    private Jedis jedis;
    @Override
    public List<EasyUITree> findItemCatCache(Long parentId) {
        String key="ITEMCAT_PARENTID::"+parentId;
        List treeList=new ArrayList();
        if(jedis.exists(key)){
            //如果存在则直接返回
            String json=jedis.get(key);
          treeList=  ObjectMapperUtil.toObj(json, treeList.getClass());
            System.out.println("查询redis缓存");
        }else {
            //如果不存在则查询数据库
            treeList=findItemCatList(parentId);
            //将数据保存到缓存中
               //将java对象转化为JSON串存到缓存中
            String json=ObjectMapperUtil.toJSON(treeList);
            jedis.set(key,json);
            System.out.println("查询数据库");
        }
        return treeList;
    }

利用AOP实现商品分类缓存

为什么使用AOP

问题一:如果将代码直接写死,那么代码不具有通用性

问题2:代码冗余,代码的耦合性高

AOP:面向切面编程

AOP作用:在不修改原有的方法的条件下,对原有的方法进行扩展

关于AOP复习

公式:AOP=切入点表达式+通知方法

常见的通知方法:

1.before              目标方法执行之前执行

2.afterThrowing   目标方法执行之后 抛出异常执行

3.afterReturing    目标方法执行之后  返回结果是执行

4.after                目标方法执行之后执行

5.around            环绕通知功能最为强大  可以控制目标方法的执行 在目标方法执行前后都要执行

 

常见切入点表达式:

1.bean(bean的id) 按bean匹配!什么是bean?   -----spring容器管理的对象就叫bean    粗粒度

2.within(包名.类名)按照包路径匹配  其中可以使用通配符*代替

       within("com.jt.service") 位于com.jt.service中的包得所有的类都会匹配    粗粒度

3.execution(返回值类型   包名.类名.方法名(参数列表)) 匹配的是方法参数级别         细粒度

   execution(*com.jt.service.*.*(..))  解释:返回值类型任意  在com.jt.service的包路径的任意类的任意方法的任意参数

execution(*com.jt.service.userService.add*(..))

4.@annotation(包名.注解名称)   按照注解匹配    常用的切入点表达式

关于AOP的案例

package com.jt.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component//组件   将类交给spring容器管理
@Aspect//表示我是一个切面
public class RedisAOP {
    //公式aop=切入点表达式+通知方法
   //表达式一 @Pointcut("bean(itemCateServiceImpl)")
  //表达式二  @Pointcut("within(com.jt.service.*)")
   //表达式三
    @Pointcut("execution(* com.jt.service..*.*(..))")
    public void pointCut(){
    }
    //如何获取,目标对象的相关参数????
    //注意这里只能用JoinPoint  因为ProceedingJoinPoint is only supported for around advice
    //也就是说ProceedingJoinPoint只能用于环绕通知
    @Before("pointCut()")
    public void befor(JoinPoint joinPoint){//连接点
        Object target=joinPoint.getTarget();//获取目标对象
        Object[] args=joinPoint.getArgs();//获取方法参数
        String className=joinPoint.getSignature().getDeclaringTypeName();//获取类名称
        String methodName=joinPoint.getSignature().getName();//获取方法名称
        System.out.println("目标对象"+target);
        System.out.println("方法参数"+ Arrays.toString(args));
        System.out.println("类名称"+className);
        System.out.println("方法名称"+methodName);
        System.out.println("我是前置通知!!!!!!!");
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值