《Redis入门》

Redis初始

Linux中安装Redis

redis的说明

Redis 是一个开源的,内存中的数据结构存储系统它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构

Redis常用命令

string类型:

命令 说明 案例
set 添加key-value set username admin
get 根据key获取数据 get username
exists 判断key是否存在 exists name(返回1存在 0不存在)
del 删除redis中的key del key
Keys 用于查询符合条件的key keys * 查询redis中全部的key,keys n?me 使用占位符获取数据 keys nam* 获取nam开头的数据

Hash类型

命令 说明 案例
hset 为对象添加数据 hset key field value
hget 获取对象的属性值 hget key field
hexists 判断对象的属性是否存在 HEXISTS key field1表示存在 0表示不存在
hdel 删除hash中的属性 hdel user field

List类型

说明

Redis中的List集合是双端循环列表,分别可以从左右两个方向插入数据
List集合可以当做队列使用,也可以当做栈使用

队列:存入数据的方向和获取数据的方向相反

栈:存入数据的方向和获取数据的方向相同

命令 说明 案例
lpush 从队列的左边入队一个或多个元素 LPUSH key value
rpush 从队列的右边入队一个或多个元素 RPUSH key value
lpop 从队列的左端出队一个元素 LPOP key
rpop 从队列的右端出队一个元素 RPOP key

Redis事务命令

说明

说明:redis中操作可以添加事务的支持.一项任务可以由多个redis命令完成,如果有一个命令失败导致入库失败时.需要实现事务回滚.

命令 说明 案例
multi 标记一个事务开始 127.0.0.1:6379> MULTI
exec 执行所有multi之后发的命令 127.0.0.1:6379> EXEC
discard 丢弃所有multi之后发的命令

Redis入门

导入jar包

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

客户端操作String类型

前提

创建一个Java类测试类

配置redis服务

主要目的测试程序远程操作Redis是否有效
1.redis需要关闭IP绑定模式
2.redis关闭保护模式
3.redis最好开启后端运行

redis入门案例(1)

整体结构

     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"));
    }

1 . 测试链接

    Jedis jedis = new Jedis("192.168.126.129",6379);
    jedis.set("a", "动态获取redis中的数据");
    System.out.println(jedis.get("a"));
1 - Jedis是在springboot中使用redis的时候引入到包,他springboot中代表redis new一个Jedis的时候参数的方式来引入redis所在的ip地址和端口。
2 - set是 添加key和value
3 - get是 获取根据key获取value

2 . 测试数据是否存在

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

判断 a 是否存在 如果存在的话a的value值改成<修改数据>,如果不存在的话a的value是<新增数据>

3 . 删除redis

    jedis.del("a");
del 表示删除

删除key 是 a 的数据

4 . 清空所有的数据

    jedis.flushDB();
    jedis.flushAll();
flushDB 清空单个数据库
flushAll 清空全部数据库

此方法很危险删除你的数据所以不建议使用

5 . 为数据添加超时时间

    jedis.set("b", "设定超时时间");
    jedis.expire("b", 10);
    Thread.sleep(2000);
    System.out.println(jedis.ttl("b"));

redis入门案例(2)

原子性

什么是原子性?

一个事务是一个不可分割的最小工作单位,要么都成功要么都失败。

原子操作是指你的一个业务逻辑必须是不可拆分的.比如你给别人转钱,你的账号扣钱,别人的账号
增加钱,这个业务逻辑就是原子性的,这个操作就是原子操作,要么都成功要么都失败。

Redis所有单个命令的执行都是原子性的。

整体结构

     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.setex("s", 20, "为数据添加超时111");
        System.out.println("获取超时时间:"+jedis.ttl("s"));
    }

需求1

如果数据不存在时,才会为数据赋值.

         jedis.setnx("d","测试setnx方法");
         System.out.println(jedis.get("d"));
setnx - 在指定的 key 不存在时,为 key 设置指定的值

如果d不存在的话才指定值

需求2

需要为数据添加超时时间,同时满足原子性的要求

    jedis.setex("s", 20, "为数据添加超时111");
    System.out.println("获取超时时间:"+jedis.ttl("s"));

setex - 指定的key设置值及其过期时间。如果key已经存在, setex 命令将会替换旧的值

需求3

如果数据存在才修改,并且为数据添加超时时间,满足原子性要求
SetParams:
XX: 数据存在时赋值.
NX: 数据不存在时赋值
EX: 添加超时时间单位秒
PX: 添加超时时间单位毫秒
使用Redis中的setparams

 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"));
 }
flushAll - 清空全部数据库(Redis)
xx().ex(20) - 分别为 xx() 数据存在时,ex(20) 超时20毫秒

关于List集合说明

关于队列应用场景

秒杀场景: 马上过年了, 店铺周年店庆 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")); //队列
    }
lpush - 从列队的左边入队 一个或者多个元素
rpop - 从队列的右端出队一个元素

SpringBoot整合Redis

1 . 编辑properties配置文件

redis是公共的,建议配置放到公共的目录中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VCFhgeRR-1612708919265)(/img/bVcOw3d)]

创建一个properties配置文件里面写redis的节点

2 . 编辑配置类

需要创建redis的一个配置类,配置类也放到公共的目录中

    @Configuration  //表示一个配置类  一般会与@Bean的注解联用
    @PropertySource("classpath:/redis.properties") //导入配置文件
    public class RedisConfig {
    
    

    @Value("${redis.host}")
    private String host;
    @Value("${redis.port}")
    private Integer port;

    @Bean   //将方法的返回值结果,交给spring容器进行管理.
    public Jedis jedis(){
    
    

        return new Jedis(host, port);
        }
    }
@Configuration - 当前的类是配置类
@PropertySource - 导入配置文件
@bean - 把结果交给spring管理

3 . 测试redis的案例

在test中测试我们的配置

在这里插入图片描述

@SpringBootTest //目的:动态获取spring容器中的数据
public class TestRedis {
    
    
    @Autowired
 private Jedis jedis;
    @Test
 public void testRedis(){
    
    
        jedis.set("jedis", "spring测试");
        System.out.println(jedis.get("jedis"));
    }
}

运行时出现这样表示成功


JSON转化工具API

测试1

   @Test
   public void test01() throws JsonProcessingException {
    
    
       ObjectMapper objectMapper = new ObjectMapper();
       //将对象转化为JSON 调用的是对象的get方法获取属性/属性的值
       Sysprod sysprod = new Sysprod();
       sysprod.setId(1000).setTitle("对象与json转化").setProd_name("prodname").setPrice(1000).setProd_id(1000);
       String json = objectMapper.writeValueAsString(sysprod);
       System.out.println(json);
       //将JSON串转化为对象 调用的是对象的set方法为对象属性赋值
       Sysprod sysprod1 = objectMapper.readValue(json, Sysprod.class);
       System.out.println(sysprod1.getTitle());
   }
objectMapper - 将java对象与json格式相互转化的类
writeValuesAsString - 方法就可以把对角转化成json字符串(get方法)
readValue - 方法就可以把对角转化成json字符串(set方法)

把数据的get和set方式都要转换json类型,获取和赋值都转成json

sysprod 是 pojo对象

测试2

     @Test
    public void test02() throws JsonProcessingException {
    
    
        ObjectMapper objectMapper = new ObjectMapper();
        //将对象转化为JSON  调用的是对象的get方法获取属性/属性的值
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(1000L).setItemDesc("对象与json转化").setCreated(new Date()).setUpdated(new Date());
        ItemDesc itemDesc2 = new ItemDesc();
        itemDesc2.setItemId(2000L).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 list3 = objectMapper.readValue(json,list2.getClass());
        System.out.println(list3);
        }
    }

如果有两个pojo对象那么把两个pojo对象包装给list集合


封装工具API

该工具类,主要的功能实现对象与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);
            }
        }
    }
第一步:new 一个 objectMapper类,(静态的和常量)修饰符
第二步:对象转化为JSON(返回string类型),把异常不要抛出去而且调用
第三步:JSON转化对象 要求用户传什么类型就返回给对象

工具类的功能:

我们发出的数据转化成json格式到客户端,用户传来的json数据到服务端就转化对象

利用缓存实现查询(高级案例)

说明:如果页面的数据每次都数据库里查询的话这样的效率并不高,可以使用redis缓存来提升效率

流程:

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

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

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

第一步,检查初始环境是否正常

1.1 检查properties配置文件是否正常

在这里插入图片描述

1.2检查redis配置类设否正常

在这里插入图片描述

1.3检查json转换配置工具是否正常

在这里插入图片描述

写业务代码

controller层

    @RequestMapping("/find")
    public viewTable module(Sysprod_list sysprod_list,Sysprod sysprod,String name){
    
    
//       return sysprodService.findobj(sysprod_list, sysprod,name);
       return  sysprodService.findCacheobj(sysprod_list, sysprod,name);
    }

业务层

在这里插入图片描述

  • 数据库查询业务
  • redis缓存查询业务

业务层的实现类

导入redis配置类以及

    @Autowired
    private Jedis jedis;

数据库查询业务

 @Override
    @Transactional
    public List<Sysprod> findobj(Sysprod_list sysprod_list, Sysprod sysprod, String name) {
    
    

        List<Sysprod_list> port_list= sysprodLIst.selectList(null);
        for (Sysprod_list letes: port_list) {
    
    
            UpdateWrapper<Sysprod> u=new UpdateWrapper<>();
            System.out.println(letes.getId());
            u.eq("prod_id", letes.getId());
            Sysprod s=sysprod.setProd_name(letes.getName());
            sysprodDao.update(s,u);
        }
        QueryWrapper<Sysprod> q=new QueryWrapper<>();
        q.eq("prod_name", name);
        List<Sysprod> list=sysprodDao.selectList(q);
        return list;
    }

缓存(重要)

 @Override
    public viewTable findCacheobj(Sysprod_list sysprod_list, Sysprod sysprod, String name) {
    
    
        long startTime=System.currentTimeMillis();

        String Key=name;
        List treeList=new ArrayList();

        if (jedis.exists(Key)){
    
    
            String json=jedis.get(Key);
            treeList = RedisUtl.toObject(json, treeList.getClass());
            System.out.println("查询Redis缓存!!!");
            
            long endTime = System.currentTimeMillis();
            System.out.println("耗时:"+(endTime - startTime)+"毫秒");
            System.out.println(jedis.get(Key));
        }else{
    
    
            treeList=findobj(sysprod_list,sysprod,name);

            String json=RedisUtl.toJSON(treeList);
            jedis.set(Key, json);

            System.out.println("查询数据库!!!");
            long endTime = System.currentTimeMillis();
            System.out.println("耗时:"+(endTime - startTime)+"毫秒");
        }
        return new viewTable(treeList);
    }

1.1

 String Key=name;
 List treeList=new ArrayList();
  • 封装存储redis的key值
  • 封装存储redis的value类型和返回值的类型

1.2

  if (jedis.exists(Key)){
    
    
      String json=jedis.get(Key);
      treeList = RedisUtl.toObject(json, treeList.getClass());
      System.out.println("查询Redis缓存!!!");
  • 用户访问时先查询缓存,缓存里受否存在当前的信息
  • key是我们封装的redis key值,第一次查询当然没有key
  • 所以去数据库查询,如果有key值那么 把key的json格式转换成object类型存储LIst中并返回list集合
    • get来获取key的值
    • key的值转化成object,封装list集合
    • list集合返回给客户端

1.3

  }else{
    
    
      treeList=findobj(sysprod_list,sysprod,name);

      String json=RedisUtl.toJSON(treeList);
      jedis.set(Key, json);
  • 如果缓存中找不到的话 在数据库中查询,并返回客户端
  • 同时数据库中查询的值 转换成json格式
  • 转化后存储到redis存储中
  • 缓存中有了数据后 第二次查询时 从缓存中的数据给客户端返回

1.4

	return new viewTable(treeList);
  • 给客户端返回list集合

1.5

在这里插入图片描述

  • 第一次查询 查了数据库
  • 后面的查询都查了 缓存

猜你喜欢

转载自blog.csdn.net/weixin_45103228/article/details/113748890