Java高级 redis

目录

        一、NOSQL

        二、NOSQL和 RDBMS 区别

        三、常用的NOSQL产品

        四、概述redis

         五、redis的优点

        六、redis应用场景

        七、安装redis

        八、redis的客户端软件

        8.1 设置后台启动

        8.2 修改端口号

        8.3 设置redis服务允许远程连接

        九、Redis中常用的命令

        9.1 redis操作key的命令

        9.2 操作redis的数据库

        9.3 redis支持的数据类型以及命令

        9.3.1 字符串类型

        9.3.2 hash类型

        9.3.3 list队列类型

        9.3.4 Set集合类型

        9.3.5 sorted set集合类型

        十、Redis的持久化

        10.1 : redis的持久化方式

        10.2 : RDB持久化方式

       10.3: AOF持久化方式

        十一、redis的应用场景     

        十二、redis的集群模式

        12.1 : redis的主从模式

        12.2 :redis的哨兵模式

        12.3 redis集群模式

        测试集群环境  

        十三、java连接redis服务

        13.1 引入依赖

        13.2 测试Key的API方法

        13.3 测试字符串类型的api方法         

        13.4 测试hash类型的api方法

        13.5 jedis提高了连接池

        十四、springboot整合redis

        【1】StringRedisTemplate

        [2]RedisTemplate  


        一、NOSQL

                NOSQL [Not only SQL]不仅仅是sql. 指的是非关系型数据库。

        二、NOSQL和 RDBMS 区别

        RDBMS
- 高度组织化结构化数据。 表--结构【列[数据类型] 列[数据类型] ....】
- 结构化查询语言(SQL) sql数据
- 数据和关系都存储在单独的表中。【class  student】
- 数据操纵语言DML,数据定义语言DDL  DML DDL DQL
- 严格的一致性. 事务.---JDBC 事务。
- 基于事务
         NoSQL
- 代表着不仅仅是SQL
- 没有声明性查询语言。 DQL
- 键 - 值对存储。 key value. 底层就是map  
- 非结构化和不可预知的数据  字符串  对象  队列  集合
- 高性能,高可用性和可伸缩性。 适合搭建集群。
- 大多数NOSQL都是基于内存运算。

        三、常用的NOSQL产品

                Redis--基于KEY-VALUE模式

                mongodb:--基于文档存储。而且它的语法和关系型数据库很相似。【掌握】

        四、概述redis

        

被数百万开发人员用作数据库、缓存、流引擎和消息代理的开源内存数据存储。

Redis是一种开放源代码(BSD许可)的内存中数据结构存储,用作数据库,缓存和消息代理。Redis提供数据结构,例如字符串,哈希,列表,集合,带范围查询的排序集合,位图,超日志,地理空间索引和流。Redis具有内置的复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供了高可用性。

         五、redis的优点

                5.0的版本--

        1.Redis读取的速度是110000次/s,写的速度是81000次/s
        2.原子 。Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
        3.支持多种数据结构:string(字符串);list(列表);hash(哈希),set(集合);zset(有序集合)
        4.持久化--磁盘,主从复制(集群)
        5.官方不支持window系统,但是又第三方版本。 linux系统。---有人搞了window的版本4.的版本

        六、redis应用场景

                实时数据存储

                缓存和会话存储-------划重点

                重点流媒体和消息传递

        七、安装redis

        

                下载redis 并且解压

        进入redis解压目录

        make 编译命令

        make install 安装命令

        开启redis服务器

        redis-server redis的配置文件 # 按照配置文件启动redis服务器。  

       

        客户端连接redis服务

 

        如果想连接其他redis服务

        redis-cli -h ip地址 -p 端口号

        八、redis的客户端软件

        

                这两款redis客户端软件  安装其一即可                要想使用该软件必须redis开启

                        默认redis服务器开启时独立占用了一个窗口    所以我们再开一个

        8.1 设置后台启动

                我们在这里设立redis后台自动启动,编辑redis   在259行修改

        8.2 修改端口号

                        默认为6379 

        8.3 设置redis服务允许远程连接

                安装客户端软件 并能够连接到redis服务端。 设置redis后台启动  

        九、Redis中常用的命令

                redis存储数据的模式: key value模式

        9.1 redis操作key的命令

                set k1 v1 往redis中存储字符串元素。

        1.keys * : 查看redis中所有的key.
        2.del key key...: 删除指定的key
        3.exists key: 判断指定的key是否存在 存在返回大于0  不存在返回0
        4.expire key seconds: 为指定的key设置过期时间。单位为秒
        5.ttl key: 查看key的过期时间剩余多少。返回-2表示key不存在  返回-1永久不过期

        9.2 操作redis的数据库

                redis默认帮你创建了16库。

        select n: 选择指定的库。
        flushdb: 清空当前所在的库内容
        flushall: 清空所有的库内容 

        9.3 redis支持的数据类型以及命令

我们主要学习的是前五种。String字符串类型 Lists队列类型 Sets集合类型 Hash哈希类型         Sorted sets有序集合。 其他类型建议有时间看看论坛

        上面所说的类型是指value的数据类型。redis的key永远都是string类型

redis命令手册

Redis 命令参考 — Redis 命令参考

        9.3.1 字符串类型

        value类型为字符串类型, 字符串是最基本的 Redis 数据类型。它们通常用于缓存

        关于操作redis字符串的命令:

                set key value: 存储字符串数据
                set key value ex seconds: 存储key时为其设置过期时间。
                get key: 获取指定key的字符串内容。
                getex key EX seconds: 获取key的值并设置过期时间: 登录时。
                setnx key value: 如果指定的key存在,则不存储,如果不存在则存储。
                incr key: 为指定的key进行递增---点赞 收藏数
                decr key: 为指定的key进行递减--取消收藏 取消点赞

        9.3.2 hash类型

                hash类型: redis中的value为hash类型。 hash类型的结构是field-value字段

                        hset key field value [field value field value....]: 存储hash数据
                        hget key field: 获取指定key对应的field的值。
                        hkeys key: 返回哈希表 key 中的所有field
                        hvals key: 返回哈希表 key 中所有field的值
                        hgetall key: 返回哈希表 key 中,所有的域和值。

        9.3.3 list队列类型

                redis中value值为list对象类型

                        1. lpush key value......:  从左边存储队列类型
                        2. lpop key: 移除并返回列表 key 的头元素。
                        3. LRANGE 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定

        9.3.4 Set集合类型

                它和我们上面讲解的list类型比较相似,但是它是无序而且不允许重复

        sadd key value value...: 添加set集合元素。

        sismember key member: 判断 member 元素是否集合 key 的成员。

        SPOP key: 随机从集合中获取一个元素并移除该元素

        smembers key: 获取集合中所有的元素

        sunion key1 key2: 获取指定key1和key2集合的并集

        sinter key1 key2: 获取指定key1和key2集合的交集

        9.3.5 sorted set集合类型

                与上面的类型比较相似,它的特点也是无序,不可重复,但是它允许带分数。用于排行榜

        zadd key values score value score value score....往redis中添加有序集合元素。

        zrange key start end: 获取指定key中指定范围的元素按照从低到高。

        zrevrange key start end: 获取指定key中指定范围的元素按照从高到低。

        十、Redis的持久化

        什么是持久化?

                        把内存中的数据保存到磁盘获取网盘上,这个过程就是持久化。

        redis持久化?

                        redis的运算都是基于内存执行的,但是为了包装数据不丢失,可以把数据保存到磁盘中。

                        当redis启动时,从磁盘中把数据在读取到内存中参与运算。

        10.1 : redis的持久化方式

    redis持久化方式有两种:

        (1)RDB:快照模式

        (2)AOF: 文件追加模式

        10.2 : RDB持久化方式

                其实就是把数据以快照的形式保存在磁盘上,什么是快照呢,你可以理解成把当前时刻的数据拍成一张照片保存下来。

                        默认保存在dump.rdb文件中

        RDB的触发机制有哪些?

                第一种:手动触发

                第二种:自动触发

        手动触发的方式也有两种:1.save命令         2.bgsave命令

        

        Save命令和bgsave命令的区别:

                Sava:该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下   

            

        执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取

        bgsave:执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应其他客户端请求。具体流程如下

         

        上面这两种方式都是需要客户手动触发。而实际我们应该让redis自动触发。

        

        如何自动触发:只需要修改reids的配置就可以了

        

        从上面的演示我们就可以知道RDB持久化的优缺点

                优点:

                持久化速度比较快,而且数据恢复也比较快

                缺点:

                由于是某个时间断触发RDB,这样会导致丢失一个时间断的数据。数据完整性比较差。

       10.3: AOF持久化方式

                AOF:日志追加 记录服务器接受的每个写入操作,当服务器启动时再次加载该日志,会把日志中的命令重新执行一遍。

                该模式默认不启动,而且这个日志文件的名字appendonly.aof

                

 

        优点:数据完整性比较高。最多丢失一条命令。

        缺点:随着写操作越来越大,日志文件也越来越大。数据恢复非常慢。

        十一、redis的应用场景     

        1.热点数据的缓存: 减少对数据库的访问频率和减轻数据库的压力。

        2.限时业务的运用: 秒杀 存储登录者用户信息 存储短信验证码. 可以设置key的过期时间

        3.计数器相关问题: 点赞数 收藏数 播放量 incr decr.

        4.update 表名 set num=num+1 where id=?

        5.排行榜相关问题: sort set

        6.分布式锁:         

        十二、redis的集群模式

               作用: 为了解决redis单点故障。提高redis的可用性

        12.1 : redis的主从模式

       如何搭建redis的主从模式: 配从不配主。

一主两从: 三台服务器【这个三台之间可以相互访问】。 我这里为了操作方便,就在一台服务器启动三个redis服务。 只需要修改端口号即可

创建三个redis配置文件

        1. 修改端口号
        2. 修改rdb文件的名称。
        3. 修改aof的文件名 

        启动上面三个redis服务--根据上面的配置

                客户端连接到redis三台服务器  

        redis-cli -p 端口号

         配置三者之间的主从关系:  6380为主节点  6381和6382为从节点。 配从不配主

        我们在客户端输入info replication 可以查看每台redis服务器的主从关系  

                从上面的命令可以查看到三台redis服务器之间没有任何主从关系。

                我们可以使用 slaveof 主节点ip 主节点port

        主节点写入的数据会同步到所有从节点  

        从节点只能负责读操作,不能负责写操作  

        思考:

1.如果新加入了一个从节点,那么该从节点会不会把主节点之前的数据同步?                

2.如果主节点挂掉,从节点会不会上位?                 不会

        12.2 :redis的哨兵模式

                我们从上面的主从模式 我们知道该模式,如果主节点宕机后,需要人为的选举主节点。 从节点不会主动变成主节点。 哨兵模式 会在剩下的从节点中选举一个作为主节点。

                修改哨兵的配置文件 并启动哨兵服务。  

        启动哨兵服务  

                演示主节点宕机

         

                思考: 原来的主节点恢复了,是否可以当老大            不可以

        12.3 redis集群模式

                从上面的两种模式 我们知道它只有一个主节点,如果后期写操作也比较多,势必会操作主节点压力比较大。而且上面主节点要把数据同步到所有从节点。所以出现了多主多从模式

        搭建一个三主三从的redis集群。7001~7006  

        

        端口号

        rdb文件名

        aof文件名[必须开启aof模式]

        开启集群模式。

        启动上面6台redis服务 

        

        分配槽以及主从关系  

        redis-cli --cluster create --cluster-replicas 1 192.168.223.158:7001 192.168.223.158:7002  192.168.223.158:7003  192.168.223.158:7004 192.168.223.158:7005  192.168.223.158:7006

        测试集群环境  

        

        十三、java连接redis服务

                

        redis提高很多语言的api接口。这些语言都可以操作redis服务器。 redis提高了对Java语言操作的接口的jar,它就是jedis. 这jar中封装了一个Jedis类,该类中包含了所有对redis操作的方法

        13.1 引入依赖

<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.6.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

        13.2 测试Key的API方法

 //对应redis中key的操作接口
    @Test
    public void test02(){
        Jedis jedis=new Jedis("192.168.223.158",6379);
        //获取所有的key
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);

        //删除指定的key
        Long c = jedis.del("k1","k2","k5");
        System.out.println("删除key的个数:"+c);

        //判断指定的key是否存在
        Boolean exists = jedis.exists("k2");
        System.out.println("判断key是否存在:"+exists);

    }

        13.3 测试字符串类型的api方法         

 //对应字符串操作的方法
    @Test
    public void test03(){
        Jedis jedis=new Jedis("192.168.223.158",6379);
        //存放字符串数据
        jedis.set("k1","1");
        jedis.set("k2","v2");

        //获取指定key的内容
        String value1 = jedis.get("k1");
        System.out.println("k1对应的内容:"+value1);

        //如果指定的key存在则不存入,不存在则存入redis
        Long aLong = jedis.setnx("k8", "ldh");
        System.out.println("是否存入:"+aLong);

        //存入时设置过期时间
        String str = jedis.setex("k4", 30l, "v4");
        System.out.println("存入的内容:"+str);

        //用于点赞和收藏
        Long incr = jedis.incr("k1");
        System.out.println("递增后的结果:"+incr);


    }

        13.4 测试hash类型的api方法

//对应hash类型的操作----可以存放对象。
    @Test
    public void test04(){
        Jedis jedis=new Jedis("192.168.223.158",6379);
        Map<String,String> map=new HashMap();
        map.put("name","刘德华");
        map.put("age","18");
        map.put("sex","男");
        Long k1 = jedis.hset("k1", map);


        String name = jedis.hget("k1", "name");
        System.out.println("获取hash中name对应的值:"+name);


        Map<String, String> map1 = jedis.hgetAll("k1");
        System.out.println("获取指定key对应的内容:"+map1);

        Set<String> k11 = jedis.hkeys("k1");
        System.out.println("获取k1对应的所有field:"+k11);

        List<String> values = jedis.hvals("k1");
        System.out.println("获取k1对应的所有field的值:"+values);
    }

        13.5 jedis提高了连接池

        为了减少频繁的创建和销毁jedis对象,提高了jedis的连接池,以提高连接效率。

                JedisPool

import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class Test02 {

    @Test
    public void test01(){
        //创建连接池的配置类
        JedisPoolConfig config=new JedisPoolConfig();
        config.setMinIdle(5); //设置空闲的个数
        config.setMaxIdle(10);
        config.setMaxTotal(2000); //设置最多的数量
        config.setMaxWaitMillis(6000);//设置最大的等待时长
        config.setTestOnBorrow(true); //是否检验池子中的jedis对象可用
        //创建jedis连接池对象.
        JedisPool jedisPool = new JedisPool(config,"192.168.223.158",6379);

        //获取jedis对象---从池子中获取。
        Long start = System.currentTimeMillis();
        for(int i=0;i<10000;i++) {
            Jedis jedis = jedisPool.getResource();
            String ping = jedis.ping();

            jedis.close();

        }
        Long end = System.currentTimeMillis();
        System.out.println("耗时:"+(end-start));
    }
}

        十四、springboot整合redis

        

        (2) 配置application配置文件

#指定redis服务的地址和端口号哦
spring.redis.host=192.168.223.158
spring.redis.port=6379
# 最大的活跃数
spring.redis.jedis.pool.max-active=10
spring.redis.jedis.pool.max-wait=5000
spring.redis.jedis.pool.max-idle=5

        (3)在springboot中封装了两个类,RedisTemplate和StringRedisTemplate. 而这两个类也被redis自动装配类加载spring容器中管理,所以我们可以直接在代码中注入这两个类对象 

        【1】StringRedisTemplate

package com.ykq.qy158springbootredis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class Qy158SpringbootRedisApplicationTests {

    //该类中封装了很多api方法--redis服务
    @Autowired
    private StringRedisTemplate redisTemplate;

    //关于key操作的方法。
    @Test
    void contextLoads() {
            //删除指定的key
        Boolean aBoolean = redisTemplate.delete("k1");
        System.out.println("是否删除成功:"+aBoolean);

        //判断指定的key是否存在
        Boolean hasKey = redisTemplate.hasKey("k1");
        System.out.println("判断指定的key是否存在:"+hasKey);
    }

    //关于对字符串的操作。
    //在redisTemplate类中,对于每种数据类型,都封装了相应的类对象,得到相应的类对象,即可对相应的数据类型操作。
    @Test
    public void test02(){
        //获取对String类型操作的类对象。
        ValueOperations<String, String> forValue = redisTemplate.opsForValue();
        //使用上面的类对象即可对String类型操作
        forValue.set("k1","张三爱吃水果");
        forValue.set("k4","10");
        forValue.set("k2","李四爱吃榴莲",15, TimeUnit.MINUTES);

        //如果存在,则不存入,不存在则存入
        Boolean aBoolean = forValue.setIfAbsent("k3", "王五爱吃米饭", 25, TimeUnit.SECONDS);
        System.out.println("是否存入成功:"+aBoolean);

        //获取对于的值
        String value1 = forValue.get("k1");
        System.out.println("获取k1对于的数据:"+value1);

        Long aLong = forValue.increment("k4");
        System.out.println("递增后的结果:"+aLong);
    }

    //关于对Hash类型的操作
    @Test
    public void test03(){
        HashOperations<String, Object, Object> forHash = redisTemplate.opsForHash();

        forHash.put("k1","name","刘德华");
        forHash.put("k1","age","18");
        forHash.put("k1","address","香港");

        Map<String,String> map=new HashMap<>();
        map.put("name","张学友");
        map.put("age","25");
        map.put("address","北京");
        forHash.putAll("k2",map);

        Object o = forHash.get("k1", "name");
        System.out.println("获取指定key对于的name的值:"+o);

        Map<Object, Object> k2 = forHash.entries("k2");
        System.out.println("获取k2对于的map对象:"+k2);

        Set<Object> keys = forHash.keys("k2");
        System.out.println("获取k2对于的所以field:"+keys);

        List<Object> values = forHash.values("k2");
        System.out.println("获取k2对于的所有filed的值:"+values);
    }
}

        [2]RedisTemplate  

        该类型其实是StringRedisTemplate的父类

                        public class StringRedisTemplate extends RedisTemplate<String, String> {

        我们知道StringRedisTemplate它存储的key和value field必须都是String类型,不能存放对象类型。 而RedisTemplate的key和value可以自己指定数据类型,所有它的key和value可以是任意类型  

                        public class RedisTemplate<K, V>

        

@Test
    public void test01(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("k1",new Student(1,"张三","男"));
    }

                表示: 存入的对象需要序列化。 默认使用的是JDK序列化。必须要求你的类实现序列化接口。  

        解决办法:

package com.ykq.qy158springbootredis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class Qy158SpringbootRedisApplicationTests02 {

    //该类中封装了很多api方法--redis服务
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test01(){
        //默认RedisTemplate它的key和value的序列化都是使用的JdkSerializationRedisSerializer方式,该序列化要求类必须实现Serializable接口。

        //我们在实际开发中,我们的key都是String类型,我们应该指定String序列化方式
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("k1",new Student(1,"张三","男"));
        System.out.println(valueOperations.get("k1"));
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值