Redis相关知识点

一、NoSQL的四大分类

1.KV键值对

  • Redis(做缓存和日志)

2.文档型数据库(bson格式和json一样)

  • MongDB(一般必须要掌握)
    • MongoDB是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档!
    • MongoDB是一个基于关系型数据库和非关系型数据库的中间产品,MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的
  • ConthDB

3.列存储数据库

  • HBase
  • 分布式文件系统

4.图关系型数据库

  • 不是存图形的,放的是关系,比如:朋友圈社交网络,广告推荐
  • Neo4j,InfoGrid;(社交网络和推荐系统专注于构建关系图谱)

二.Redis入门

1.概念:

Redis是什么?

Redis(Remote Dictionary Server),即远程字典服务。

一次性读可以读100000次,写可以写80000次。

Redis能干嘛?

1.内存存储,持久化,内存是断电即失,所以说持久化很重要(rdb,aof)

2.效率高,可以用于高速缓存

3.发布订阅系统

4.地图信息分析

5.计时器,计数器(浏览量!)

特性:

  • 多样的数据类型
  • 持久化
  • 集群
  • 事务

下载:

http://download.redis.io/releases/

https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100

2、redis-benchmark测试

前提要开启redis服务。

测试:100个并发连接,每个连接100000请求

redis -benchmark -h localhost -c 100 -n 100000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A6puO6YT-1684541589747)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675655106913.png)]

3.基础的知识

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-srE7uYuR-1684541589752)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675731978258.png)]

总共有16个数据库,默认使用的是第0个数据库

可以用select进行切换数据库!

基本的操作命令:

127.0.0.1:6379> select 3 #切换数据库
OK
127.0.0.1:6379[3]> dbsize #查看db大小
(integer) 0
127.0.0.1:6379[3]> set name xiaofeng
get name
keys *
flushdb 删除当前库
flushall 删除所有库

Redis特点:

  • redis是单线程的!!

  • 明白redis是很快的,官方表示,Redis是基于内存操作,CPU不是redis的性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程。

  • Redis是C语言写的,官方提供的数据为100000+的QPS,完全不比同样是使用key-value的Memecache差!

Redis为什么单线程还这么快?

1.误区1:高性能的服务器一定是多线程的?

2.误区2:多线程(CPU上下文会切换!)一定比单线程效率高?

核心:redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率是最高的,多线程(CPU上下文会切换:耗时操作!!!),对于内存系统来说,没有上下文切换,效率是最高的。多次读写都是在CPU上,在内存情况下,这个就是最佳的方案。

4.五大数据类型

Redis-Key

单点登录,过期时间,热点数据-----> 使用expire name 10 过期时间设置

keys *
expire name 10 #设置删除时间
ttl name #查看还是多久的时间删除完
move name 1  #移除key
type name

若有不清楚的命令,就上官网查看。

String(字符串)

set view 0
set key1 v
incr view  #view++   1
decrview  #view--    0
incrby view 10 #view 加10   10
decrby view 10 #view 减10    0
append key1 "hello" # 在原先的值上加上字符串“hello” (vhello) 

##############################
set key1 "hello,kuangshen"
getrange key1 0 3        #"hell"  ==subString方法
getrange key1 0 -1          #"hello,kuangshen"(输出全部)

##############################
set key2 abcdefg
setrange key2 1 XX   #axxdefg  ==replace()方法,替换指定位置的字符串
##############################
setex key3 30 "hello" #设置key3为hello,30秒后过期
setnx mykey "redis" # 如果mykey不存在,创建成功。“redis”
setnx mykey "mongdb" #如果mykey存在,创建失败 “redis"

##############################
mset k1 v1 k2 v2 k3 v3 #设置多个值
msetnx k1 v1 k4 v4 #不能设置k4,原子性操作,要么成功,要么失败(因为k1存在)
##############################
#对象
set user:1 {name:zhangsan,age:3} #设置一个user:1对象,值为json字符来保存一个对象!
mset user:1:name kuangshen user:1:age 22
mget user:1:name user:1:age  #"kuangshen" "22"


##############################
getset #先get后set
127.0.0.1:6379> getset db redis
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongdb
"redis"
127.0.0.1:6379> get db
"mongdb"

数据结构是相同的。

String类似的使用场景:value除了是我们的字符串,还可以是我们的数字

  • 计数器
  • 统计多单元的数量;uid: follow: incr
  • 粉丝数
  • 对象缓存存储

List

在redis中,我们可以把list玩成,栈,队列,阻塞队列!

往list中插入:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RRQtMzbK-1684541589755)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675937545630.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1TOpuQYZ-1684541589759)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675937405157.png)]

双端队列,两端都可以插入
lpush list one
lrange list 0 -1 #获取list中的值
rpush list right #将一个值或者多个值,插入到列表尾部(右)
range list 0 -1 #通过区间获取具体的值

往list中移除:

lpop list #移除list的第一个元素
rpop list #移除list的最后一个元素
lrange list 0 -1
#移除指定的值
取关 UID
lrem list 2 three  #移除list中的两个three值


llen list #获取list中的值得个数

trim修剪

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hc0x85Ip-1684541589765)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675937137595.png)]

rpoplpush # 移除列表的最后一个元素并将它移动到最后一个列表中!(移动)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GA2yp71e-1684541589768)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675937804320.png)]

lset #将列表中指定下标的值替换为另外一个值(更新)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dU9nTYUS-1684541589771)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675938097492.png)]

linsert #将某个具体的value插入到列表中某个元素的前面或者后面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ARcsaNd9-1684541589778)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675938311502.png)]

总结:

  • 它实际上是一个链表,before Node 或者after Node都可以插入值
  • 如果key值不存在,需要创建新的列表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在。
  • 在两边插入或改动值,效率d最高,中间元素,效率会相对低一点。

消息排队!消息队列 Lpush Rpop

Lpush Lpop(栈)

Set(集合)

set中的值不可以重复且无序

向set集合中存值,取值,判断某个值是否在set中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uwmkJbnz-1684541589802)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1675939036008.png)]

sadd myset "hello" #set集合中添加值
smembers myset  #查看指定set集合中所有的值
sismember myset hello #判断某个值是否在set集合中
srem myset "hello" #移除set集合中指定的元素
scard myset # 获取set元素中内容元素个数
sdiff myset myset1 #获取myset和myset1中的差集
sinter myset myset1 #获取myset和myset1中的交集
sunion myset myset1 #获取myset和myset1中的并集

Hash(哈希)

Map集合,key-value

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mmj06x6m-1684541589805)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1676882996376.png)]

hset
hget 
hmset  
hmget 
hmgetall 
hdel

5.通过Jedis操作redis

SpringBoot 2.4.5版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

插件的添加

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.4.5</version>
        </plugin>
    </plugins>
</build>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>jedis_demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jedis_demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.5</version>
            </plugin>
        </plugins>
    </build>

</project>

编写测试类,连接本地redis数据库,实现相应的操作。

package com.itheima.test;

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

import java.util.Set;

/**
 * 使用Jedis操作Redis
 */
public class JedisTest {

    @Test
    public void testRedis(){
        //获取连接
        Jedis jedis = new Jedis("localhost",6379);
        //执行其他的操作
        jedis.set("username","xiaomeng");
        String value = jedis.get("username");
        System.out.println(value);
//        jedis.del("username");
        jedis.hset("myhash","addr","bj");
        String hget = jedis.hget("myhash", "addr");
        System.out.println(hget);
        Set<String> keys = jedis.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }
        //关闭连接
        jedis.close();
    }

}

6.通过SpringDataRedis操作redis

SpringBoot 2.4.5版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

插件的添加

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.4.5</version>
        </plugin>
    </plugins>
</build>

6.1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>springdataredis_demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springdataredis_demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>
        </plugins>
    </build>

</project>

6.2、application.yml

spring:
  application:
    name: springdataredis_demo
    #redis相关配置
  redis:
    host: localhost
    port: 6379
    #password:123456
    database: 0 #操作的是0号数据库
    jedis:
      #redis连接池配置
      pool:
        max-active: 8 #最大连接数
        max-wait: 1ms #连接池最大阻塞连接时间
        max-idle: 4 #连接池中的最大空闲连接
        min-idle: 0 #连接池中的最小空闲连接



6.3、编写测试单元

package com.itheima;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner;

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

@SpringBootTest
@RunWith(SpringRunner.class)
class SpringdataredisDemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 操作Sting类型数据
     */
    @Test
    public void testString(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("city","beijing");
        String value = (String)redisTemplate.opsForValue().get("city");
        System.out.println(value);

        redisTemplate.opsForValue().set("key1","value1",10l, TimeUnit.SECONDS);
        System.out.println(redisTemplate.opsForValue().setIfAbsent("city", "nanjing"));
    }

    /**
     * 操作hash类型数据
     */
    @Test
    public void testHash(){
        HashOperations hashOperations = redisTemplate.opsForHash();
        //存值
        hashOperations.put("001","name","xiaoming");
        hashOperations.put("001","age","29");
        hashOperations.put("001","address","nanjing");
        //取值
        String  name = (String) hashOperations.get("001", "name");
        System.out.println(name);
        //获取hash结构中的所有字段
        Set<String> keys = hashOperations.keys("001");//hashMap中的getKeys()方法相似
        for (String key : keys) {
            System.out.println(key);
        }
        //获取hash结构中的所有值
        List<String> values = hashOperations.values("001");//hashMap中的getValues()方法相似
        for (String value : values) {
            System.out.println(value);
        }
    }

    /**
     * 操作list类型的数据(有序,可重复)
     */
    @Test
    public void testlist(){
        ListOperations listOperations = redisTemplate.opsForList();

        //存值
        listOperations.leftPush("mylist","a");
        listOperations.leftPushAll("mylist","b","c","d");
        //取值
        List<String> mylist = listOperations.range("mylist", 0, -1);
        for (String value : mylist) {
            System.out.println(value);
        }

        //获取队列长度llen
        Long size = listOperations.size("mylist");
        int iSize = size.intValue();
        for (int i = 0; i < iSize; i++) {
            //出队列
            String element = (String) listOperations.rightPop("mylist");
            System.out.println(element);
        }
    }

    /**
     * 操作Set类型数据(无序,无重复元素)
     */
    @Test
    public void testSet(){
        SetOperations setOperations = redisTemplate.opsForSet();

        //存值
        setOperations.add("myset","a","b","c","a");
        //取值
        Set<String> myset = setOperations.members("myset");
        for (String s : myset) {
            System.out.println(s);
        }

        //删除成员
        setOperations.remove("myset","a","b");
        //取值
        myset = setOperations.members("myset");
        for (String s : myset) {
            System.out.println(s);
        }
    }

    /**
     * 操作ZSet类型数据(有序无重复元素)排序规则:从小到大
     */

    @Test
    public void testZSet(){
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        //存值
        zSetOperations.add("myZSet","a",10.0);
        zSetOperations.add("myZSet","b",12.0);
        zSetOperations.add("myZSet","d",13.0);
        zSetOperations.add("myZSet","a",14.0);
        //取值
        Set<String> myZSet = zSetOperations.range("myZSet", 0, -1);
        for (String s : myZSet) {
            System.out.println(s);
        }
        //修改分数
        zSetOperations.incrementScore("myZSet","b",20.0);
        //取值
        myZSet = zSetOperations.range("myZSet", 0, -1);
        for (String s : myZSet) {
            System.out.println(s);
        }

        //删除成员
        zSetOperations.remove("myZSet","a","b");

        //取值
        myZSet = zSetOperations.range("myZSet", 0, -1);
        for (String s : myZSet) {
            System.out.println(s);
        }
    }
    
    
    /**
     * 通用操作,针对不同的数据类型都可以操作
     */
    @Test
    public void testCommon(){
        //获取redis中所有的key
        Set<String> keys = redisTemplate.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }

        //判断某个key是存在
        Boolean itcast = redisTemplate.hasKey("itcast");
        System.out.println(itcast);
        //删除指定的key
        redisTemplate.delete("myZSet");
        //获取指定key对应的value的数据类型
        DataType dataType = redisTemplate.type("myset");
        System.out.println(dataType);
    }
}

7.缓存穿透(查不到)

用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败,当用户很多的时候,缓存都没有命中(秒杀系统!)于是都去请求了持久层数据库,这会给持久层数据库造成很大的压力,就相当于出现了缓存穿透。

解决办法:

布隆过滤器

缓存空对象

8.缓存击穿(量太大,缓存过期!)

是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在过期的瞬间,有大量的请求并发访问,这个数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大。

解决办法:

热点数据不过期

加分布式锁

9.缓存雪崩

指在某一个时间段,缓存集中过期失效,redis宕机。

三.三级缓存定义

intln(key);
}

    //判断某个key是存在
    Boolean itcast = redisTemplate.hasKey("itcast");
    System.out.println(itcast);
    //删除指定的key
    redisTemplate.delete("myZSet");
    //获取指定key对应的value的数据类型
    DataType dataType = redisTemplate.type("myset");
    System.out.println(dataType);
}

}


## 7.缓存穿透(查不到)

用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败,当用户很多的时候,缓存都没有命中(秒杀系统!)于是都去请求了持久层数据库,这会给持久层数据库造成很大的压力,就相当于出现了缓存穿透。

解决办法:

布隆过滤器

缓存空对象

## 8.缓存击穿(量太大,缓存过期!)

是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在过期的瞬间,有大量的请求并发访问,这个数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大。

解决办法:

热点数据不过期

加分布式锁

## 9.缓存雪崩

指在某一个时间段,缓存集中过期失效,redis宕机。



# 三.三级缓存定义

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0Rv4sJs-1684541589812)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1679795535806.png)]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值