参考:https://www.bilibili.com/video/BV1Rv41177Af?p=5&spm_id_from=pageDriver
Redis版本为6.6

1.1 Redis安装

1.1.1 下载安装最新版本的gcc编辑器

yum install -y gcc

查看gcc版本gcc —version

1.1.2下载最新版本的Redis安装包并上传到任意目录

https://redis.io/
下载resis-6.2.6.tar.gz到/opt目录

1.1.3解压:tar -zxvf redis-6.2.6.tar.gz

1.1.4进入目录:cd redis-6.2.6

1.1.5在 redis-6.2.6 目录下执行make编译

1.1.6再次该目录下执行make install

如果报错,首先看gcc有没有成功安装,其次可以执行 make distclean 清楚编译文件重新编译

1.2 安装目录:/usr/local/bin

  • redis-benchmark:性能测试工具
  • redis-check-aof:修复有问题的AOF文件
  • redis-check-rdb/redis-check-dump:修复有问题的dump.rbd
  • redis-sentinel:Redis集群使用
  • redis-server:Redis服务器启动命令
  • redis-cli:客户端操作入口

1.3 前台启动(不推荐)

//该窗口不能做操作也不能关闭
redis-server
Port:占用的端口号
Ctrl+c停止

1.4后台启动(推荐)

//把窗口关闭仍可以正常使用

1.4.1 备份redis.conf

cd /opt
拷贝一份redis.conf到其他目录
cp redis.conf /etc/redis.conf

1.4.2后台启动设置daemonize no 改成 daemonize yes

修改redis.conf文件里的daemonize no 改成 daemonize yes,设置支持后台启动
可以使用vim的搜索命令”/daemonize no”

1.4.3 Redis启动

cd /usr/local/bin
redis-server /etc/redis.conf
ps -ef | grep redis

1.4.4 用客户端连接Redis

redis-cli
127.0.0.1:6379> //成功连接
127.0.0.1:6379>ping //表示目前正常连接
PONG

1.4.5 Redis关闭

方案一:
redis-cli
127.0.0.1:6379>shutdown
方案二:
ps -ef | grep redis //找到进程
kill //杀死进程

1.4.6 Redis相关知识

端口号6379对应非智能手机上Merz四个字母所在的按键

Redis是单线程 + 多路IO复用
为什么是单线程?
redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。
redis 用 单个CPU 绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事。在内存的情况下,这个方案就是最佳方案。
[

](https://blog.csdn.net/weixin_43582101/article/details/90474946)
什么是IO多路复用?
I/O就是指的我们网络I/O,多路指多个TCP连接(或多个Channel),复用指复用一个或少量线程。串起来理解就是很多个网络I/O复用一个或少量的线程来处理这些连接。

为什么Redis要用单线程 + 多路IO复用?
首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的。
文件事件处理器使用 I/O 多路复用模块同时监听多个 FD,当 accept、read、write 和 close 文件事件产生时,文件事件处理器就会回调 FD 绑定的事件处理器。
虽然整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,提高了网络通信模型的性能,同时也可以保证整个 Redis 服务实现的简单。

和Memcached相比,Redis有哪些优势?
memcached支持单一的数据类型,Redis支持更多的数据类型;memcached不支持持久化,Redis支持;memcached使用 多线程+锁 的机制,Redis使用 单线程 + 多路IO复用

1.5 Redis常用五大数据类型

用客户机登陆Redis
image.png

Redis键(keys)

  • set k1 lucy 设置一个key为k1、value为lucy的库
  • keys * 查看当前库所有key
  • exists key 判断某个key是否存在
  • type key 查看你的key是什么类型
  • del key 删除指定的key数据
  • unlink key 根据 value 选择非阻塞删除
  • (仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作中)
  • expire key 10 10秒中:为给定的key设置过期时间
  • ttl key 查看还有多少秒国企,-1表示永远不过其,-2表示已过期
  • select 命令切换数据库
  • dbsize 查看当前数据库的key的数量
  • flushdb 清空当前库
  • flushall 通杀全部库

1.5.1 Redis 字符串(String)

1.5.1.1 简介

String是Redis最近本的类型,可以理解为与Memcached一摸一样的类型,一个key对应一个value。

String类型是二进制安全的,意味着Redis的string可以包含任何数据,比如 jpg 图片或者序列化对象。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M。


1.5.1.2 常用命令

set 添加键值对
image.png

get 取key对应的值
append 将给定的追加到原值的末尾
image.png
strlen 获得值的长度
setnx 只有在key不存在时,设置key的值

incr
将 key 中储存的数字值增1
只能对数字值操作,如果为空,新增值为1
decr
将 key 中储存的数字值减1
image.png
只能对数字值操作,如果为空,新增值为-1
incrby / decrby <步长> 将 key 中储存的数字值增减,自定义步长
image.png

mset
同时设置一个或多个 key-value对

mget
同时获取一个或多个value

msetnx
同时设置一个或多个key-value对,当且仅当所有给定的key都不存在

getrange <起始位置><结束位置>
获得值的范围

setrange <起始位置>
覆写 所储存的字符串值,从<起始位置>开始(索引从0开始)

setex <过期时间>
设置键值的同时设置过期时间,单位秒

getset
以新换旧,设置新值时获得旧值

1.5.1.3 原子性

所谓原子操作是指不会被线程调度机制打断的操作

这种操作一旦开始,就一直运行到结束,不会被打断:

  1. 在单线程中,能够在单条指令中完成的操作都可以认为是“原子操作”,因为终端只能发生在指令之间
  2. 在多线程中,不能被其他进程打断的操作就是原子操作

Redis 单命令原子性主要得益于Redis是单线程

1.5.1.4 数据结构

String的数据结构为简单动态字符串。是可以修改的字符串,采用分配冗余空间的方式来减少内存的频繁分配。

1.5.2 Redis 列表(List)

1.5.2.1 简介

单键多值

Redis列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头步或者尾部
他的底层实际上是个双向链表,对两端的操作性很高,通过索引下标的操作中间的节点性能会较差。(查询效率比较低)

1.5.2.2 常用命令

lpush/rpush …从左边/右边插入一个或多个值

lpop/rpop 从左边/右边突出一个值 。无值无键

rpoplpush 列表右边吐出一个值,插到列表左边

lrange
按索引下标获得元素(从左到右)

lrange mylist 0-1 左边第一个,-1右边第一个(0-1表示获取所有)

lindex 按照索引下标获得元素(从左到右)
lien 获得列表长度

linsert before 的后面插入
插入值
lrem 从左边删除n个value(从左到右)

1.5.2.3 数据结构

List的数据结构为快速链表

首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表

它将所有元素挨在一起储存,分配的是一块连续的内存

当数量比较多的时候才会改成quicklist

因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。

Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速恶的插入删除性能,又不会出现太大的空间冗余。

1.5.3 Redis 集合(Set)

1.5.3.1 简介

Redis set 对外提供的功能与list是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要储存一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。

Redi的 set 时 string 类型的无序集合。底层是一个value为null的hash表,所以添加,删除,查找的复杂度都是O(1).

1.5.3.2 常用命令

  • sadd ……
  • 将一个或多个 member 元素加入到集合 key 中,已经存在 member元素将被忽略
  • smembers 取出该集合的所有值
  • sismember 判断集合是否含有该值,有1,没有0
  • scard 返回该集合的元素个数
  • srem …… 删除集合中的某个元素
  • spop 随机从该集合中吐出一个值
  • srandmember 随机从该集合中取出n个值。不hi从集合中删除
  • smove value把集合中一个值从一个集合移动到另一个集合
  • sinter 返回两个集合的交集元素
  • sunion 返回两个集合的并集元素
  • sdiff 返回连那个集合的差集元素(key1中的,不包含key2中的)


1.5.3.3 数据结构

Set的数据结构是 dict 字典,字典使用哈希表实现的
在Java中HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。
Redis的set结构也是一样,它的内部也使用Hash结构,所有的value都指向同一个内部值。

1.5.4 Redis 哈希(Hash)

1.5.4.1 简介

Redis hash 是一个键值对集合,他的value按照一定的对应关系进行存储。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash特别适合用于存储对象

用户 ID 为查找的key,存储的 value 用户对象包含姓名,年龄,生日等信息,如果用普通的 ket/value 结构来存储

有两种存储方法:
假如有一串数据 {id=1,name=zhangsan,age=20}

第一种存储方式
user:{id=1,name=张三,age=20}
第二种存储方式
user:id 1
user:name zhangsan
user:age 20

第三种hash
id 1
user name zhangsan
age 20

1.5.4.2 常用命令

  • hset 集合中的键赋值
  • hget 集合取出
  • hmset … 批量设置hash的值
  • hexists 查看哈希表 key 中,给定域 field 是否存在
  • hkeys 列出该 hash 集合的所有field
  • hvals 列出该hash集合的所有value
  • hincrby 为哈希表 key 中的域 field 的值加上增量 1
  • hsetnx 将哈希表 key 中的域 field 的值设置为 value, 当且仅当域 field 不存在


1.5.4.3数据结构

Hash类型对应的数据结构是两种:ziplist(压缩表)、hashtable(哈希表),当 field-value 长度较短且个数较少时,使用ziplist,否则使用hashtable

1.5.5 Redis有序集合Zset(sorted set)

1.5.5.1 简介

Redis 有序集合 zset 与普通集合 set 非常相似,是一个没有重复元素的字符串集合。

不同之处时有序集合的每个成员都关联了一个评分(score),这个评分被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员时唯一的,但是哦i拿高分可以是重复的。

因为元素时有序的,所以也可以很快的根据评分或者次序(position)来获取与一个范围的元素

访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的只能列表

1.5.5.2 常用命令

  • zadd
  • 将一个或多个 member 元素及其 score 值加入到有序集 key 当中

  • zrange [WITHSCORES]
  • 返回有序集 key 中,下标在之间的元素
  • 带WITHSCORES,可以让分数一起和值返回到结果集

  • zrangebyscore key minmax [withscores] [limit offset count]

  • 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按score值递增(从小到大)次序排列

  • zrevrangebyscore key maxmin [withscores] [limit offset count]

  • 同上改为从大到小排列

  • zincrby 为元素的score加上增量

  • zrem 删除该集合下,指定值的元素
  • zcount 统计该集合,分数区间内的元素个数
  • zrank 返回该值在该集合中的排名,从0开始。


1.5.5.3 数据结构

SortedSet(zset)是 Redis 提供的一个非常特别的数据结构,一方面它等价于 Java 的数据结构 Map,可以给每一个元素 value 赋予一个权重 score,另一方面它又类似于 TreeSet,内部的元素会按照权重 score 进行排序,可以得到每个元素的名词,还可以通过 score 的范围来获取元素的列表

zset 底层使用了两个数据结构

(1)hash ,hash的作用就是关联元素 value 和权重 score ,保障元素 value 的唯一性, 可以通过元素 value 找到相应的 score 值。(2)跳跃表,跳跃表的目的在于给元素 value 排序,根据 score 的范围获取元素列表

1.5.5.4 跳跃表

跳跃表(skiplist)是一种有序数据结构, 它通过在每个节点中维持多个指向其他节点的指针, 从而达到快速访问节点的目的。

1.6 配置文件

所在目录:/etc/redis.conf

1.6.1 Units单位

配置大小单位,开头定义了一些基本的度量单位,只支持字节(bytes),不支持位(bit),大小写不敏感

image.png

1.6.2 INCLUDES

文件中可包含其他文件内容
image.png

1.6.3网络配置( NETWORK )

详细配置

1.6.3.1 bind = 127.0.0.1 -::1

默认情况 bind = 127.0.0.1 只能接受本机的访问请求

不写的情况下无限制接受任何 ip 地址的访问

生产环境肯定要写你应用服务器的地址;服务器是需要远程访问的,所以需要将其注释掉

1.6.3.2 protected-mode yes

开启本地保护模式,开启后只允许本地访问,不允许远程访问
改为“protected-mode no”
image.png

1.6.3.3 port 6379

端口号默认6379
image.png

1.6.3.4 tcp-backlog511

设置tcp连接的gacklog值,backlog是一个连接队列值, backlog队列总和 = 未完成三次握手的队列 + 已经完成三次握手的队列
在高并发环境下需要一个高 backlog 值来避免客户端连接问题。
image.png

1.6.3.5 timeout 0

设置超时时间(秒),如果超时就会释放连接
image.png

1.6.3.6 tcp-keepalive 300

检查心跳时间(秒),在规定时间内检测是否有操作,没有操作则会释放连接
image.png

1.6.4 通用(GENERAL)

image.png

1.6.4.1 daemonize yes

是否为后台进程,设置为yes
image.png

1.6.4.2 pidfile /var/run/redis_6379.pid

存放 pid 文件的位置,每个实例会产生一个不同的 pid 文件
在该文件中保存进程号
image.png

1.6.4.3 loglevel notice

日志级别
debug 开发者模式,能看到更详细的信息
verbose 能看到有用的信息
notice 生产环境中信息
warning 只能看到有用的重要的信息
image.png

1.6.4.4 logfile “”

设置文件的默认输出路径,默认为空(**)
image.png

1.6.4.5 databases 16

谁当库的数量,默认为16
image.png

1.6.5 安全(SECURITY)

image.png

1.6.5.1设置密码

两种设置方法
第一种在配置文件中找到 “requirepass foobared” ,取消注释
image.png
第二种通过本地连接使用命令设置密码
image.png

1.6.6 限制(LIMITS)

1.6.6.1 maxclients

设置 redis 可以同时连接多少个客户端

默认为10000个客户端

如果到达了该限制, redis 就会拒绝新的连接请求,并且向请求方发出 “max number of clients reached” 以作回应
image.png

1.6.6.2 maxmemory

设置 redis 可以使用的内存量,一旦达到内存使用上限, redis 将会试图移除内部数据,移除规则可以通过 maxmemory-policy 来指定

建议必须设置,否则内存占满会造成服务器宕机

image.png

1.7 Redis 持久化

Redis提供了两种持久化方式 ,RDB(Redis Database) 和 AOF(Append Of File)。

1.7.1 RDB是什么

RDB,是在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是所说的 Snapshot 快照,它恢复时是将快照文件直接读取到内存里。

1.7.2 RDB备份是如何执行的

Redis会单独创建一个子进程(fork)来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能,如果需要进行大规模的数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。唯一缺点是最后一次持久化后的数据可能丢失。

1.7.3 子进程(Fork)

Fork 的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数量等)数值都和原进程一样,但是是一个全新的进程,并作为原进程的子进程。

在 Linux 程序中,Fork 会产生一个和父进程完全相同的子进程,但子进程在此后多会”exec“系统调用,出于效率考虑,Linux 中引入了”写时复制技术”。

一般情况父进程和子进程会共用一段物理内存,只有进程空间的隔断的内容要发生变化时,才会将父进程的内容复制一段给子进程。

1.7.4 RDB的优劣势

优势

  • 适合较大规模的数据恢复
  • 对数据完整性和一致性要求不高的情况下更适合使用
  • 节省磁盘空间
  • 恢复速度快

劣势

  • Fork 的时候,内存中的数据被克隆了一份,大致 2 倍的膨胀性需要考虑。
  • 虽然 Redis 在 fork 时使用了 写时拷贝技术 ,但是如果数据过于庞大时还是比较消耗性能。
  • 在备份周期在一定间隔时间做一次备份,所以如果 Redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。

    1.7.5配置文件

    /etc/redis.conf
    image.png

    1.7.5.1 dbfilename dump.rdb

    在redis.conf中配置文件名称,默认为 dump.rdb
    image.png
    在主进程中如果有数据的变化就会产生名为 dump.rdb 的文件

1.7.5.2 dir ./

rdb文件的保存路径,也可以修改,默认为Redis启动时命令行所在的目录下 dir /usr/local/bin
image.png

1.7.5.3 stop-writes-on-bgsave-error yes

redis无法使用硬盘时不再进行写操作
image.png

1.7.5.4 rdbcompression yes

持久化文件是否进行压缩
image.png

1.7.5.5 rdbchecksum yes

检查文件完整性,在持久化之前检查数据是否完整,是否有损坏。
会增加大约10%的性能损耗,如果希望获取到最大的性能提升,可以关闭。
image.png

1.7.5.6 Save

格式: save 秒钟 写操作次数
默认是1分钟改了1万次,或五分钟内改了10次,或15分钟改了1次
image.png
save:save时只管保存,其他不管,全部阻塞。手动保存,不建议
bgsave:Redis会在后台异步进行快照操作,快照同时还可以相应客户端请求
可以通过 lastsave 命令获取最后一次成功执行快照的时间。

1.7.5.7 RDB的备份

进入rdb文件所在目录
将rdb文件拷贝到其他地方

rdb的恢复

  • 关闭Redis
  • 先把备份的文件拷贝到工作目录下并改名,例如:cp d.rdb dump.rdb
  • 启动Redis,备份数据会自动加载

    1.8 Redis持久化(AOF)

1.8.1 AOF是什么

以日志的形式来记录每个写操作(增量保存),将 Redis 执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件, redis 启动之初会读取该文件重新构建数据,换言之, redis 重启的话旧根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

1.8.2 AOF 默认不开启

可以在 redis。conf 中配置文件名称 ,默认为 appendonly.aof
AOF 文件的保存路径, 同 RDB 的路径一致

1.8.3 当 AOF 和 RDB同时开启时,系统默认读取 AOF的数据(数据不会存在丢失)

1.8.4 配置文件

image.png

1.8.4.1 AOF同步频率设置

  • appendfsync always

始终同步,每次 Redis 的写入都会立刻计入日志;性能较差但数据完整性比较好。

  • appendfsync everysec

每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。

  • appendfsync no

redis 不主动进行同步,把同步时机交给操 作系统。

1.8.4.1 重写/压缩 (Rewrite)

1.8.4.1.1 Rewrite是什么

AOF采用文件追加方式,文件会越来越大,为了避免出现此种情况,新增了重写机制,当 AOF 文件的大小超过所设定的阈值时, Redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令 bgrewriteaof。

1.8.4.1.2 重写/压缩原理,如何进行

AOF文件持续增长而过大时,会 fork 出一条新进程来将文件重写(也是先写临时文件最后再 rename), redis4.0 版本后的重写,是指吧 rdb 的快照,以二级制的形式附在新的 aof 头部,作为已有的历史数据,替换掉原来的流水账操作。

no-appendfsync-on-rewrite = yes
不写入aof文件只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的数据(减低数据安全性,提高性能)。
no-appendfsync-on-rewrite = no
还是回吧数据向磁盘里写入,但是遇到重写操作,可能会发生阻塞(数据安全,但是性能降低)。

1.8.4.1.3 触发机制

Redis会记录上次重写时的 AOF 大小,默认配置时当 AOF 文件大小是上次 rewrite 后大小的一倍且文件大于 64M 时触发。

重写虽然可以节约大量磁盘空间,减少恢复时间,但每次重写还是有一定的负担,因此设定 Redis 要满足一定条件才会进行重写。

auto-aof-rewrite-percentage:设置重写的基准值,文件达到 100% 时开始重写(文件时原来重写后文件的 2 倍时触发)
auto-aof-rewrite-min-size:设置重写的基准值,最小文件 64M。达到这个值开始重写。

1.8.4.1.4 重写流程

  1. bgrewriteaof 触发重写,判断是否当前有 bgsave 或 bgrewriteaof 在运行, 如果有,则等待该命令结束后再继续执行。

  2. 主进程 fork 出子进程执行重写操作,保证主进程不会阻塞。

  3. 子进程遍历 redis 内存中数据到临时文件,客户端的写请求同时写入 aof buf 缓冲区和 aof rewrite _buf 重写缓冲区保证原 AOF 文件完整以及新 AOF 文件生成期间的新的数据修改动作不会丢失。

  4. 子进程写完新的 AOF 文件后.向主进程发信号.父进程更新统计信息。2).主进程把aof rewrite _buf 中的数据写入到新的AOF文件。

  5. 使用新的 AOF 文件覆盖旧的AOF文件,完成AOF重写。

    1.8.5AOF启动/修复/恢复

    AOF 的备份机制和性能虽然和 RDB 不同, 但是备份和恢复的操作同 RDB 一样,都是拷贝备份文件,需要恢复时再拷贝到 Redis 工作目录下,启动系统即加载

正常恢复

  • 修改默认的appendonly on ,改成 yes
  • 将有数据的 aof 文件复制一份保存到队形目录 (查看目录:config get dir)
  • 恢复:重启 redis,然后重新加载

异常恢复

  • 修改默认的 appendonly no, 改为yes
  • 如遇到 AOF 文件损坏, 通过 /usr/local/bin/redis-check-aof—fix appendonly.aof 进行恢复
  • 备份被写坏的 AOF 文件
  • 恢复:重启 redis ,然后重新加载

1.8.6 AOF持久化流程

  1. 客户端的请求写命令会被 append 追加到 AOF 缓冲区内;
  2. AOF 缓冲区根据AOF持久化策略 [always,everysec,no] 将操作 sync 同步到磁盘的 AOF 文件中;
  3. AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件 rewrite 重写,压缩 AOF 文件容量;
  4. Redis 服务重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的

1.8.7 优劣势

优势

  • 备份机制更稳定,丢失数据概率更低
  • 可读的日志文本,通过操作 AOF 文件,可以处理误操作

劣势

  • 比起 RDB 占用更多的磁盘空间
  • 恢复备份速度要慢
  • 每次读写都同步的话,有一定的性能压力
  • 存在个别 Bug ,造成恢复不能

1.9 用 RDB 好还是 AOF 好?

官方推荐是两个都启用
如果对数据不敏感,可以单独选用 RDB
不建议单独用 AOF ,因为可能会出现 Bug
如果只是做春内存缓存,可以都不用