RedisDay1

RedisDay1

什么是Redis

Redis(Remote Dictionary Server)是一个开源的高性能键值存储系统,支持多种数据结构,如字符串、哈希、列表、集合等。它以内存存储为主,提供极快的读写速度,常用于缓存、消息队列和实时数据处理。Redis支持持久化,确保数据安全,并具备主从复制、高可用和分布式集群功能,适用于高并发场景。

Redis的特点

  • Redis是一个高性能key/value内存型数据库 在redis中,所有的数据形式都是以键值对的方式来存储的
  • Redis支持丰富的数据类型 string,list,set,sorted set,hash 指的是键值对中的值的类型
  • Redis支持持久化 持久化:将数据落盘,明天会详细说一说redis中的持久化
  • Redis单线程,单进程 由于是单线程和单进程的,所以它的线程是安全的,我们之前说的java中的多线程安全在分布式中不起作用,当时只针对一个JVM中是有效的。

Redis安装时的注意事项

redis底层是由C语言编写的
#安装gcc  
- yum install -y gcc

#进入解压缩目录执行如下命令
# 注意。一定要在Makefile文件的同目录下使用下面的命令对redis做编译(切记:不要make test
- yum install -y tcl
- make MALLOC=libc


#编译完成后执行如下命令
- make install PREFIX=/usr/local/soft/redis

#进入/usr/redis目录启动redis服务 
- ./redis-server

#Redis服务端口默认是 6379
ps aux|grep redis	

#进入bin目录执行客户端连接操作
- ./redis-cli -h localhost –p 6379
# 如果是在一台机器上,可以省略后面的
- ./redis-cli
# 1. redis服务启动的时候,如果单纯的就是redis-server命令启动,默认启动后会占用6379的端口号

# 2. 一个redis服务相当于一个新的redis数据库

# 3.修改端口号
	一台机器上可以同时启动多个redis服务,只要每个redis服务所占用的端口号不同即可,要想启动多个redis服务,就必须去修改端口号
  	在哪修改呢?在linux中,绝大部分的框架组件要想修改参数的话,可以去找到对应软件的配置文件,然后做修改
 	redis服务启动的时候会默认应用一个配置文件,默认服务启动的时候会去编译好的目录下找到一个叫做redis.conf的文件,并非是安装目录
  	只要是单纯的使用redis-server启动的话,都会去编译好的目录下找到一个叫做redis.conf的文件去启动,即便是修改了端口号,也是只能启动一个redis服务。
  	修改redis.conf文件中的port 6379---> port xxxx
  	指定端口号启动命令:redis-server /xxx/xx/redis.conf
  	
# 4. 配置环境变量,为了可以在任意目录下执行redis命令
	vim /etc/profile
	
	修改配置文件:
	export JAVA_HOME=/usr/local/soft/jdk1.8.0_171
    export REDIS_HOME=/usr/local/soft/redis
    export PATH=.:$PATH:$JAVA_HOME/bin:$REDIS_HOME/bin
    
    保存退出:
    :wq
    
    让环境变量生效
    source /etc/profile

# 5. 客户端指定服务链接
	如果就默认的redis-cli链接的话,默认连接的是本机localhost(127.0.0.1)的6379端口号的redis服务
	指定连接某一台机器上的某个端口号的redis服务
	redis-cli -h 服务器的ip地址 -p 端口号
	举例:redis-cli -h localhost -p 7000

# 6. 查看当前数据库中的所有键 key *

# 7. 数据库的概念
	对于一个redis服务而言,包含默认有16个数据库给我们使用,从0开始编号,共15号数据库,默认使用的是0号数据库
	切换库,select 库号  举例:使用1号库:select 1
	库和库之间数据不共享
	库和库之间的键可以重名

Redis中的五大基本数据类型

String类型

常用命令

命令 说明
set 设置一个key/value
get 根据key获得对应的value
mset 一次设置多个key value
mget 一次获得多个key的value
getset 获得原始key的值,同时设置新值
strlen 获得对应key存储value的长度
append 为对应key的value追加内容
getrange 索引0开始 截取value的内容 到末尾-1 [开始,结束]
setex 设置一个key存活的有效期(秒)
psetex 设置一个key存活的有效期(毫秒)
setnx 存在不做任何操作,不存在添加
msetnx原子操作(只要有一个存在不做任何操作) 可以同时设置多个key,只有有一个存在都不保存
decr 进行数值类型的-1操作
decrby 根据提供的数据进行减法操作
Incr 进行数值类型的+1操作
incrby 根据提供的数据进行加法操作
Incrbyfloat 根据提供的数据加入浮点数(不是四舍五入)

List类型

list列表 相当于java中list 集合

特点:元素有序(插入和取出的顺序一致)且可以重复,key还是一个字符串,值是一个list

常用指令

命令 说明
lpush 将某个值加入到一个key列表头部 lpush list1 xiaohu xiaohei xiaoming 当列表不存在的时候会进行创建
lpushx 同lpush,但是必须要保证这个key存在 必须在列表进行存在的情况下从左插入
rpush 将某个值加入到一个key列表末尾
rpushx 同rpush,但是必须要保证这个key存在
lpop 返回和移除列表左边的第一个元素
rpop 返回和移除列表右边的第一个元素
lrange 获取某一个下标区间内的元素 lrange list 0 -1
llen 获取列表元素个数
lset 设置某一个指定索引的值(索引必须存在)
lindex 获取某一个指定索引位置的元素
lrem 删除重复元素
ltrim 保留列表中特定区间内的元素
linsert 在某一个元素之前,之后插入新元素

Set类型

特点: Set类型 Set集合 元素无序 不可以重复

常用命令

(如果set集合没有元素,key也就不存在了)

命令 说明
sadd 为集合添加元素
smembers 显示集合中所有元素 无序
scard 返回集合中元素的个数
spop 随机返回一个元素 并将元素在集合中删除
smove 从一个集合中向另一个集合移动元素 必须是同一种类型
srem 从集合中删除一个元素
sismember 判断一个集合中是否含有这个元素
srandmember 随机返回元素 后面可以加数字 表示每次返回的个数
sdiff 去掉第一个集合中其它集合含有的相同元素
sinter 求交集
sunion 求和集

ZSet类型

特点: 可排序的set集合 排序 不可重复

常用命令

命令 说明
zadd 添加一个有序集合元素 zadd zset 2 xiaohu 3 xiaohu2
zcard 返回集合的元素个数
zrange 升序 zrevrange 降序 返回一个范围内的元素 如果想看看分数 withscores
zrangebyscore 按照分数查找一个范围内的元素 zrangebyscore zset 0 20 withscores limit 0 2
zrank 返回排名
zrevrank 倒序排名
zscore 显示某一个元素的分数
zrem 移除某一个元素
zincrby 给某个特定元素加分

hash类型

特点: value 是一个map结构 存在key value key 无序的

redis key(String) value(map)

Map<String,Map<String,value>> map

举例:map name zhangsan

常用命令

命令 说明
hset 设置一个或多个key/value对
hget 获得一个key对应的value
hgetall 获得所有的key/value对
hdel 删除某一个key/value对
hexists 判断一个key是否存在
hkeys 获得所有的key
hvals 获得所有的value
hmset 设置多个key/value
hmget 获得多个key的value
hsetnx 设置一个不存在的key的值
hincrby 为value进行加法运算(只能针对数值做运行)
hincrbyfloat 为value加入浮点值

Redis的两种持久化方法

  • RDB快照【简便】
  • AOF日志文件【需修改redis.conf文件手动开启】

RDB持久化(快照Snapshot)

这种方式可以将某一时刻的所有数据都写入硬盘中,当然这也是redis的默认开启持久化方式,保存的文件是以.rdb形式结尾的文件因此这种方式也称之为RDB方式。

默认情况下,redis服务在哪个目录下启动,哪个目录就是工作目录,后面的rdb持久化或者AOF持久化,产生的文件都存在于redis的当前工作目录下。在哪里启动就会读取哪里的快照文件

快照生成方式

  • 客户端方式: BGSAVE 和 SAVE指令
  • 服务器配置自动触发
# 1.客户端方式之BGSAVE
- a.客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork¹来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。
	
`名词解释: fork当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类似于unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务`

BGSAVE

# 2.客户端方式之SAVE- b.客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令

SAVE

注意: SAVE命令并不常用,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外服务

# 3.服务器配置方式之满足配置自动触发
- 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令

# 4.服务器接收客户端shutdown指令
- 当redis通过shutdown指令接收到关闭服务器的请求时,会执行一个save命令,阻塞所有的客户端,不再执行客户端执行发送的任何命令,并且在save命令执行完毕之后关闭服务器

AOF追加日志文件持久化

这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集.

开启AOF持久化

#在redis的默认配置中AOF持久化机制是没有开启的,需要在配置中开启

# 1.开启AOF持久化
- a.修改 appendonly yes 开启持久化
- b.修改 appendfilename "appendonly.aof" 指定生成文件名称

日志追加频率

#redis.conf文件中有三种追加方式:always、everysec、no

# 1.always 【谨慎使用】
- 说明: 每个redis写命令都要同步写入硬盘,严重降低redis速度
- 解释: 如果用户使用了always选项,那么每个redis写命令都会被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少;遗憾的是,因为这种同步策略需要对硬盘进行大量的写入操作,所以redis处理命令的速度会受到硬盘性能的限制;
- 注意: 转盘式硬盘在这种频率下200左右个命令/s ; 固态硬盘(SSD) 几百万个命令/s;
- 警告: 使用SSD用户请谨慎使用always选项,这种模式不断写入少量数据的做法有可能会引发严重的`写入放大`问题,导致将固态硬盘的寿命从原来的几年降低为几个月。

# 2.everysec 【推荐默认】
- 说明: 每秒执行一次同步显式的将多个写命令同步到磁盘
- 解释: 为了兼顾数据安全和写入性能,用户可以考虑使用everysec选项,让redis每秒一次的频率对AOF文件进行同步;redis每秒同步一次AOF文件时性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,redis可以保证,即使系统崩溃,用户最多丢失一秒之内产生的数据。 

# 3.no	【不推荐】
- 说明: 由操作系统决定何时同步 
- 解释:最后使用no选项,将完全由操作系统决定什么时候同步AOF日志文件,这个选项不会对redis性能带来影响但是系统崩溃时,会丢失不定数量的数据,甚至丢失全部数据,另外如果用户硬盘处理写入操作不够快的话,当缓冲区被等待写入硬盘数据填满时,redis会处于阻塞状态,并导致redis的处理命令请求的速度变慢。

AOF文件的重写(面试题)

AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件Redis提供了AOF重写(ReWriter)机制。

重写用来在一定程度上减小AOF文件的体积,加快启动速度,并且还能保证数据不丢失

#触发重写的方式

# 1.客户端方式触发重写
- 执行BGREWRITEAOF命令  不会阻塞redis的服务

# 2.服务器配置方式自动触发
- 配置redis.conf中的auto-aof-rewrite-percentage选项 参加下图↓↓↓
- 如果设置auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大

重写原理(面试题)

从 Redis 7.0.0 开始,Redis 使用了多部分 AOF 机制。也就是将原来的单个AOF文件拆分为基础文件(最多一个)和增量文件(可能不止一个)。基本文件表示重写AOF 时存在的数据的初始(RDB 或 AOF 格式)快照。增量文件包含自创建最后一个基本 AOF 文件用来来的增量更改。所有这些文件都放在一个单独的目录中,并由清单文件跟踪。

从 Redis 7.0.0 开始,在调度 AOF 重写时,Redis 父进程会打开一个新的增量 AOF 文件继续写入。子进程执行重写逻辑并生成新的基础 AOF。Redis 将使用一个临时清单文件来跟踪新生成的基础文件和增量文件。当它们准备好后,Redis 会执行原子替换操作,使这个临时清单文件生效。为了避免在 AOF 重写重复失败和重试的情况下创建大量增量文件的问题,Redis 引入了 AOF 重写限制机制,以确保失败的 AOF 重写以越来越慢的速度重试。

#日志重写

# 重写流程
- 1. redis调用fork ,现在有父子两个进程 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
- 2. 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
- 3. 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
- 4. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

持久化总结(面试题)

两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定。

无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外, 用户还应该对持久化的文件进行备份(最好备份在多个不同地方)。

1、redis中持久化方案有几种?

RDB持久化 AOF持久化

2、redis默认是哪一种?

RDB持久化

3、如何触发RDB持久化?几种方式?有什么区别?

4种方式:BGSAVE SAVE 默认触发策略 shutdown(类似于ctrl+c)

4、AOF持久化与RDB持久化,它们之间的优缺点

RDB持久化

​ 优点:

文件紧凑:二进制格式,文件较小。

恢复速度快:直接加载数据,恢复效率高。

性能影响小:后台生成快照,对主线程影响较小。

​ 缺点:

数据安全性低:可能丢失最后一次快照后的数据。

不可读:二进制格式,无法直接查看或修改。

频繁快照影响性能:数据量大时,生成快照可能阻塞主线程。

AOF持久化

​ 优点:

数据安全性高:记录每次写操作,故障时最多丢失1秒数据(默认配置)。

可读性强:以文本形式存储,便于理解和修复。

灵活:支持多种同步策略(如每秒同步、每次写操作同步)。

​ 缺点:

文件较大:记录所有写操作,文件体积通常比RDB大。

恢复速度慢:需要重放所有操作,恢复时间较长。

性能开销:频繁写入可能影响性能,尤其是同步策略较严格时。

总结

AOF:适合对数据安全性要求高的场景,但文件大、恢复慢。

RDB:适合需要快速恢复和文件紧凑的场景,但可能丢失更多数据。

5、redis7.0之后的持久化方案:

RDB+AOF

6、redis7.0之前的重写机制和redis7.0之后的重写机制

Redis 7.0 之前:AOF 重写是单线程的,存在性能瓶颈和阻塞风险。

Redis 7.0 之后:引入多线程重写,显著提升了重写效率,降低了主进程负担和阻塞风险,整体性能更优。

posted @   Roxan  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
点击右上角即可分享
微信分享提示