Redis

 

问题描述

spring开发项目的时候 每次访问时 都会查询一次数据库 对于那些不经常修改的数据 每次都查询数据库 性能差 不够优雅

1. 缓存

缓存的功能 就是提高性能 减少与数据库的交互

1.1. 缓存的思想

  • 当用户第一次查询的时候 去查询数据库 查询到的内容 一方面返给页面 另外一方面做缓存(存在容器中)

  • 当用户第二次查询的时候 此时缓存中 就有了 此时不用查询数据库 就能够拿到数据

  • 当增删改数据库信息时 把缓存清空

核心流程

  • 用户访问 先看缓存中有没有

  • 如果有 则直接拿出 返回给页面

  • 如果没有则查询数据库 把查询出的内容 放到缓存中

1.2. 缓存的弊端

做到数据的实时性 比较麻烦 需要在增删改的时候 清空数据

1.3. 使用Map集合作为缓存

2. 什么是Nosql数据库

  NoSql,叫非关系型数据库,它的全名Not only sql。 是针对关系型数据库来说的

3. Nosql数据的分类

Redis

4. Nosql的好处

为了解决高并发、高可用、高可扩展,大数据存储等一系列问题而产生的数据库解决方案

5. Nosql和关系型数据库区别

  • 区别一

    • 关系型数据库是需要依赖数据库的关系的 比如说主外键 数据在硬盘上

    • 非关系型数据库依赖特殊结果 比如redis是key-value的数据格式 在内存中 可以持久化

  • 区别二

    • 关系型数据库 有主外键关系

    • 非关系型数据库 没有这个概念

  • 区别三:

    • 关系型数据库: 操作的是硬盘 效率低 安全性稍微高

    • 非关系型数据库(redis) 操作的是内存 效率高 但是不安全 数据可能丢失

6. Redis

6.1. 什么是redis

Redis是使用c语言开发的一个高性能键值NoSQL数据库。Redis可以通过一些键值类型来存储数据

6.2. Redis的特点

  • 高性能,持久存储,适应高并发的应用场景。

  • 相比许多键值数据存储,Redis拥有一套较为丰富的数据类型

  • Redis数据库完全在内存中,使用磁盘仅用于持久性。

  • Redis可以将数据复制到任意数量的从服务器。

6.3. Redis的优势

  • 异常快速:Redis的速度非常快,支持丰富的数据类型。读的速度是110000次/s,写的速度是81000次/s 。

  • 操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。

6.4. Redis的作用

  • 缓存

  • 存临时数据

6.5. Redis的下载

github上下载

Redis

6.6. Redis的文件介绍

Redis

6.7. Redis的启动

Redis

运行成功页面

Redis

6.8. 客户端连接

Redis

 

 Redis

6.9. Redis的Value的取值

注意: Redis存的key-value 但是key只能是字符串 value的取值有如下几个类型

  • 字符串(string)

  • 散列(hash)

  • 列表(list)

  • 集合(set)

  • 有序集合(sortedSet)

Redis

 

 

6.10. List&Set&sortSet区别

  • list类型: 有顺序 可以重复

  • set类型:没有顺序 不能重复

  • sortedSet: 有顺序 不能重复

6.11. String类型的操作

6.11.1. 存取单个数据

  • 存值

    set key value

  • 取值

    get key

Redis

6.11.2. 存取多个数据

  • 存值

    mset key value key value ....

  • 取值

    mget key1 key2

    Redis

6.11.3. 删除数据

del key

Redis

6.12. hash类型操作

6.12.1. 存取单个属性值

  • 存值

    hset key field fieldValue

  • 取值

    hget key field

    Redis

6.12.2. 存取多个属性值

  • 存值

    hmset key field1 field1Value field2 fieldValue2

  • 取值

    hmget key field1 field2

    Redis

     

     

6.12.3 删除属性值

  • 语法、

hdel key field1 field2

Redis

6.13. list集合操作

有顺序 可以重复

6.13.1. 右压栈和左弹栈

右压栈 是指 数据从头添加 数据顺序往后排 类似数据往右压 右压栈

左弹栈 是指 数据从左边弹出

  • 右压栈

    lpush key value1 value2 value3

  • 左弹栈

    lpop key (从左边弹出第一个)

Redis

6.13.2. 左压栈和右弹栈

左压栈: 表示数据从后添加

右弹栈: 表示数据从后弹出

  • 左压栈

    rpush key value1 value2 value3

  • 右弹栈

    rpop key (从右边弹出一个)

    Redis

6.13.3. 查看数据

  • 语法

    lrange key startIndex endIndex

    注意: 当endIndex=-1时 表示查询所有

Redis

6.14. 操作set集合

不能重复 没有顺序

6.14.1. 存取数据

  • 存数据

    sadd key value1 value2 value3

  • 取数据

    smembers key

Redis

 

 

6.14.2. 删除数据

  • 语法

    srem key value

Redis

6.15. 操作sortedSet

有序 不能重复

注意:每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

6.15.1 存取值

  • 存值

    zadd key score1 value1 score2 value2

  • 取值

    zrange key startIndex endindex

当endIndex等于-1时 表示查询所有

Redis

6.15.2. 删除值

  • 语法

    zrem key value

    Redis

6.16. Redis的通用指令

key* 获得所有的key

key list* 获得以list开头的key

6.17. Redis的持久化

redis是把数据存在内存中的 如果我们的服务器关机 这个时候内存中的数据将不存在 所以呢要做持久化

当服务器再次启动的时候 redis就会把本地数据加载到内存中

6.17.1. RDB的方式

这种持久化的方式 是默认的 不用任何配置

  • 它的规则

Redis

  • 持久化文件

    Redis 

6.17.2. AOF的方式

每一次操作或者每一秒 都会把记录持久化到硬盘中 (费资源) 到底是每一次还是每一秒 取决于配置

  • 开启方式

    Redis

Redis

6.18. java操作Redis

  • Jedis的方式

  • springdataRedis的方式

6.18.1.Jedis单独的方式

  • 创建java工程

  • 导入jar

    commons-pool2-2.3.jar

​   jedis-2.7.0.jar

  • 创建测试类

  • 注意: junit测试包 通过idea导入

  • 对String的操作

    Redis

     

     

  • 对hash的操作

    Redis

     

     

  • 对List的操作

    Redis

     

     

  • 对set的操作

    Redis

  • sortedSet的操作

    Redis

  • 所有的代码

    package com.shangma.cn;
      ​
      import org.junit.Test;
      import redis.clients.jedis.Jedis;
      ​
      import java.util.List;
      import java.util.Set;
      ​
      public class RedisTest1 {
      ​
          @Test
          public void fun() {
              //如果不写 域名端口 默认就是 本机 默认端口就是6379
      //        Jedis jedis  = new Jedis();
              Jedis jedis = new Jedis("localhost", 6379);
              jedis.set("name", "huige");
              String name = jedis.get("name");
              System.out.println(name);
              jedis.close();//释放资源
          }
          
          //  @Test
        public void fun1() {
            Jedis jedis = new Jedis();
            jedis.hset("wife", "name", "高圆圆");
            String name = jedis.hget("wife", "name");
            System.out.println(name);
            jedis.close();//释放资源
        }
          
          
       //     @Test
        public void fun2() {
            Jedis jedis = new Jedis();
            //右压栈
              //jedis.lpush("s1", "aaa", "bbb", "cccc");
            // 左压栈
            jedis.rpush("s1", "ddd", "eee");
            List<String> si = jedis.lrange("s1", 0, -1);
            si.forEach(System.out::println);
            jedis.close();//释放资源
      ​
        }
          
       //  @Test
            public void fun3() {
            Jedis jedis = new Jedis();
            jedis.sadd("s2", "zs", "ls", "ww");
            Set<String> s2 = jedis.smembers("s2");
            s2.forEach(System.out::println);
            jedis.close();//释放资源
        }
      ​
       // @Test
        public void fun4() {
            Jedis jedis = new Jedis();
            jedis.zadd("mv",20,"如花");
            Set<String> mv = jedis.zrange("mv", 0, -1);
            mv.forEach(System.out::println);
      ​
            jedis.close();//释放资源
        }
            }

     

6.18.2. Jedis连接池的方式

每次操作redis都会频繁创建和关闭链接 资源浪费 并且性能不好

所以我们需要连接池 类似数据库连接一样

具体代码

        /**
         * 连接池的使用
         */
    //    @Test
        public void pool() {
            JedisPoolConfig config  = new JedisPoolConfig();
            // 最大空闲数
            config.setMaxIdle(10);
    //        最大连接数
            config.setMaxTotal(50);
  ​
            //通过配置类创建连接池
            JedisPool pool = new JedisPool(config,"localhost",6379);
            // 在连接池中取出Jedis连接
            Jedis jedis = pool.getResource();
            jedis.set("haha","窗前明月光");
            String haha = jedis.get("haha");
            System.out.println(haha);
  ​
        }

 

6.18.3. 连接池的封装

  • 第一步 :新建一个jedis.properties文件

      host=localhost
      port=6379
      maxIdle=10
      maxTotal=50

     

  • 第二步:编写工具类

      public class JedisUtil {
      ​
          private static JedisPool jedisPool;
      ​
          static {
              InputStream in = JedisUtil.class.getClassLoader().getResourceAsStream("redis.properties");
              Properties properties = new Properties();
              try {
                  properties.load(in);
                  JedisPoolConfig config = new JedisPoolConfig();
                  // 最大空闲数
                  config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")));
                  // 最大连接数
                  config.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal")));
                  jedisPool = new JedisPool(config, properties.getProperty("host"), Integer.parseInt(properties.getProperty("port")));
              } catch (IOException e) {
                  throw new RuntimeException("配置文件加载失败");
              }
      ​
          }
      ​
          /**
           * 这个是获得Jedis
           *
           * @return
           */
          public static Jedis getJedis() {
              return jedisPool.getResource();
          }
      ​
          /**
           * 释放资源
           */
          public static void release(Jedis jedis) {
              //这个表示当前jedis链接 放到我们链接池中  并不是关闭了
              jedis.close();
          }
      ​
      }

     

  • 第三步 测试

      @Test
          public void pool1() {
              Jedis jedis = JedisUtil.getJedis();
              jedis.set("haha", "窗前明月光");
              String haha = jedis.get("haha");
              System.out.println(haha);
              JedisUtil.release(jedis);
          }

     

6.18.4. SpringDataRedis操作

//TODO:等着

6.19. Redis集群

redis的数据存在内存中 但是如果数据量比较多 内存占用很大 那么一台机器 可能无法满足需求

这个时候我们可能要搭建redis集群

6.19.1. 集群的搭建

  • 复制一份配置文件

    Redis

  • 修改复制的配置文件

    Redis

  • 根据不同的配置文件分别启动2次

    Redis

6.19.2. Jedis对集群的操作

      @Test
      public void fun() {
          JedisPoolConfig config = new JedisPoolConfig();
          config.setMaxTotal(50);
          config.setMaxIdle(10);
          JedisShardInfo info1 = new JedisShardInfo("localhost", 6379);
          JedisShardInfo info2 = new JedisShardInfo("localhost", 7777);
          List<JedisShardInfo> list = new ArrayList<>();
          list.add(info1);
          list.add(info2);
          ShardedJedisPool pool = new ShardedJedisPool(config, list);
  ​
          ShardedJedis jedis = pool.getResource();
          for (int i = 0; i <100; i++) {
              jedis.set("name"+i,"huige"+i);
          }
          jedis.close();
      }
  }

6.19.3. SpringDataRedis对集群的操作

//TODO:等着

6.20. Redis可视化工具

6.20.1. 安装

  双击安装

6.20.2. 连接Redis

Redis

 

 

 

上一篇:SSM项目集成Redis


下一篇:常见分布式限流方案