Redis

Redis

1、NoSQL

NoSQL ,Not only SQL,也解释为 non-relational 非关系型数据库,NoSQL是非关系型数据库之中的一个

Redis是nosql最具代表的一种缓存数据库

相对于 RDBMS(关系型数据库),mysql就是关系型数据库

1.1、为什么使用NoSQL?

关系数据库的瓶颈

1.  可以处理大量集中地高并发操作
2.  可以处理海量数据,面对海量数据必须使用主从复制
3.  高可用,nosql在不太影响性能的情况,可以方便实现高可用的架构
4.  访问量大
5.  灵活的数据模型
6.  低成本,对硬件要求低

1.2、劣势:

1.  无关系,数据之间是无联系的(没有外键相联)
2.  不支持标准的 SQL,没有公认的 NoSQL 标准
3.  没有关系型数据库的约数,大多数没有索引的概念
4.  没有事务,不能依靠事务实现ACID(不能回滚,不能做转账等操作)
5.  没有丰富的数据类型

2、Redis安装与使用

2.1、Redis介绍

Redis 是当今非常流行的基于 KV 结构(map)的作为 Cache (缓存)使用的 NoSQL 数据库

一般用户经常访问的数据放在 Redis 中,位于 service 业务层和 dao 持久层之间
用于减轻对数据库查询的压力

官网 redis.cn

一般在 Windows 环境可以模拟测试,真正开发运行是在 Linux 环境中

2.2、Windows 安装

Windows 版本:http://github.com/MSOpenTech/redis/releases

  1. 将压缩包解压

  2. 在解压的目录中打开 cmd ,输入redis-server.exe redis.windows.conf

  3. 运行成功,会出现下图:端口号为6379;此命令窗口不可关闭

  4. 然后双击 redis-cli.exe ,在此输入命令行,进行调用
    在这里插入图片描述

  5. 按 ctrl+c 退出 Redis 服务程序

2.3、Linux 安装

2.3.1、安装

  1. 先从官网下载安装包:

  2. 使用 SecureFXPortable.exe 将文件上传至 Linux 系统的 /home/soft 目录里面

  3. 解压 redis-6.2.6.tar.gz 到/usr/local 目录

    cd /home/soft/

    tar -zxvf redis-6.2.6.tar.gz -C /usr/local/

  4. 查看解压后的文件

  5. 安装 gcc 编译器

    CentOS7的yum工具默认安的gcc版本太老,不更新的话编译不了新版的redis,会报错

    执行:
    yum -y install centos-release-scl
    yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
    echo “source /opt/rh/devtoolset-9/enable” >>/etc/profile
    可以将yum版本升级到9,就可以兼容redis6.0.6的.c文件编译了

    ​ 执行命令:yum -y install gcc

  6. 编译 redis 源文件

    1. 开始执行 make

      cd /usr/local/redis-6.2.6 再执行 make

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

      ​ 如果 make 命令执行过程中出现错误: error: jemalloc/jemalloc.h: No such file or directory

      ​ 解决方式执行 make MALLOC=libc

    2. 执行 make 成功的标志

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

    3. 查看make编译结果,cd src目录

      cd src 在执行 ls

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

2.3.2、启动Redis

redis 安装目录下 redis.conf 是重要的配置文件,包含 redis 服务器的配置信息。 启动 redis 需要指定配置文件路径

启动方式:

​ ①前台启动 ./redis-server

​ ②后台启动 ./redis-server &

第①种 前台启动

启动 Redis 的服务器端:切换到 /usr/local/redis-6.2.6/src 目录下执行 ./redis-server

此时启动不需要指定配置文件位置,但是在后面更改了配置文件 redis.conf 之后,每次启动都要指定配置文件位置

使用命令: ./redis-server ../redis.conf

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

redis 应用以前台的方式启动,不能退出当前窗口,退出窗口,应用终止

在其他窗口查看 redis 启动的进程

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

第②种 后台启动

src目录下执行 ./redis-server &

此时启动不需要指定配置文件位置,但是在后面更改了配置文件 redis.conf 之后,每次启动都要指定配置文件位置

使用命令: ./redis-server ../redis.conf &

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

此时关闭窗口,查看redis进程,依然存在

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

启动服务之后,启动 Redis 客户端

执行 ./redis-cli

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

exit 可以退出命令行客户端

2.3.3、关闭Redis

  1. 使用Redis 客户端关闭

    切换到 redis-4.0.13/src/ 目录,执行./redis-cli shutdown

    这种方式是先拒绝新的请求,然后Redis先完成数据操作再关闭

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

  2. 先使用 ps -rf | grep redis 查出进程号,然后使用 kill pid 或者 kill -9 pid

    进程号应该是 redis-server 的进程号

    这种方式不会考虑当前应用是否有数据正在执行操作,直接关闭应用,不推荐

  3. 在 Redis 客户端执行 shutdown ,然后 Ctrl + C 退出

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

2.4、Redis 客户端

2.4.1、redis 命令行客户端

  1. 直接连接 redis (默认 ip127.0.0.1,端口 6379):./redis-cli
    ​ 在 redis 安装目录/src,执行 ./redis-cli
    ​ 此命令是连接本机 127.0.0.1 ,端口 6379 的 redis
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fT7a2DZ9-1649581490929)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220217113635541.png)]
  2. 指定 IP 和端口连接 redis:./redis-cli -h 127.0.0.1 -p 6379
    ​ -h redis 主机 IP(可以指定任意的 redis 服务器)
    ​ -p 端口号(不同的端口表示不同的 redis 应用)
    ​ 在 redis 安装目录/src,执行 ./redis-cli -h 127.0.0.1 -p 6379
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7IpMsAU-1649581490930)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220217113740670.png)]

2.4.2、远程客户端 Redis Desktop Manager

连接Linux的Reids之前需要修改Redis服务器的配置信息。 Redis服务器有安全保护措施,默认只有本机(安装Redis的那台机器)能够访问。配置信息存放在Redis安装目录下的 redis.conf 文件

远程连接redis需要修改redis主目录下的redis.conf配置文件:

① bind ip 绑定ip此行注释

② protected-mode yes 保护模式改为 no

  1. 修改之前先备份文件
    执行 cp redis.conf redis.conf_bak

  2. 修改文件 vi redis.conf

    1. bind ip 绑定 ip 此行注释
      在进入编辑模式时,输入 /bind 进行搜索,按键 n 向下跳,直到找到

    2. 在 bind 这一行下面一点点的位置,找到 protected-mode yes ,改为 no

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

  3. 修改完成之后,需要重新启动 Reids,默认不加载配置文件。且今后每次启动 Reids 的时候都要指定配置文件位置
    进入 /usr/local/redis-6.2.6/src 目录下,执行命令: ./redis-server ../redis.conf &
    表示本目录中的 redis-server ,上级目录中的 redis.conf
    在这里插入图片描述

  4. 关闭 Linux 系统的防火墙
    执行:systemctl stop firewalld
    查看防火墙状态:systemctl status firewalld

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

  5. 配置 Redis Desktop Manamager(RDM),连接 Redis

  6. 连接成功
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8XKNlI9Q-1649581490933)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220217124552646.png)]

2.5、基本操作命令

redis 默认为 16 个库,redis 默认自动使用 0 号库

(在 redis.conf 文件可配置默认数据库个数,该文件很重要,后续很多操作都是这个配置文件)

(1) 沟通命令,查看状态

​ 输入 ping 输入 ping,redis 给我们返回 PONG,表示 redis 服务运行正常

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

(2) 查看当前数据库中 key 的数目:dbsize

​ 语法:dbsize

​ 作用:返回当前数据库的 key 的数量。

​ 返回值:数字,key 的数量

​ 例:先查索引 5 的 key 个数, 再查 0 库的 key 个数

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

(3) redis 默认使用 16 个库

Redis 默认使用 16 个库,从 0 到 15。 对数据库个数的修改,在 redis.conf 文件中 databases 16

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

(4) 切换库命令:select db

​ 使用其他数据库,命令是 select index

​ 例 1: select 5

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

(5) 删除当前库的数据:flushdb

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

(6) redis 自带的客户端退出当前 redis 连接: exit 或 quit

注意:退出的是客户端,后台 redis 服务仍然在运行

如果使用命令 shutdown 就是直接退出 redis 服务

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

2.6、Redis的key的操作命令

redis 中,所有的 key 都是文本类型的

redis 接收请求是单线程的,建议少用 keys * ,比较耗时

(1)keys

​ 语法:keys pattern
​ 作用:查找所有符合模式 pattern 的 key. pattern 可以使用通配符。
通配符:
​ * :表示 0-多个字符,例如:keys * 查询所有的 key
​ ?:表示单个字符,例如:keys wo?d 匹配 word , wood

例 1:显示所有的 key

例 2:使用 *表示 0 或多个字符

例 3:使用?表示单个字符

(2)exists

​ 语法:exists key [key…]
​ 作用:判断 key 是否存在
​ 返回值:整数,存在 key 返回 1,其他返回 0.使用多个 key,返回存在的 key 的数量

例 1:检查指定 key 是否存在

例 2:检查多个 key

(3)expire

​ 语法:expire key seconds
​ 作用:设置 key 的生存时间,超过时间,key 自动删除。单位是秒
​ 返回值:设置成功返回数字 1,其他情况是 0

例 1:设置红灯的倒计时是 5 秒

(4)ttl

​ 语法:ttl key

​ 作用:以秒为单位,返回 key 的剩余生存时间(ttl: time to live)

返回值:
​ -1 :没有设置 key 的生存时间, key 永不过期。
​ -2:key 不存在
​ 数字 :key 的剩余时间,秒为单位

例 1:设置 redlight 的过期时间是 10,查看剩余时间

(5)type

​ 语法:type key

​ 作用:查看 key 所存储值的数据类型

返回值: 字符串表示的数据类型
​ none (key 不存在)
​ string (字符串)
​ list (列表)
​ set (集合)
​ zset (有序集)
​ hash (哈希表)

例 1:查看存储字符串的 key:wood

例 2:查看不存在的 key

(6)del

​ 语法:del key [key…]
​ 作用:删除存在的 key,不存在的 key 忽略
​ 返回值:数字,删除的 key 的数量

例 1:删除指定的 key

2.7、Redis的5种数据类型

(1)字符串类型(string)

是最基本的数据类型,能存储任何形式的字符串,包括二进制数据、序列化后的数据、JSON 化的对象

最大 512M

(2)哈希类型 hash

hash 特别适合用于存储对象

哈希类型 一般用来存放 java 对象的全部属性数据

key 对应的 哈希类型的value 里面,可以有 field 和 value 的映射表,即键值对里面存放了多个键值对

(3)列表类型 list

列表类型的 value 是简单地字符串列表,是按照顺序插入的,可以根据下标在指定位置插入数据

(4)集合类型set

集合类型的 value 是 string 类型的无序集合,集合成员是唯一的,集合中不能出现重复的数据

(5)有序集合类型zset

zset 类型的 value 是 string 类型的元素集合,不允许重复的成员

但是每个元素会关联一个分数,分数可以重复,通过分数来进行排序

3、Redis操作命令

redis 中,所有的 key 都是文本类型的

3.1、字符串类型string

先测试能连接到 redis 服务器

(1)set

​ 将字符串值 value 设置到 key 中
语法:set key value

设置 value 值

查看已经插入的 key

向已经存在的 key 设置新的 value,会覆盖原来的值

(2)get

​ 获取 key 中设置的字符串值
语法:get key

例如:获取 usrname 这个 key 对应的 value

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

(3)incr

就是 increment
​将 key 中储存的数字值加 1,如果 key 不存在,则 key 的值先被初始化为 0 ,再执行 incr 操作
​(只能对数字类型的数据操作)
语法:incr key

例 1:此时 index 不存在,先创建 index ,初始值为0,然后值 +1

例 2:对非数字的值操作是不行的

(4)decr

就是 decrease
将 key 中储存的数字值减1,如果 key 不存在,则么 key 的值先被初始化为 0 再执 行 decr 操作
(只能对数字类型的数据操作)
语法:decr key

例1:不存在的key,初值为0,再减 1

例2:对存在的数字值的key ,减 1
​ 先执行 incr index ,增加到 3


incr ,decr 在实现关注人数上,文章的点击数上

(5)append

语法:append key value
​ 说明:如果 key 存在,则将 value 追加到 key 原来旧值的末尾;如果 key 不存在,则将 key 设置值为 value
​ 返回值:追加字符串之后的总长度

例 1:追加内容到存在的 key

例 2:追加到不存在的 key,同 set key value

(6)strlen

语法:strlen key

​ 说明:返回 key 所储存的字符串值的长度

​ 返回值:

​ ①:如果key存在,返回字符串值的长度

​ ②:key不存在,返回0

例 1:计算存在 key 的字符串长度


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

​ 设置中文 set k4 中文长度,按字符个数计算

例 2:计算不存在的 key

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

(7)getrange

语法:getrange key start end

​ 作用: 获取 key 中字符串值从 start 开始到 end 结束的子字符串,包括 start 和 end

​ 是从 0 开始

​ 负数表示从字符串的末尾开始,-1 表示最后一个字符

​ 返回值:截取的子字符串

例 1: 截取从 2 到 5 的字符


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

例 2:从字符串尾部截取,start ,end 是负数,最后一位是-1

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

例 3:超出字符串范围的截取,获取合理的子串

(8)setrange

语法:setrange key offset value
​ 说明:用 value 覆盖(替换)key 的存储的值从 offset 开始,不存在的 key 做空白字符串
​ 返回值:修改后的字符串的长度

例 1:替换给定的字符串

例 2:设置不存在的 key

(9)mset

语法:mset key value [key value…]

​ 说明:同时设置一个或多个 key-value 对

​ 返回值:OK

例 1:一次设置多个 key,value

(10)mget

语法:mget key [key …]

​ 作用:获取所有(一个或多个)给定 key 的值

​ 返回值:包含所有 key 的列表

例 1:返回多个 key 的存储值

例 2:返回不存在的 key

3.2、哈希类型hash

hash 特别适合用于存储对象

(1)hset

语法:hset hash 表的 key field value

​ 作用: 将哈希表 key 中的域 field 的值设为 value

​ 如果 key 不存在,则新建 hash 表,执行赋值,如果有 field ,则覆盖值

​ 返回值: ①如果 field 是 hash 表中新 field,且设置值成功,返回 1

​ ②如果 field 已经存在,新值覆盖旧值,返回 0

例 1:新的 field

例 2:覆盖旧的的 field

(2)hget

语法:hget key field

​ 作用:获取哈希表 key 中给定域 field 的值

​ 返回值:field 域的值,如果 key 不存在或者 field 不存在返回 nil

例 1:获取存在 key 值的某个域的值

例 2:获取不存在的 field

(3)hmset

语法:hmset key field value [field value…]

​ 说明:同时将多个 field-value(域-值)设置到哈希表 key 中

​ 此命令会覆盖已经存在的 field;hash 表 key 不存在,创建空的 hash 表,执行 hmset.

​ 返回值:设置成功返回 ok,如果失败返回一个错误

例 1:同时设置多个 field-value

使用 redis-desktop-manager 工具查看 hash 表 website 的数据结构

例 2:key 类型不是 hash,产生错误

(4)hmget

语法:hmget key field [field…]

​ 作用:获取哈希表 key 中一个或多个给定域的值

​ 返回值:返回和 field 顺序对应的值,如果 field 不存在,返回 nil

例 1:获取多个 field 的值

(5)hgetall

语法:hgetall key

​ 作用:获取哈希表 key 中所有的域和值

​ 返回值:以列表形式返回 hash 中域和域的值,key 不存在,返回空 hash

例 1:返回 key 对应的所有域和值

例 2:不存在的 key,返回空列表

(6)hdel

语法:hdel key field [field…]

​ 作用:删除哈希表 key 中的一个或多个指定域 field,不存在 field 直接忽略

​ 返回值:成功删除的 field 的数量

例 1:删除指定的 field

(7)hkeys

语法:hkeys key

​ 作用:查看哈希表 key 中的所有 field 域

​ 返回值:包含所有 field 的列表,key 不存在返回空列表

例 1:查看 website 所有的域名称

(8)hvals

语法:hvals key

​ 作用:返回哈希表 中所有域的值

​ 返回值:包含哈希表所有域值的列表,key 不存在返回空列表

例 1:显示 website 哈希表所有域的值

(9)hexists

语法:hexists key field

​ 作用:查看哈希表 key 中,给定域 field 是否存在

​ 返回值:如果 field 存在,返回 1,其他返回 0

例 1:查看存在 key 中 field 域是否存在

3.3、列表 list

(1)lpush

语法:lpush key value [value…]

​ 作用:将一个或多个值 value 插入到列表 key 的表头(最左边)

​ 从左边开始加入值,从左到右的顺序依次插入到表头

​ 返回值:数字,新列表的长度

例 1:将 a,b,c 插入到 mylist 列表类型

​ 在 redis-desktop-manager 显示

​ 插入图示:

例 2:插入重复值到 list 列表类型

​ 在 redis-desktop-manager 显示

(2)rpush

语法:rpush key value [value…]

​ 作用:将一个或多个值 value 插入到列表 key 的表尾(最右边)

从右到左的顺序依次插入到表头,各个 value 值按从左到右 的顺序依次插入到表尾

​ 返回值:数字,新列表的长度

例 1:插入多个值到列表

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

​ 在 redis-desktop-manager 显示:

(3)lrange

语法:lrange key start stop

​ 作用:获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,以 1 表示列表的第二个元素;

​ start , stop 是列表的下标值,也可以负数的下标

​ -1 表示列表的最后一 个元素, -2 表示列表的倒数第二个元素,以此类推

​ start ,stop 超出列表的范围不 会出现错误。

​ 返回值:指定区间的列表

例 1:返回列表的全部内容,可以使用 lrange key 0 -1

例 2:显示列表中第 2 个元素,下标从 0 开始

(4)lindex

语法:lindex key index

​ 作用:获取列表 key 中下标为指定 index 的元素,列表元素不删除,只是查询

​ 0 表示列表的第一个元素, 1 表示列表的第二个元素

​ start , stop 是列表的下标值,也可以负数的下标

​ -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推

​ 返回值:指定下标的元素;index 不在列表范围,返回 nil

例 1:返回下标是 1 的元素

例 2:不存在的下标

(5)llen

语法:llen key

​ 作用:获取列表 key 的长度

​ 返回值:数值,列表的长度;key 不存在返回 0

例 1:显示存在 key 的列表元素的个数

(6)lrem

语法:lrem key count value

​ 作用:根据参数 count 的值,移除列表中与参数 value 相等的元素

​ count >0 ,从列表的左侧向右开始移除;

​ count < 0 从列表的尾部开始移除;

​ count = 0 移除表中 所有 与 value 相等的值。

​ 返回值:数值,移除的元素个数

例 1:删除 2 个相同的列表元素

例 2:删除列表中所有的指定元素,删除所有的 java

(7)lset

语法:lset key index value

​ 作用:将列表 key 下标为 index 的元素的值设置为 value

​ 返回值:设置成功返回 ok ; key 不存在或者 index 超出范围返回错误信息

例 1:设置下标 2 的 value 为“c”

(8)linsert

语法:linsert key BEFORE|AFTER pivot value

​ 作用:将值 value 插入到列表 key 当中位于值 pivot 之前或之后的位置

​ key 不存在,pivot 不在列表中,不执行任何操作

​ 返回值:命令执行成功,返回新列表的长度。没有找到 pivot 返回 -1, key 不存在返回 0

例 1:修改列表 arch,在值 dao 之前加入 service

3.4、集合类型set

redis 的 Set 是 string 类型的无序集合,集合成员是唯一的,即集合中不能出现重复的数据

(1)sadd

语法:sadd key member [member…]

​ 作用: 将一个或多个 member 元素加入到集合 key 当中

​ 已经存在于集合的 member 元素将被忽略,不会再加入

​ 返回值:加入到集合的新元素的个数。不包括被忽略的元素

例 1:添加单个元素

例 2:添加多个元素

(2)smembers

语法:smembers key

​ 作用:获取集合 key 中的所有成员元素,不存在的 key 视为空集合

例 1:查看集合的所有元素

例 2:查看不存在的集合

(3)sismember

语法:sismember key member

​ 作用:判断 member 元素是否是集合 key 的成员

​ 返回值:member 是集合成员返回 1,其他返回 0

例 1:检查元素是否存在集合中

(4)scard

语法:scard key

​ 作用:获取集合里面的元素个数

​ 返回值:数字,key 的元素个数。其他情况返回 0

例 1:统计集合的大小

例 2:统计不存在的 key

(5)srem

语法:srem key member [member…]

​ 作用:删除集合 key 中的一个或多个 member 元素,不存在的元素被忽略

​ 返回值:数字,成功删除的元素个数,不包括被忽略的元素

例 1:删除存在的一个元素,返回数字 1

例 2:删除不存在的元素

(6)srandmember

语法:srandmember key [count]

​ 作用:只提供 key,随机返回集合中一个元素,元素不删除,依然在集合中;

​ 提供了 count 时,count 正数,随机返回包含 count 个数元素的集合,集合元素各不相同

​ count 负数,随机返回一个 count 绝对值的长度的集合,集合元素可能会重复

​ 返回值:一个元素;多个元素的集合

例 1:随机显示集合的一个元素

例 2:使用 count 参数, count 是正数

例 3:使用 count 参数,count 是负数

(7)spop

语法:spop key [count]

​ 作用:随机从集合中删除一个元素,count 是删除的元素个数

返回值:被删除的元素,key 不存在或空集合返回 nil

例 1:随机从集合删除一个元素

例 2:随机删除指定个数的元素

3.5、有序集合类型zset

redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员

不同的是 zset 的每个元素都会关联一个分数(分数可以重复),分数可以重复,根据分数排大小

分数相同的根据 value 的字母排序

(1)zadd

语法:zadd key score member [score member…]

​ 作用:将一个或多个 member 元素及其 score 值加入到有序集合 key 中

​ 如果 member 存在集合中,则更新值;score 可以是整数或浮点数(保留两位小数)

​ 返回值:数字,新添加的元素个数

例 1:创建保存学生成绩的集合

例 2:使用浮点数作为 score

(2)zrange

语法:zrange key start stop [WITHSCORES]

​ 作用:查询有序集合,指定区间的内的元素

​ 集合成员按 score 值从小到大来排序;start, stop 都是从 0 开始

​ 0 是第一个元素,1 是第二个元素,依次类推

​ 以 -1 表示最后一 个成员,-2 表示倒数第二个成员

​ WITHSCORES 选项是让 value 和 score 一同返回,先显示value再显示score

​ 返回值:自定区间的成员集合

例 1:显示集合的全部元素,不显示 score,不使用 WITHSCORES

例 2:显示集合全部元素,并使用 WITHSCORES

例 3:显示第 0,1 二个成员

例 4:排序显示浮点数的 score

(3)zrevrange

语法:zrevrange key start stop [WITHSCORES]

​ 作用: 返回有序集 key 中,指定区间内的成员

​ 其中成员的位置按 score 值递减(从大到小)来排列;其它同 zrange 命令

​ 返回值:自定区间的成员集合

例 1:成绩榜

(4)zrem

语法:zrem key member [member…]

​ 作用:删除有序集合 key 中指定的一个或多个成员,不存在的成员被忽略

​ 返回值:被成功删除的成员数量,不包括被忽略的成员

例 1:删除指定一个成员 wangwu

(5)zcard

语法:zcard key

​ 作用:获取有序集 key 的元素成员的个数

​ 返回值:key 存在返回集合元素的个数, key 不存在,返回 0

例 1:查询集合的元素个数

(6)zrangebyscore

语法:zrangebyscore key min max [WITHSCORES] [LIMIT offset count]

​ 作用:获取有序集 key 中,所有 score 值介于 min 和 max 之间(包括 min 和 max)的成员

​ 有序成员是按递增(从小到大)排序

​ min,max 是包括在内,使用符号(min(max 表示不包括

​ min, max 可以使用 -inf ,+inf 表示最小和最大

​ limit 用来限制返回结果的数量和区间,分页,offset 是开始限制位置的索引,count 是限制的数量

​ withscores 表示同时显示 score 和 value

​ 返回值:指定区间的集合数据

使用的准备数据

例 1:显示指定具体区间的数据


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

例 2:显示指定具体区间的集合数据,开区间(不包括 min,max)

在这里插入图片描述

例 3:显示整个集合的所有数据

增加新的数据:

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

例 4:使用 limit

显示从第二个位置开始,取一个元素

(7)zrevrangebyscore

语法:zrevrangebyscore key max min [WITHSCORES ] [LIMIT offset count]

​ 作用:返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员

​ 有序集成员按 score 值递减(从大到小)的次序排列;其他同 zrangebyscore

例 1:查询工资最高到 3000 之间的员工

(8)zcount

语法:zcount key min max

​ 作用:返回有序集 key 中,score 值在 min、max 之间(默认包括等于 min 或 max)的成员的数量

例 1:求工资在 3000-5000 的员工数量

高级命令

命令
keys *返回满足的所有键,可以模糊查询
exists是否存在指定key
expire设置某个 key 的过期时间,使用 ttl 查看剩余时间
persist取消过期时间
flushdb清空当前数据库
flushall清空所有数据库
select选择数据库,从0开始
move [key] [数据库下标]将当前数据库的key转移到其他数据库
randomkey随机返回数据库的一个 key
rename重命名 key
echo打印名
dbsize查看数据库 key 数量
info查看数据库信息
config get实时传储收到的请求,返回相关的配置信息
config get *返回所有配置

4、高级话题

4.1、Redis 事务

Redis 中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令,redis 事务保证这些命令被执行时中间不会被任何其他操作打断

4.1.1、事务操作的命令

(1) multi

​ 语法: multi

​ 作用:标记一个事务的开始。事务内的多条命令会按照先后顺序被放进一个队列当中

​ 返回值:总是返回 ok

(2) exec

​ 语法:exec

​ 作用:执行所有事务块内的命令

​ 返回值:事务内的所有执行语句内容,事务被打断,返回 nil

(3) discard

​ 语法:discard

​ 作用:取消事务,放弃执行事务块内的所有命令

​ 返回值:总是返回 ok

(4) watch

​ 语法:watch key [key …]

​ 作用:监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动, 那么事务将被打断

​ 返回值:总是返回 ok

(5) unwatch

​ 语法:unwatch

​ 作用:取消 WATCH 命令对所有 key 的监视

​ 如果在执行 WATCH 命令之后, EXEC 命令 或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了

​ 返回值:总是返回 ok

4.1.2、事务的实现

(1) 正常执行事务

事务的执行步骤:

  1. 首先开启事务
  2. 其次向事务队列中加入命令
  3. 最后执行事务提交

例 1:事务的执行:

​ 1)multi:

​ 用 multi 命令告诉 Redis,接下来要执行的命令你先不要执行,而是把它们暂时存 起来(开启事务)

​ 2)saddworks john

​ 第一条命令进入等待队列(命令入队)

​ 3)sadd works rose

​ 第二条命令进入等待队列(命令入队)

​ 4)exce

​ 告知 redis 执行前面发送的两条命令(提交事务)

查看 works 集合

(2) 事务执行 exec 之前,入队命令错误(语法错误;严重错误导致服务器不能正常工作(例如内存不足)),放弃事务

执行事务步骤:

​ 1)MULTI 正常命令

​ 2)SET key value 正常命令

​ 3)INCR 命令语法错误

​ 4)EXEC 无法执行事务,那么第一条正确的命令也不会执行,所以 key 的值不会设置成功

结论:事务执行 exec 之前,入队命令错误,事务终止,取消,不执行

(3) 事务执行 exec 命令后,命令执行错误,事务提交

执行步骤:

​ 1)MULTI 正常命令

​ 2)SET username zhangsan 正常命令

​ 3)lpop username 正常命令,语法没有错误,执行命令时才会有错误

​ 4)EXEC 正常执行,发现错误可以在事务提交前放弃事务,执行 discard

结论:在 exec 执行后的所产生的错误,即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行

Redis 在事务失败时不进行回滚,而是继续执行余下的命令

Redis 这种设计原则是:Redis 命令只会因为错误的语法而失败(这些问题不能在入队时发现),或是命令用在了错误类型的键上面,失败的命令并不是 Redis 导致,而是由编程错误造成的,这样错误应该在开发的过程中被发现,生产环境中不应出现语法的错误。就是在程序的运行环境中不应该出现语法的错误。而 Redis 能够保证正确的命令一定会被执行。 再者不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速

(4) 放弃事务

执行步骤:

​ 1) MULTI 开启事务

​ 2) SET age 25 命令入队

​ 3) SET age 30 命令入队

​ 4) DISCARD 放弃事务,则命令队列不会被执行

例 1:

(5) Redis 的 watch 机制
  1. Redis 的 WATCH 机制

    ① WATCH 机制:使用 WATCH 监视一个或多个 key , 跟踪 key 的 value 修改情况,如果有 key 的 value 值在事务 EXEC 执行之前被修改了,整个事务被取消。EXEC 返回提示信息,表示事务已经失败。

    ② WATCH 机制使的事务 EXEC 变的有条件,事务只有在被 WATCH 的 key 没有修改的前提下才能执行。不满足条件,事务被取消。使用 WATCH 监视了一个带过期时间的键,那么即使这个键过期了,事务仍然可以正常执行

    ③ 大多数情况下,不同的客户端会访问不同的键,相互同时竞争同一 key 的情况一般都很 少,watch 能很好解决数据冲突的问题

  2. 何时取消 key 的监视(WATCH)?

    ① WATCH 命令可以被调用多次。对键的监视从 WATCH 执行之后开始生效,直到调用 EXEC 为 止。不管事务是 否成功执行,对所有键的监视都会被取消

    ② 当客户端断开连接时,该客户端对键的监视也会被取消

    ③ UNWATCH 命令可以手动取消对所有键的监视

  3. WATCH 的事例

    执行步骤:

    1. 首先启动 redis-server , 在开启两个客户端连接,分别叫 A 客户端和 B 客户端。 启动 Redis 服务器

    2. A 客户端(红色):WATCH 某个 key,同时执行事务

    3. B 客户端(黄色):对 A 客户端 WATCH 的 key 修改其 value 值

      1) 在 A 客户端设置 key : str.lp ,登录人数为 10

      2) 在 A 客户端监视 key : str.lp

      3) 在 A 客户端开启事务 multi

      4) 在 A 客户端修改 key : str.lp 的值为 11

      5) 在 B 客户端修改 key : str.lp 的值为 15

      6) 在 A 客户端执行事务 exec

      7) 在 A 客户端查看 str.lp 值,A 客户端执行的事务没有提交,因为 WATCH 的 str.lp 的值已 经被修改了,所有放弃事务

4.2、持久化

可以同时支持 RDB 和 AOF 方式,服务启动时,会先读取 AOF 文件,再读取 RDB 文件

4.2.1、持久化概述

持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存中,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久化的,而把数据放在磁盘就算是一种持久化

Redis 的数据存储在内存中,内存是瞬时的,如果 linux 宕机或重启,又或者 Redis 崩溃或重启,所有的内存数据都会丢失,为解决这个问题,Redis 提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据

4.2.2、持久化方式

(1) RDB 方式
㈠、什么是 RDB 方式?

​ Redis Database(RDB),也称为内存快照,就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存

​ RDB 保存了在某个时间点的数据集(全部数据),存储在一个二进制文件中,只有一个文件,默认是 dump.rdb

​ RDB 技术非常适合做备份,可以保存最近一个小时、一天、一个月的全部数据。保存数据是在单独的进程中写文件,不影响 Redis 的正常使用

​ RDB 恢复数据时比其他 AOF 速度快

㈡、如何实现?

RDB 方式的数据持久化,仅需在 redis.conf 文件中配置即可,默认配置是启用的

在配置文件 redis.conf 中搜索 SNAPSHOTTING,查找在注释开始和结束之间的关于 RDB 的配置说明,配 SNAPSHOTTING 置地方有三处:

  1. 配置执行 RDB 生成快照文件的时间策略。

    对 Redis 进行设置,让它在 “N 秒内数据集至少有 M 个 key 改动” 这一条件被满足时, 自动保存一次数据集

    配置格式:(save可以有多条)

    save <seconds> <changes>

    ​ save 900 1

    ​ save 300 10

    ​ save 60 1000

  2. dbfilename:设置 RDB 的文件名,默认文件名为 dump.rdb

  3. dir:指定 RDB 文件的存储位置,默认是 ./ 当前目录

配置步骤:

  1. 查看 ps -ef | grep redis ,如果 redis 服务启动,先停止

  2. 修改 redis.conf 文件,修改前先备份,执行 cp redis.conf bak_redis.conf

    查看默认启用的 RDB 文件

  3. 编辑 redis.conf 增加 save 配置,修改文件名等。vi redis.conf

    修改的内容:(save “” 表示关闭RDB方式)

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

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

    原来的默认的 dump.rdb 删除,修改 redis.conf 后,重新启动 redis

  4. 在 20 秒内容,修改三个 key 的值

  5. 查看生成的 rdb 文件

㈢、总结

优点:由于存储的是数据快照文件,恢复数据很方便,也比较快

缺点:

​ 1)会丢失最后一次快照以后更改的数据,因为需要满足条件才会保存,如果不满足条件数据容易丢失

​ 如果你的应用能容忍一定数据的丢失,那么使用 rdb 是不错的选择;如果你不能容忍一定数据的丢失,使用 AOF

​ 2)由于需要经常操作磁盘,RDB 会分出一个子进程。如果你的 redis 数据库很大的话,子进程占用比较多的时间,并且可能会影响 Redis 暂停服务一段时间(millisecond 级别), 如果你的数据库超级大并且你的服务器 CPU 比较弱,有可能是会达到一秒

(2) AOF 方式
㈠、什么是 AOF 方式

Append-only File(AOF),Redis 每次接收到一条改变数据的命令时,它将把该命令写到一个 AOF 文件中(只记录写操作,读操作不记录),当 Redis 重启时,它通过执行 AOF 文件中所有的命令来恢复数据

会同时记录对数据的修改命令和数据,把命令保存,重启之后,会重新执行一遍记录的所有命令

㈡、如何实现

​ AOF 方式的数据持久化,仅需在 redis.conf 文件中配置即可(默认不开启,如想使用需要配置)

配置项:

  1. appendonly :默认是 no,改成 yes 即开启了 aof 持久化

  2. appendfilename :指定 AOF 文件名,默认文件名为 appendonly.aof

  3. dir :指定 RDB 和 AOF 文件存放的目录,默认是 ./

  4. appendfsync :配置向 aof 文件写命令数据的策略

    1. no :不主动进行同步操作,而是完全交由操作系统来做(即每 30 秒一次),比较快但不是很安全

    2. always :每次执行写入都会执行同步,慢一些但是比较安全

    3. everysec (默认):每秒执行一次同步操作,比较平衡,介于速度和安全之间。这是默认项

      万一丢失也只会丢失这一秒之内的操作数据

  5. auto-aof-rewrite-min-size:允许重写的最小 AOF 文件大小,默认是 64M 。当 aof 文件大 于 64M 时,开始整理 aof 文件,去掉无用的操作命令,缩小 aop 文件

操作示例:

  1. 停止运行的 redis ,备份要修改的 redis.conf

  2. 查看 redis 安装目录/src 下有无 .aof 文件,默认是在 redis 的当前目录

    一般没有此文件,因为默认是关闭的,需要进行配置开启 AOF 方式

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

  3. 编辑 redis.conf

    设置 appendonly 为 yes 即可

    查看 appendfsync 的当前策略

    查看 appendfilname 的文件名称

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

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

  4. 在 redis 客户端执行写入命令

  5. 查看 aof 文件


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

㈢、总结
  1. append-only 文件是另一个可以提供完全数据保障的方案

  2. AOF 文件会在操作过程中变得越来越大

    比如,如果你做一百次加法计算,最后你只会 在数据库里面得到最终的数值,但是在你的 AOF 里面会存在 100 次记录,其中 99 条记录 对最终的结果是无用的

    但 Redis 支持在不影响服务的前提下在后台重构 AOF 文件,让文件得以整理变小

  3. 可以同时使用这两种方式,redis 默认优先加载 aof 文件(aof 数据最完整)

4.3、主从复制

4.3.1、主从复制–读写分离(集群)

​ 通过持久化功能,Redis 保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了, 也会导致数据丢失

​ 为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台 服务器出现故障其他服务器依然可以继续提供服务

​ 这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,那该怎么实现呢?Redis 的主从复制

​ Redis 提供了复制(replication)功能来自动实现多台 redis 服务器的数据同步(每天 19 点新闻联播,基本从 cctv1-8 各大卫视都会播放)

​ 我们可以通过部署多台 redis,并在配置文件中指定这几台 redis 之间的主从关系,主负责写入数据,同时把写入的数据实时同步到从机器,这种模式叫做主从复制,即 master/slave

​ 并且 redis 默认 master 用于写,slave 用于读,向 slave 写数据会导致错误

(1) Redis 主从复制实现(master/slave)

修改配置文件,启动时,服务器读取配置文件,并自动成为指定服务器的从服务器,从 而构成主从复制的关系

实现步骤:

模拟多 Reids 服务器,在一台已经安装 Redis 的机器上,运行多个 Redis 应用模拟多 个 Reids 服务器

一个 Master,两个 Slave

1、新建三个 Redis 的配置文件

如果 Redis 启动,先停止

作为 Master 的 Redis 端口是 6380

作为 Slaver 的 Redis 端口分别是 6382 , 6384

从原有的 redis.conf 拷贝三份,分别命名为 redis6380.conf、 redis6382.conf、 redis6384.conf

同时需要清空三个文件,可以使用 重定向 > redis6380.conf

2、编辑 Master 配置文件

编辑 Master 的配置文件 redis6380.conf——在空文件加入如下内容

  • ​ include /usr/local/redis-4.0.13/redis.conf
  • ​ daemonize yes #本句是说明此服务是后台启动
  • ​ port 6380
  • ​ pidfile /var/run/redis_6380.pid
  • ​ logfile 6380.log
  • ​ dbfilename dump6380.rdb

配置项说明:

  1. include :包含原来的配置文件内容。/usr/local/redis-4.0.13/redis.conf 按照自己的目录设置
  2. daemonize :yes 后台启动应用,相当于 ./redis-server & 的作用
  3. port :自定义的端口号
  4. pidfile : 自定义的文件,表示当前程序的 pid ,进程 id
  5. logfile :日志文件名
  6. dbfilename :持久化的 rdb 文件名
3、编辑 Slave 配置文件

编辑 Slave 的配置文件 redis6382.conf ——在空文件加入如下内容

  • ​ include /usr/local/redis-4.0.13/redis.conf
  • ​ daemonize yes
  • ​ port 6382
  • ​ pidfile /var/run/redis_6382.pid
  • ​ logfile 6382.log
  • ​ dbfilename dump6382.rdb
  • ​ slaveof 127.0.0.1 6380

配置项说明:

  1. slaveof :表示当前 Redis 是谁的从。当前是 127.0.0.0 端口 6380 这个 Master 的从

编辑 Slave 的配置文件 redis6384.conf——在空文件加入如下内容

  • ​ include /usr/local/ redis-4.0.13/redis.conf
  • ​ daemonize yes
  • ​ port 6384
  • ​ pidfile /var/run/redis_6384.pid
  • ​ logfile 6384.log
  • ​ dbfilename dump6384.rdb
  • ​ slaveof 127.0.0.1 6380
4、启动服务器 Master/Slave 都启动

启动方式 ./redis-server 配置文件

启动 Redis,并查看启动进程

此处运行可以看到没有使用 & ,但是仍然是后台启动,因为配置文件中配置过了

5、查看配置后的服务信息

命令:

  1. Redis 客户端使用指定端口连接 Redis 服务器

    ./redis-cli -p 端口

  2. 查看服务器信息

    info replication

登录到 Master:6380

查看当前服务信息

在客户端的 Redis 内执行命令 info replication Master

服务的查看结果:

在新的 Xshell 窗口分别登录到 6382 ,6384 查看信息

6384 也登录,内容同 6382

6、向 Master 写入数据

在 6380 执行 flushall 清除数据,避免干扰的测试数据。生产环境避免使用

7、再从 Slave 读数据

6382、6384 都可以读主 Master 的数据,不能写

Slave 写数据失败

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

(2) 容灾处理

当 Master 服务出现故障,需手动将 slave 中的一个提升为 master,剩下的 slave 挂至新的 master 上

(冷处理:机器挂掉了,再处理)

命令:

  1. slaveof no one

    将一台 slave 服务器提升为 Master (提升某 slave 为 master)

  2. slaveof 127.0.0.1 6382

    (将 slave 挂至新的 master 上)

执行步骤:

1、将 Master:6380 停止(模拟挂掉)

2、选择一个 Slave 升到 Master,其它的 Slave 挂到新提升的 Master

3、将其他 Slave 挂到新的 Master

在 Slave 6384 上执行 slaveof 127.0.0.1 6382

现在的主从(Master/Slave)关系:Master 是 6382, Slave 是 6384

查看 6382:

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

4、原来的服务器重新添加到主从结构中

6380 的服务器修改后,重新工作,需要把它添加到现有的 Master/Slave 中

先启动 6380 的 Redis 服务

连接到 6380 端口

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

当前服务挂到 Master 上

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

5、查看新的 Master 信息

在 6382 执行:

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

现在的 Master/Slaver 关系是:

Master :6382

Slave :6380 6384

(3) 操作命令

进入客户端需指定端口:./redis-cli -p 6380

不配置启动默认都是主master

查看 redis 服务器所处角色 : info replication

(4) 总结
  1. 一个 master 可以有多个 slave
  2. slave 下线,读请求的处理性能下降
  3. master 下线,写请求无法执行
  4. 当 master 发生故障,需手动将其中一台 slave 使用 slaveof no one 命令提升为 master,其 它 slave 执行 slaveof 命令指向这个新的 master,从新的 master 处同步数据
  5. 主从复制模式的故障转移需要手动操作,要实现自动化处理,这就需要 Sentinel 哨兵, 实现故障自动转移

4.3.2、高可用 Sentinel 哨兵

Sentinel 哨兵是 redis 官方提供的高可用方案,可以用它来监控多个 Redis 服务实例的运行情况。Redis Sentinel 是一个运行在特殊模式下的 Redis 服务器。Redis Sentinel 是在多个 Sentinel 进程环境下互相协作工作的

Sentinel 系统有三个主要任务:

  1. 监控 : Sentinel 不断的检查主服务和从服务器是否按照预期正常工作

  2. 提醒 : 被监控的 Redis 出现问题时,Sentinel 会通知管理员或其他应用程序

  3. 自动故障转移 : 监控的主 Redis 不能正常工作,Sentinel 会开始进行故障迁移操作

    ​ 将一个从服务器升级新的主服务器,让其他从服务器挂到新的主服务器,同时向客户端提供新的主服务器地址

一般会有至少3个哨兵,奇数个

每个哨兵都在独立的服务器上运行,独自监控主(Master)Redis,不能因为一个哨兵故障而影响其他哨兵

多个哨兵每秒都向服务器发送 PING 命令,如果一个哨兵得不到 PONG 的回复,此哨兵就认为服务器挂了,投一票;第二个哨兵也得不到回复,也投一票;第三个哨兵不管投不投票,服务器都被认定为挂了,少数服从多数。所以哨兵是奇数个的

默认端口号 26379

(1) Sentinel 配置

复制三份 sentinel.conf 文件:

Sentinel 系统默认 port 是 26379 。现在配置三个 port 分别设置为 26380 , 26382 , 26384

三个文件分别命名:

​ sentinel26380.conf

​ sentinel26382.conf

​ sentinel26384.conf

执行复制命令 cp sentinel.conf xxx.conf

(2) 三份 sentinel 配置文件修改
  1. 修改 port 26380、 port 26382、 port 26384
  2. 修改 sentinel monitor mymaster 127.0.0.1 6380 2

格式:sentinel monitor <name> <masterIP> <masterPort> <Quorum 投票数>

Sentinel监控主(Master)Redis,Sentinel 根据Master的配置自动发现Master的Slave,Sentinel 默认端口号为26379

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

  1. sentinel26380.conf

    1. 修改 port

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

    2. 修改监控的 master 地址

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

  2. sentinel26382.conf 修改port 26382 , master的port 6382

  3. sentinel26384.conf 修改port 26384 , master的port 6382

(3) 启动主从(Master/Slave)Redis

启动 Reids

查看 Master 的配置信息

连接到 6382 端口

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

使用 info 命令查看 Master/Slave

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

(4) 启动 Sentinel

redis安装时make编译后就产生了redis-sentinel程序文件,可以在一个redis中运行多个 sentinel 进程

启动一个运行在 Sentinel 模式下的 Redis 服务实例语法:

./redis-sentinel ../sentinel26379.conf 前台启动,窗口不可关闭

在 XShell 开启三个窗口分别执行:

执行以下三条命令,将创建三个监视主服务器的Sentinel实例:

第一个窗口:./redis-sentinel …/sentinel26380.conf

第二个窗口:./redis-sentinel …/sentinel26382.conf

第三个窗口:./redis-sentinel …/sentinel26384.con

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

(5) 主 Redis 不能工作

让 Master 的 Redis 停止服务,执行 shutdown

先执行 info replication 确认 Master 的 Redis,再执行 shutdown

查看当前 Redis 的进程情况

(6) Sentinel 的起作用

在 Master 执行 shutdown 后,稍微等一会 Sentinel 要进行投票计算,从可用的 Slave 选举新的 Master

查看 Sentinel 日志,三个 Sentinel 窗口的日志是一样的

查看新的 Master

查看原 Slave 的变化

(7) 新的 Redis 加入 Sentinel 系统,自动加入 Master

重新启动 6382

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

查看 6384 的信息

测试数据:在 Master 写入数据

在 6382 上读取数据,不能写入

(8) 监控
  1. Sentinel 会不断检查 Master 和 Slave 是否正常
  2. 如果 Sentinel 挂了,就无法监控,所以需要多个哨兵,组成 Sentinel 网络,一个健康的 Sentinel 至少有 3 个 Sentinel 应用,彼此在独立的物理机器或虚拟机
  3. 监控同一个 Master 的 Sentinel 会自动连接,组成一个分布式的 Sentinel 网络,互相通信并交换彼此关于被监控服务器的信息
  4. 当一个 Sentinel 认为被监控的服务器已经下线时,它会向网络中的其它 Sentinel 进行确认,判断该服务器是否真的已经下线
  5. 如果下线的服务器为主服务器,那么 Sentinel 网络将对下线主服务器进行自动故障转移, 通过将下线主服务器的某个从服务器提升为新的主服务器,并让其从服务器转移到新的主服务器下,以此来让系统重新回到正常状态
  6. 下线的旧主服务器重新上线,Sentinel 会让它成为从,挂到新的主服务器下
(9) 总结

主从复制,解决了读请求的分担,从节点下线,会使得读请求能力有所下降,Master 下线, 写请求无法执行

Sentinel 会在 Master 下线后自动执行故障转移操作,提升一台 Slave 为 Master,并让其它 Slave 成为新 Master 的 Slave

4.4、安全设置

4.4.1、设置密码

访问 Redis 默认是没有密码的,这样不安全,任意用户都可以访问,可以启用使用密码 才能访问 Redis

设置 Redis 的访问密码:修改 redis.conf 中这行 requirepass 密码

密码要比较复杂,不容易破解,而且需要定期修改。因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,需要指定非常非常强大 的密码来防止暴力破解

(1)开启访问密码设置

修改 redis.conf , 使用 vim 命令。找到 requirepass 行去掉注释,requirepass 空格后就是 密码

**例 1:**设置访问密码是 123456 (这是练习使用,生产环境要设置复杂密码),修改 redis.conf

原始内容:

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

修改后:

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

(2)访问有密码的 Redis

如果 Redis 已经启动,关闭后,重新启动

访问有密码的 Redis 两种方式:

  1. 在连接到客户端后,使用命令 auth 密码,命令执行成功后,可以正常使用 Redis

    1. 连接服务

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

    2. 输入命令 auth 密码

  2. 在连接客户端时使用 -a 密码。例如 ./redis-cli -h ip -p port -a password

4.4.2、修改默认端口

修改 redis 的端口,这一点很重要,使用默认的端口很危险

redis.conf 中修改 port 6379 将其修改为自己指定的端口(可随意),端口 1024 是保留给操作系统使用的。用户可以使用 的范围是 1024-65535

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

使用 -p 参数指定端口,例如:./redis-cli -p 新设置端口

4.5、缓存穿透、击穿、雪崩

一般使用 Redis 作为缓存

用户发起请求的时候先会去缓存中查询,如果缓存中没有,再去数据库中查询

4.5.1、缓存穿透(查不到)

何为缓存穿透?

查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透

如果直接去查询一条缓存中和数据库中都不存在的数据,那么这个查询就会百分之百查询到数据库上去

这种查询称为缓存穿透,因为去缓存中查询一定会失败,所以请求就会打到数据库上

缓存穿透带来的问题

如果有人恶意拿一个不存在的数据去查询,会产生大量请求,这些请求最终会打到数据库中,数据库可能因为承受不住压力而宕机

如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大

解决方案

1、缓存空值

碰到查询结果为空的键,放一个空值在缓存中,下次再访问就立刻知道这个键无效,不用查询数据库了

但是这个方法并不完美:

  1. 缓存空值需要更多的内存空间,我们可以设置一个比较短的过期时间,过了这个时间,自动剔除这个空值的缓存。此外空值应该与正常值分开存放,否则当空间不足的时候,缓存系统可能有优先剔除正常值,再剔除空值,这个漏洞可能会被攻击
  2. 如果某个key在缓存中记录为空值,过了一段时间,数据库中添加了这个key,那此时需要利用某种方式来清除这个空值。如果使用的是redis缓存,更新数据后直接在redis中清除即可
2、BloomFilter(布隆过滤器)

布隆过滤器是一种数据结构,对所有可能查询的参数以 hash 形式存储,在控制层先进行校验,不符合则丢弃,从而避免对底层存储系统的查询压力

布隆过滤器可以用来告诉你某样东西 “ 一定不存在或者可能存在 ”

我们在缓存之前加一个布隆过滤器,查询的时候先去布隆过滤器中查询key是否存在,如果不存在就直接返回,如果key可能存在,再去缓存中查询

4.5.2、缓存击穿(查太多)

何为缓存击穿?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期)

这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

在缓存失效的瞬间,持续的大并发就穿破缓存直击数据库

解决方案:

  1. 设置热点数据永远不过期。
  2. 加互斥锁,互斥锁参考代码如下

4.5.3、缓存雪崩

何为缓存雪崩?

缓存雪崩是指缓存中数据大批量到过期时间(或者 Redis 宕机或断网),而查询数据量巨大,引起数据库压力过大甚至down机

和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库

当某一时刻发生大规模的缓存失效的情况,会有大量的请求进来直接冲到数据库上面

结果就是数据库扛不住,直接挂掉

解决方案

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生,甚至于设置热点数据永远不过期
  2. 数据预热,将热点数据加载到缓存中;如果缓存数据库是分布式部署,将热点数据均匀分布在不同缓存数据库中
  3. 使用集群缓存,保证缓存服务高可用(多增几台Redis,搭建集群)
  4. 限流降级,使用 Hystrix 限流(Hystrix 是一个 java 依赖隔离工具,它帮助我们管理线程池,让每种资源都单独运行在自己的线程池中)

5、Jedis 操作 Redis

5.1、 Jedis、Commons-Pool依赖

5.1.1、引入 Jedis 依赖

Jedis 是 Redis 的 java 客户端。 Maven 依赖:

<!-- jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

5.1.2、引入 Commons-Pool 依赖

Jedis 对象并不是线程安全的,在多线程下使用同一个 Jedis 对象会出现并发问题

为 了避免每次使用 Jedis 对象时都需要重新构建,Jedis 提供了 JedisPool

JedisPool 是基于 Commons Pool 2 实现的一个线程安全的连接池

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

5.2、操作 String 类型

使用 Jedis 工具库在java代码中操作Redis数据库的数据

步骤:

  1. 修改redis.conf、关闭 Linux防火墙
  2. 新建 java project,引入依赖
  3. 新建类,创建 Jedis 对象,调用其方法,实现数据的处理
/**
 *  这里是通过网络访问 Redis 服务器
 *      1、需要修改 redis.conf,启动 redis 服务器
 *      2、关闭 Linux 防火墙,或者让 redis 端口通过防火墙
 */
public static void main(String[] args) {
    /**
     *  创建 Jedis 对象,指定连接的redis服务器的 ip、端口
     *      String host :redis所在 Linux 服务器的 ip
     *      int port :redis 运行的端口号
     */
    String host = "192.168.1.1";
    int port = 6379;
    Jedis jedis = new Jedis(host, port);
    
    //设置访问密码
    jedis.auth("123456");

    //调用 Jedis 对象的方法,操作 Redis 数据
    jedis.set("key1","value1");
    //获取 key 值
    String v = jedis.get("key1");
    System.out.println("key1===" + v);

    // mset() :一次创建多个 key-value
    jedis.mset("key2","value2","key3","value3");
    //mget() :获取多个 key 对应的值
    List<String> vs = jedis.mget("key1", "key2", "key3");
    vs.forEach(System.out::println);
}

5.3、使用 Jedis 连接实例池

public class redisUtil {
    private static JedisPool pool;

    //创建 JedisPool 对象
    public static JedisPool open(String ip, int port){
        if (pool == null){
            //创建 JedisPoolConfig 对象,给config设置连接池参数,使用config对象创建JedisPool
            JedisPoolConfig config = new JedisPoolConfig();

            //设置连接池参数
            //设置最大的线程数,一个线程就是一个 Jedis 对象
            config.setMaxTotal(20);
            //设置最大的空闲数,两个空闲线程留备用
            config.setMaxIdle(2);
            //设置检查项为true,表示从线程池中获取的悐一定是经过检查是可用的
            config.setTestOnBorrow(true);

            //创建 JedisPool 对象
            /**
             *  构造器参数:
             *      GenericObjectPoolConfig:配置器
             *      String host:redis所在Linux的ip
             *      int port:redis的端口号
             *      int timeout:连接redis的超时,毫秒值
             *      String password:redis的访问密码
             */
            pool = new JedisPool(config, ip, port, 6000, "123456");
        }
        return pool;
    }
    //关闭 pool 对象
    public static void close(){
        if (pool != null){
            pool.close();
        }
    }
}

5.4、使用连接池操作 hash 数据类型

public static void main(String[] args) {
    JedisPool pool = null;
    Jedis jedis = null;
    try{
        //创建 JedisPool 对象,从JedisPool中获取 Jedis
        pool = redisUtil.open("192.168.1.1", 6379);
        //从 pool 中获取 Jedis
        jedis = pool.getResource();

        /**
         *  设置 hash 类型
         *      key:login
         *          field:username
         *          value:lisi
         */
        jedis.hset("login","username","lisi");
        //mget() :获取多个 key 对应的值
        String v = jedis.hget("key1", "username");
        System.out.println("username的值" + v);
    }finally {
        //使用完的连接池对象,放回连接池
        if (pool != null){
            pool.close();
        }
    }
}

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

5.5、列表 list

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

5.6、集合 Set

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

5.7、有序集合 Sorted Set

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

5.8、事务

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

6、lettuce 操作 Redis

Java 操作 Redis 的库有两个,Jedis 和 Lettuce,目前 SpringBoot 2.x 中已经将 Jedis 换成了 Lettuce。Lettuce 和 Jedis 的都是连接Redis Server的客户端程序。

Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池,为每个Jedis实例增加物理连接。

Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例

导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

配置文件

spring.redis.host=localhost  #默认值
spring.redis.port=6379       #默认值
#spring.redis.password=battcn

# 连接超时时间(毫秒)
spring.redis.timeout=10000
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
spring.redis.database=0
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0

实体类

@Data
public class User implements Serializable {
    private static final long serialVersionUID = 8655851615465363473L;
    private Long id;
    private String username;
    private String password;
}

测试

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    //private RedisTemplate<String,Object> template;
    //有些公司约定,redis的key、value都是字符串类型
    //StringRedisTemplate extends RedisTemplate<String, String>
    private StringRedisTemplate template;

    @Test
    void contextLoads() {
        template.opsForValue();    //操作字符串对象
        template.opsForList();    //操作list对象
        template.opsForSet();    //操作set对象
        template.opsForZSet();    //操作zset对象
        template.opsForHash();    //操作hash对象

        template.opsForValue().set("name","caomei");
        System.out.println(template.opsForValue().get("name"));

        //redis命令,就是spring-data-redis方法的缩写
        /**
         *  lpush —— leftpush
         *  rpush —— rightpush
         *  template.opsForList().leftpush()
         */
        //template的方法,就是redis的全局命令
        //template.keys("*") —— keys *
        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值