Redis

一、Redis介绍

1.1 引言

  1. 由于用户量增大,请求数量也随之增大,数据压力过大。
  2. 多台服务器之间,数据不同步。
  3. 多台服务器之间的锁,已经不存在互斥性了。

在这里插入图片描述

1.2 NoSQL

Redis就是一个NoSQL

NoSQL->非关系型数据库

​ 1.key -value :Redis

​ 2.文档型: ElaticSearch,Solr,Mongodb

​ 3.面向列:Hbase,Cassandra

​ 4.图形化:Neo4j

除了关系型数据库就是菲关系型数据库

NoSQL只是一种概念

1.4 介绍

有一位意大利人,在开发一款LL00GG的统计页面,因为MySQL的性能不好,Salvatore自己研发了-款非关系型数据库,并命名为Redis。
Redis (Remote Dictionary Server)即远程字典服务,Redis是由C语言去编写:基于Key-value,而且

Redis是基于内存存储数据,Redis提供了多种持久化机制,性能可以达到110000/s读取,81000/s写入数据。Redis提供了主从,哨兵以及集群的搭建方式,更加方便的横向扩展以及垂直扩展

2.1 安装Redis

version: '3.1'
services:
  redis:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 6379:6379

进入redis容器

​ docker exec -it id bash

执行redis-cli进入

2.3 使用图形化界面连接Redis

在github上下载redis–manager

三、redis常用命令

3.1 Redis存储数据的结构

  • key:string :一个key对应一个值

  • key-hash:一个key对应一个Map

  • key-list:一个key对应一个列表

  • key-set:一个key对应一个集合

  • key-zset:一个key对应一个有序集合

    另外三种

    HyperLogLog:计算近似值的

    GEO:地理位置

    BIT:一般存储的也是一个字符串,存储的是一个byte[]
    在这里插入图片描述

key-string:最常用的,一般用于存储一个值

key-hash:存储一个对象数据

key-list:使用list结构实现站和队列结构

key-set:交集,差集,并集等操作

key-zset:排行榜

3.2 string常用命令

​ 1.#添加值

​ set key value

​ #2.取值

​ get key

​ #3.批量操作

​ mset key value key value…

​ mget key key…


​ #4.自增命令(点赞)

​ incr key

​ #5.自减命令

​ decr key

​ #6.自增或自建

​ incrby key increment

​ decrby key increment


​ #8.设置值的同时,指定生存时间(每次向Redis中添加数据时,尽量设置生存时间)

​ setex key second value

​ #9.设置值,如果当前key不存在的话,如果key存在,什么事都不做,不存在的话,会set

​ setnx key value

​ #10.在key对应的value后,追加内容

​ append key value

​ #11.查看value字符串的长度

​ strlen key

3.3 hash常用命令

#1.存储数据

​ hset key field value

#2.获取数据

​ hget key field

#3.批量操作

​ hmset key field value field value …

​ hmget key field field…

#4.自增(指定自增/减值)

​ hinerby key field increment#

#5.设置值(如果key-field不存在,那么就正常添加,如果存在,什么事都不做)

​ hsetnx key field value

#6.检查field是否存在

​ hexists key field

#7.删除key对应的某一个field

​ hdel key field field …

#8.获取当前hash结构中的全部field和value

​ hvals key

#9.获取当前hash结构中的全部field

​ hkeys key

#10.获取当前hash结构中全部value

​ hvals key

#11.获取当前bash结构总field的数量

​ hlen key

3.4 list常用命令

#1.存储数据(从左/右侧插入数据)

​ lpush key value …

​ rpush key value …

#2.存储数据(如果key不存在,什么事都不做,如果key存在,但不是list结构的话,什么都不做)

​ lpushx key value

​ rpushx key value

#3.存储数据(存储数据时,指定好你的索引位置,覆盖之前的索引位置的数据)

​ lset key index value


#4.弹栈方式获取数据(左/右侧弹出数据,)

​ lpop key

​ rpop key

#5.查看获取指定索引范围的数据(start 从0开始,stop输入-1,代表最后一个,-2代表倒数第二个)

​ lrange key start stop

#6.获取指定索引位置的数据

​ lindex key index

#7.获取整个列表的长度

​ llen key

#8.删除列表中的数据(他是删除当前列表中的count个value值,count>0)从左侧向右侧删除,count<0从右向左删除,count==0删除列表中全部value)

​ lrem key count value

#9.保留列表中的数据(保留你指定索引范围内的数据,超过整个索引范围被移除掉)

​ ltrim key start stop

#10.将一个列表中最后的一个数据,插入到另一个列表的头部位置

​ rooplpush list1 list2

3.5 set常用命令

#1.存储数据

​ sadd key member …

#2.获取数据

​ smembers key

#3.随机获取数据(会覆盖)

​ spop key


#4.交集

​ sinter set1 set2…

#5.并集(获取全部集合中的数据)

​ sunion set1,set2

#6.差集(获取多个集合中不一样的数据)

​ sdiff set1 set2 …

#7.删除数据

​ srem key member member …

#8.查看当前的set集合中是否包含这个值

​ sismember 可以memver

3.6 zset的常用命令

#1. 添加数据(score必须是一个数值 ,member不允许重复)

​ zadd key score member [score member …]

#2.修改member的分数(如果member是存在与key中的,正常增加分数,如果member不存在,这个命令相当于zadd)

​ zincrby key increment member


#3. 查询指定的member分数

​ zscore key member

#4. 获取zset中数据的数量

​ zscard key

#5. 根据score的范围查询member的数量查询

​ zcount key min max

#6. 删除zset中的成员

​ zrem key member member …

#7. 根据分数从小到大排序、获取指定范围内的数据(withscore如果添加这个参数,那么会返回member对应的分数)

​ zrange key start stop [withscores]

#8. 根据分数从大到小排序、获取指定范围内的数据(withscore如果添加这个参数,那么会返回member对应的分数)

​ zrevrange key start stop [withscores]

#9. 根据分数的返回去获取member(withscores代表同时返回score,添加limit,就和MySQL一样)

​ zrangebyscore key min max [withscores] [limit offset count]

#10.根据分数的返回去获取member(withscores代表同时返回score,添加limit,就和MySQL一样)

​ zrangebyscore key max min [withscores] [limit offset count]

3.7 key常用命令

#1. 查看Redis中全部的key (pattern : .xxx. *xxx)

​ keys pattern

#2. 查看某一个key是否存在

​ exists key

#3. 删除key

​ del key key …

…查看官方文档

四、Java连接Redis

Jedis连接Redis或者Lettuce连接Redis

4.1 Jedis连接Redis

1.创建MAVEN

2.导入jar包

​ jedis

​ junit

​ lombok

3.测试

@Test
public void test1(){
    //1.连接Redis
    Jedis jedis=new Jedis("192.168.56.100",6379);
    //2.操作Redis ,因为Redis的命令是什么,Jedis方法就是什么
    //jedis.set("name","lisi");
    String name = jedis.getrange("start",0,-1) ;
    System.out.println(name);
    //3.释放资源
    jedis.close();
}

4.2 Jedis如何存储一个对象到Redis

准备一个User实体类

导入spring-context依赖

写测试类

4.3 Jedis存储对象到Redis以string形式

导入JSON包

4.4 Jedis连接池

//1.创建连接池配置信息
GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
poolConfig.setMaxTotal(100);//最大连接对象
poolConfig.setMaxIdle(10); //最大空闲数
poolConfig.setMinIdle(3); //最小
poolConfig.setMaxWaitMillis(3000); //时间超过则超时
//2.创建连接池
JedisPool jedisPool=new JedisPool(poolConfig,"192.168.56.100",6379);
//3.获取Jedis
Jedis jedis = jedisPool.getResource();
//3.操作
String stringUser = jedis.get("stringUser");
System.out.println(stringUser);
//4.释放
jedis.close();

4.5 Redis管道操作(提高并发能力)

因为在操作Redis的时候,执行一个命令需要先发送请求到Redis服务器,这个过程需要经历网络的延迟,Redis
还需要给客户端一个响应。
如果我需要一次性执行很多个命令,上述的方式效率很低,可以通过Redig的管道,先将命令放到客户端的一
个Pipeline中,之后一次性的将全部命令都发送到Redi服务,Redis服务一次性的将全部的返回结果响应给客
户端。

package com.it.test;

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

public class Demo5 {
    //Redis管道操作
    @Test
    public void popeline(){
        //1.创建连接池
        long start = System.currentTimeMillis();
        JedisPool pool=new JedisPool("192.168.56.100",6379);
        //2.获取一个连接对象
        //Jedis jedis = pool.getResource();
        3.限制性incr -10000次
        //for (int i=0;i<10000;i++){
        //    jedis.incr("pp");
        //}
        4.释放
        //jedis.close(); //39909
        //-------------------

        //2.获取一个连接对象
        Jedis jedis = pool.getResource();
        //3.创建管道
        Pipeline pipelined = jedis.pipelined();
        //4.执行incr -10000次放到管道中
        for (int i=0;i<10000;i++){
            pipelined.incr("qq");
        }
        //5.执行
        pipelined.syncAndReturnAll();
        //6.释放
        jedis.close(); //242
        long end = System.currentTimeMillis();
        System.out.println("所用时间:"+(end-start));
    }
}

五、Redisc其他配置及集群

5.1 修改yml (映射配置文件,方便修改配置)

在这里插入图片描述

version: '3.1'
services:
  redis:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 6379:6379
    volumes:
      - ./conf/redis.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]

5.2 Redis的AUTH

在这里插入图片描述

5.3 Redis的事务

在这里插入图片描述

5.4 Redis持久化机制

在这里插入图片描述
在这里插入图片描述

5.5 Redis主从架构

单机版Redis存在读写瓶颈的问题

在这里插入图片描述

version: "3.1"
services:
  redis1:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis1
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7001:6379 
    volumes:
      - ./conf/redis1.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis2:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis2
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7002:6379 
    volumes:
      - ./conf/redis2.conf:/usr/local/redis/redis.conf
    links:
      - redis1:master
    command: ["redis-server","/usr/local/redis/redis.conf"] 
  redis3:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis3
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7003:6379 
    volumes:
      - ./conf/redis3.conf:/usr/local/redis/redis.conf
    links:
      - redis1:master
    command: ["redis-server","/usr/local/redis/redis.conf"]

#从节点(redis2 , redis3)配置 (redis1.conf不用配置)

replicaof master 6379

docker-compose up -d

进入redis1.conf容器 执行info(查看), 可以进行读/写

进入redis2.conf容器 执行info(查看), 可以进行读

进入redis3.conf容器 执行info(查看), 可以进行读

5.6 哨兵 sentinel

哨兵可以帮助我们解决主从架构中的单点故障问题
在这里插入图片描述

准备哨兵的配置文件,并且在容器内部手动启动哨兵即可

修改docker-compose.yml

version: "3.1"
services:
  redis1:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis1
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7001:6379 
    volumes:
      - ./conf/redis1.conf:/usr/local/redis/redis.conf
      - ./conf/sentinel1.conf:/data/sentine.conf #添加的内容
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis2:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis2
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7002:6379 
    volumes:
      - ./conf/redis2.conf:/usr/local/redis/redis.conf
      - ./conf/sentinel2.conf:/data/sentine.conf #添加的内容
    links:
      - redis1:master
    command: ["redis-server","/usr/local/redis/redis.conf"] 
  redis3:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis3
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7003:6379 
    volumes:
      - ./conf/redis3.conf:/usr/local/redis/redis.conf
      - ./conf/sentinel3.conf:/data/sentine.conf #添加的内容
    links:
      - redis1:master
    command: ["redis-server","/usr/local/redis/redis.conf"]

redis1.conf redis2.conf redis3.conf 配置文件

#代表哨兵需要后台启动

daemonize yes

#指定Master节点的ip和端口(主)

sentinel monitor master localhost 6379 2

#指定Master节点的ip和端口(从)

sentinel monitor master master 6379 2

#哨兵每隔多久监听一次redis架构

sentinel down-after-milliseconds master 10000
在这里插入图片描述

重启:docker-compose down

​ docker-compose up -d

进入所有的Redis容器开启哨兵

执行 redis-sentinel sentinel.conf

5.7 Redis集群

Redis集群在保证主从加哨兵的基本功能之外,还能够提升Redis存储数据的能力。
在这里插入图片描述


#docker-compose.yml

version: "3.1"
services:
  redis1:
  	image: daocloud.io/library/redis:5.0.7
    restart: always
  	container_name: redis1
  	enviroment:
  	  - TZ=Asia/Shanghai
  	ports: 
  	  - 7001:7001
  	  - 17001:17001
  	volumes: 
  	  - ./conf/redis1.conf:/usr/local/redis/redis.conf
  	command: ["redis-server","/usr/local/redis/redis.conf"]
  redis2:
   	image: daocloud.io/library/redis:5.0.7
    restart: always
  	container_name: redis2
  	enviroment:
  	  - TZ=Asia/Shanghai
  	ports: 
  	  - 7002:7002
  	  - 17002:17002
  	volumes: 
  	  - ./conf/redis2.conf:/usr/local/redis/redis.conf
  	command: ["redis-server","/usr/local/redis/redis.conf"]
  redis3:
    image: daocloud.io/library/redis:5.0.7
    restart: always
  	container_name: redis3
  	enviroment:
  	  - TZ=Asia/Shanghai
  	ports: 
  	  - 7003:7003
  	  - 17003:17003
  	volumes: 
  	  - ./conf/redis3.conf:/usr/local/redis/redis.conf
  	command: ["redis-server","/usr/local/redis/redis.conf"]
  redis4:
    image: daocloud.io/library/redis:5.0.7
    restart: always
  	container_name: redis4
  	enviroment:
  	  - TZ=Asia/Shanghai
  	ports: 
  	  - 7004:7004
  	  - 17004:17004
  	volumes: 
  	  - ./conf/redis4.conf:/usr/local/redis/redis.conf
  	command: ["redis-server","/usr/local/redis/redis.conf"]
  redis5:
   	image: daocloud.io/library/redis:5.0.7
    restart: always
  	container_name: redis5
  	enviroment:
  	  - TZ=Asia/Shanghai
  	ports: 
  	  - 7005:7005
  	  - 17005:17005
  	volumes: 
  	  - ./conf/redis5.conf:/usr/local/redis/redis.conf
  	command: ["redis-server","/usr/local/redis/redis.conf"]
  redis6:
    image: daocloud.io/library/redis:5.0.7
    restart: always
  	container_name: redis6
  	enviroment:
  	  - TZ=Asia/Shanghai
  	ports: 
  	  - 7006:7006
  	  - 17006:17006
  	volumes: 
  	  - ./conf/redis6.conf:/usr/local/redis/redis.conf
  	command: ["redis-server","/usr/local/redis/redis.conf"]

#redis.conf
#指定redis的端口号
port 7001
#开启Redis集群
cluster-enabled yes
#集群信息的文件
cluster-config-file nodes-7001.conf
#集群对外ip地址
cluster-announce-ip 192.168.56.100
#集群对外的port
cluster-announce-port 7001
#集群对外的总线端口
cluster-announce-bus-port 17001

启动了6个Redis节点。

随便跳转到一个容器内部,使用redis-cli管理集群

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

5.7 Java连接Redis集群

使用JedisCluster连接

/**
 * 连接Redis集群
 */
public class Demo6 {
    @Test
    public void test1(){
        //创建Set<HostAndPort>
        Set<HostAndPort> nodes=new HashSet<>();
        nodes.add(new HostAndPort("192.168.56.100",7001));
        nodes.add(new HostAndPort("192.168.56.100",7002));
        nodes.add(new HostAndPort("192.168.56.100",7003));
        nodes.add(new HostAndPort("192.168.56.100",7004));
        nodes.add(new HostAndPort("192.168.56.100",7005));
        nodes.add(new HostAndPort("192.168.56.100",7006));

        //创建JedisCluster对象
        JedisCluster jedisCluster=new JedisCluster(nodes);

        String value = jedisCluster.get("b");

        System.out.println(value);

    }
}

六、Redis常见问题

6.1 key的生存时间到了,Redis会立即删除吗?

回答:不会立即删除

​ 1.定期删除:

​ Redis每隔一段时间就去会去查看Redis设置了过期时间的key,会在100ms间隔中默认查看3个key

​ 2.惰性删除:

​ 如果当你去查询一个已经过了生存时间的key时,Redis会先查看当前key的生存时间,是否已经到 了,直接删除当前key,并且给用户返回一个空值。

6.2 Redis的淘汰机制

在Redis内存已经满的时候,添加了一个新的数据,执行淘汰机制。

​ 1.volatile-lru:

​ 在内存不足时,Redis会再设置过了生存时间的key中干掉一个最近最少使用(lru)的key。

​ 2.allkeys-lru:

​ 在内存不足时,Redis会再全部的key中干掉一个最近最少使用(lru)的key。

​ 3.volatile-lfu:

​ 在内存不足时,Redis会再设置过了生存时间的key中干掉一个最近最少频次使用(lfu)的key。

​ 4.allkeys-lfu

​ 在内存不足时,Redis会再全部的key中干掉一个最近最少频次使用(lfu)的key。

​ 5.volatile-random

​ 在内存不足时,Rddis会再设置过了生存时间的key中随机干掉一个。

​ 6.allkeys-random

​ 在内存不足时,Redis会再全部的key中随机干掉一个。

​ 7.volatile-ttl

​ 在内存不足时,Rddis会再设置过了生存时间的key中干掉一个剩余时间最少的

​ 8.noeviction (Default)

​ 在内存不足时,直接报错。

指定淘汰机制的方式:

​ maxmemory-policy noeviction 具体策略

设置Redis的最大内存:

​ maxmemory

6.3 缓存问题

缓存穿透

20200919091030664

缓存击穿

在这里插入图片描述

缓存雪崩
在这里插入图片描述

缓存倾斜

latile-lru:

​ 在内存不足时,Redis会再设置过了生存时间的key中干掉一个最近最少使用(lru)的key。

​ 2.allkeys-lru:

​ 在内存不足时,Redis会再全部的key中干掉一个最近最少使用(lru)的key。

​ 3.volatile-lfu:

​ 在内存不足时,Redis会再设置过了生存时间的key中干掉一个最近最少频次使用(lfu)的key。

​ 4.allkeys-lfu

​ 在内存不足时,Redis会再全部的key中干掉一个最近最少频次使用(lfu)的key。

​ 5.volatile-random

​ 在内存不足时,Rddis会再设置过了生存时间的key中随机干掉一个。

​ 6.allkeys-random

​ 在内存不足时,Redis会再全部的key中随机干掉一个。

​ 7.volatile-ttl

​ 在内存不足时,Rddis会再设置过了生存时间的key中干掉一个剩余时间最少的

​ 8.noeviction (Default)

​ 在内存不足时,直接报错。

指定淘汰机制的方式:

​ maxmemory-policy noeviction 具体策略

设置Redis的最大内存:

​ maxmemory

6.3 缓存问题

缓存穿透

在这里插入图片描述

缓存击穿

在这里插入图片描述

缓存雪崩
在这里插入图片描述

缓存倾斜
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值