五、Redis数据库及Java操作

一、NoSQL概念

1、数据库分类

关系型数据库:MySQL、Oracle、SqlServer、DB2
非关系型数据库(NoSQL):Redis、MongoDB

2、NoSQL与SQL差异

  1. 结构上的差异:
    关系型数据库是严格结构化的:存入的数据都有固定格式(数据类型、约束等等)
    非关系型数据库没有非常严格的结构:存入的数据有键值型、文档型(一行一个json数据)、图类型(存入数据看作节点)
  2. 关联上的差异
    关系型数据库可能有表之间的主外键关联,不能随便删除
    非关系型数据库则没有关联,一般是通过json数据的嵌套全部存储了
  3. 关系型数据库操作数据采用SQL语言;非关系型没有SQL语言,固定命令,缺点不同库的命令不同,要学习
  4. 关系型满足事务四大特性的;非关系型不能全部满足事务四大特性
  5. 关系型基本都是磁盘存储数据;非关系型大都是内存存储数据

3、什么时候用哪个?

如果数据结构相对固定,将来不怎么变更,对安全性,性能要求较高就使用关系型数据库;
再结合使用非关系型数据库,将表中冗余的其他表字段属性存在非关系型数据库。
比如订单主表数据存在关系型数据库,多个订单商品详细表存在Redis


二、Redis介绍

Redis是基于内存的键值型NoSQL数据库,里面存的都是键值对

1、特征

  1. 键值型:value支持多种数据结构,key是字符串
  2. 单线程:每个命令具有原子性,执行时不会有其他命令插进来,安全;Redis6的多线程仅仅是对于网络请求处理,而不是命令
  3. 低延迟,速度快(因为基于内存)
  4. 支持数据持久化,定期将数据从内存持久化到磁盘
  5. 支持主从集群(从节点可以备份主节点的数据),分片集群(提高存储上限)

2、支持的数据结构

key就是string,value支持多种数据结构,常见的有以下五种

  1. string
  2. hash:哈希表用字符串的形式描述——{name : "张三", age : 23}
  3. list:有序的集合,本质是链表——[ A<->B<->C<->D ]
  4. set:无序的集合{A, B, C}
  5. SortedSet:{A : 1, B : 2, C : 3}

三、通用命令

在Redis的命令行(redis-cli)输入:help @generic追乃瑞可,查询所有基础通用命令
help 命令名称:就可以查看该命令的用法

# 连接到 Redis 服务器
redis-cli

# 查看符合模板的键,生产环境不建议使用,数据量大,查询慢占用服务器资源
keys pattern

# 删除键 可以删多个,后面的如果不存在也不会报错,会将前面存在的删掉返回删除的数量
DEL key1, key2, key3...

# 检查键是否存在
EXISTS key

# 给key设置一个有效期,到期自动删掉这个key(单位:秒)
EXPIRE key 60

# 查看key的剩余有效期,单位秒
TTL key

四、不同类型的常用命令

1、string

# 设置字符串
SET key "value"
# 设置多个
MSET

# 获取字符串
GET key
# 获取多个
MGET

# 递增1
INCR counter
# 递增num
INCRBY counter num

# 递减数值
DECR counter
DECRBY counter num

# 先判断,如果不存在,则添加字符串
SETNX key "value"
# 添加键值对,并指定有效期
SETEX key 60 "value"

2、hash

  1. hash类型,也叫散列,是一个无序字典,是field-value形式(就是键值对),就不需要用json格式了
  2. 命令语法:所有命令前加H
    HSET key field "value"
    HGET key field

3、list

  1. 类似与LinkedList,可以看作双向链表。可以正向检索,也可以反向检索
  2. 有序,可重复,插入删除快,查询慢;用于存放有序的数据集合

3.1 常见命令

# 从左侧推入元素
LPUSH key "value1"...
# 弹出左侧第一个元素
LPOP key

# 从右侧推入元素
RPUSH key "value2"...
# 弹出右侧第一个元素
RPOP key

# 获取列表范围内元素
LRANGE key start end

3.2 用list结构模拟栈、队列、阻塞队列

模拟栈:先进后出,入口和出口在同一边。用LPUSH存,LPOP取
模拟队列:先进先出,入口出口不在同一边。用LPUSH存,RPOP取

4、set

  1. 与HashSet特征类似,无序、元素不重复、查找快
# 添加元素到集合
SADD key "value1"

# 获取集合所有元素
SMEMBERS key

# 移除集合中的元素
SREM key "value1"

# 检查元素是否在集合中
SISMEMBER key "value1"

# 返回集合中的元素个数
SCARD key

5、SortedSet有序set集合

  1. 类似于TreeSet,可排序,不重复,查询快
  2. 按照评分(scope)排序,scope是数字
# 添加元素到有序集合
ZADD key scope "value1"
ZADD key scope "value2"

# 获取有序集合范围内的元素
ZRANGE key start end

# 获取元素的评分
ZSCORE key "value1"

# 移除有序集合中的元素
ZREM key "value1"

五、key的层级格式

如何区分不同的key,key是唯一的,但是redis没有table的字段概念,如何区分不同类型的key呢?
比如用户和商品的id都是1。
解决:redis的key允许多个单词拼接形成层级结构,比如user:idproduct:id
如果value是一个Java对象,将其序列化为json字符串存储
按照层级格式自动分隔开


六、Java操作Redis

1、操作Redis的客户端库

用于操作Redis的客户端库有两种:Jedis、lettuce(来特斯)

  1. Jedis以命令作为方法名称,简单实用,但是线程不安全
  2. lettuce实现了同步,是线程安全的
  3. SpringData整合了Jedis和lettuce

2、Jedis

2.1 引入依赖

<dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.7.0</version>
</dependency>

2.2 建立连接

  1. 获取Jedis的对象:传入ip地址和端口号。端口默认是6379
  2. 设置密码:如果没设置密码,就不要写这一步
  3. 选择库:Redis默认提供了16个库,从0-15,选择一个进行操作

2.3 使用

使用比较灵活,比如可以用来做购物车,以redis做中间件存储数据,在不同的访问请求中共享数据;比如在购物车中商品数量变化的不同控制方法中给库里增删数据。
jdeis对象调用的方法都是命令的名字

2.4 释放资源

2.5 示例

2.5.1 存入数据
	public static void main(String[] args) {
    
    
        /**
         * 1、建立连接
         */
        //获取对象
        Jedis jedis = new Jedis("127.0.0.1", 6379);;
        /**设置密码,没设置密码就可以不写
         jedis.auth("123456");
         */
        //选择库
        jedis.select(0);
        /**
         * 2、使用
         */
        //存入数据
        String res = jedis.set("name", "zhangsan");//返回值是存入是否成功
        System.out.println(res); //ok
        /**
         * 3、关流
         */
        if (jedis!=null){
    
    
            jedis.close();
        }
    }
2.5.2 取出数据
    public static void main(String[] args) {
    
    
        /**
         * 1、建立连接
         */
        //获取对象
        Jedis jedis = new Jedis("127.0.0.1", 6379);;
        /**设置密码,没设置密码就可以不写
         jedis.auth("123456");
         */
        //选择库
        jedis.select(0);
        /**
         * 2、使用
         */
        //拿出数据
        String value = jedis.get("name");
        System.out.println("拿出来了"+value);
        /**
         * 3、关流
         */
        if (jedis!=null){
    
    
            jedis.close();
        }
    }

3、Jedis连接池

Jedis本身线程不安全,频繁创建和销毁也会损耗性能,因此使用Jedis连接池代替原始使用

3.1 创建JedisPoolConfig对象

设置连接池参数,最大连接数,最大空闲数,最大等待时间等等

3.2 创建JedisPool对象

3.3 getResource()获取连接

3.4 使用示例

    public static void main(String[] args) {
    
    
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(8);//最大连接数
        config.setMaxIdle(8);//最大空闲连接
        config.setMaxWaitMillis(100);//最大等待时间
        config.setMinIdle(0);//最小空闲连接。超过最大空闲时间,就关闭地剩下几个
        JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379, 1000);

        Jedis jedis = jedisPool.getResource();
        jedis.select(0);
        jedis.set("name", "zhangsan");
        if (jedis!=null){
    
    
            jedis.close();//这里是将连接归还给连接池,而不是销毁
        }
    }

七、SpringDataRedis

1、优点

SpringData集成了Jedis和Lettuce。主要的提升有

  1. 提供了RedisTemplate统一的API来操作Redis,模板对象封装了这些方法获取对象:opsForValue()、opsForHash()、opsForList()、opsForSet()、opsForZSet()
    返回的对象都是ValueOperations、HashOperations…;封装了对Redis的操作
  2. 支持JSON、Java对象的序列化和反序列化(java对象和redis数据相互转换)
  3. 实现了控制反转思想,解耦。不用我们创建Jedis或者JedisPool的对象

2、使用步骤

2.1 创建项目勾选依赖

创建项目

2.2 引入pool的依赖

<dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
</dependency>

2.3 编写配置文件

包括redis的ip和端口;使用的连接池配置

spring.redis.host=127.0.0.1
spring.redis.port=6379

spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-wait=-1
# spring.redis.jedis~         是jedis的连接池
# spring.redis.lettuce.pool~  是lettuce的连接池

2.4 JSON序列化工具

redisTemplate默认使用jdk序列化器,以二进制存到了数据库,key与value就不好取了,乱码,可读性差

2.4.1 配置类设置
@Configuration
public class RedisConfig {
    
    

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
    
    
        //1、创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //2、设置连接工厂
        template.setConnectionFactory(connectionFactory);
        //3、创建JSON的序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //4、设置Key的序列化工具
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //5、设置Value的序列化工具
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        return template;
    }
}
2.4.2 使用

使用

2.4.3 json序列化工具的坏处

如图直接可以为我们序列化反序列化java对象,因为json序列化工具自动为我们的redis数据库加了实体类的全类名,内存占用大
redis数据
所以我们要使用String类型序列化工具

2.5 使用StringRedisTemplate模板

使用springdata提供的redis模板,实现了通过string序列化,还不需要我们写配置类,但是要我们自己将Java对象转为json字符串
StringRedisTemplate示例
如下图,这样就没有class了
redis数据库的数据

猜你喜欢

转载自blog.csdn.net/sjdnnd/article/details/141308091