目录
引言
一、Reids工具与数据类型
(一)Reids工具
(二)Redis数据类型
1.String(字符串)
2.Hash(哈希)
3.List(列表)
4.Set(集合)
5.sorted set(有序集合)
二、基本命令
(一)字符串命令
1.set与get指令
2.getset指令
3.mset与mget指令
4.setnx指令
5.strlen指令
(二)哈希命令
1.hmset指令
2.hmget指令
3.Hdel指令
(三)列表命令
1.rpush指令
2.lrange指令
3.lpush指令
4.lindex指令
(四)集合命令
1.sadd与smembers指令
2.srem与smove指令
(五)有序集合命令
1.zadd指令
2.zrem指令
(六)其它命令
三、持久化
(一)redis持久化方式
1.RDB(Redis DataBase)方式
2.AOF (Append Only File) 持久化
(二)持久化过程
1..RDB持久化过程
2.AOF持久化过程
(三)开启持久化
1.开启RDB持久化
2.开启AOF持久化
(四)RDB与AOF的优缺点
1.RDB持久化方式的优点与缺点
2.AOF持久化方式的优点与缺点
四、性能管理
(一)内存碎片
(二)Redis内存碎片率
(三)Redis内存使用率
(四)Redis内部Key回收策略
总结
引言
Redis作为一种流行的内存数据存储系统,以其出色的性能、丰富的数据结构和持久化机制,被广泛应用于缓存、队列、计数器、排行榜等多种场景
一、Reids工具与数据类型
(一)Reids工具
Redis安装完毕后,会在安装目录的bin目录下生成几个工具文件
[root@localhost opt]#ll /usr/local/redis/bin/
总用量 32788
-rwxr-xr-x. 1 root root 4367640 4月 1 17:25 redis-benchmark
-rwxr-xr-x. 1 root root 8127288 4月 1 17:25 redis-check-aof
-rwxr-xr-x. 1 root root 8127288 4月 1 17:25 redis-check-rdb
-rwxr-xr-x. 1 root root 4808824 4月 1 17:25 redis-cli
lrwxrwxrwx. 1 root root 12 4月 1 17:25 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 8127288 4月 1 17:25 redis-serverredis-benchmark
#基准测试工具,用于模拟多个客户端同时对Redis服务器执行读写操作,
#以此来测试Redis服务器在各种场景下的性能表现。redis-check-aof
#持久化文件检查工具。在Redis使用AOF持久化时,这个工具可以帮助检查AOF文件是
#否损坏或存在一致性问题,并在必要时对其进行修复。redis-check-rdb
#RDB持久化文件检查工具。它可以检测RDB文件是否损坏,并在可能的情况下尝试修复。redis-cli
#redis-cli是Redis的命令行客户端,你可以通过它直接与Redis服务器进行交互,
#执行命令、查看数据、进行调试等工作。redis-sentinel
#高可用性解决方案之一,它负责监控Redis服务器实例的状态,并在主服务器发生故障时
#自动进行故障转移,确保服务的持续可用。redis-server
#执行程序,通过启动它来运行Redis数据库服务。
#通过配置文件(如redis.conf)来设置服务器的各种参数,而后通过此命令启动服务供客户端连接
(二)Redis数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
1.String(字符串)
string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
string类型是Redis最基本的数据类型,一个键最大能存储512MB。
存储方式:字符串数据类型的基本存储方式为:键-值
2.Hash(哈希)
Redis hash 是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
存储方式:哈希表的数据的基本存储方式为:键--字段--值
一个键可以对应多个字段与值:key filed1 value1 filed2 value2....
3.List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。
存储方式为:键--有序的值队列 。 key_name value0 value1....
4.Set(集合)
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)
存储方式:键--无序的不重复的成员。 key_name stringX stringY....
5.sorted set(有序集合)
Redis sorted set又称zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
存储方式:键-按分数排序的不重复的成员 。 key-scorel:stringX, score2:stringY...
二、基本命令
(一)字符串命令
命令 | 描述 |
Setnx | 只有在 key 不存在时设置 key 的值。 |
Getrange | 返回 key 中字符串值的子字符 |
Mset | 同时设置一个或多个 key-value 对。 |
Setex | 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。 |
SET | 设置指定 key 的值 |
Get | 获取指定 key 的值。 |
Getbit | 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。 |
Setbit | 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。 |
Decr | 将 key 中储存的数字值减一。 |
Decrby | key 所储存的值减去给定的减量值(decrement) 。 |
Strlen | 返回 key 所储存的字符串值的长度。 |
Msetnx | 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。 |
Incrby | 将 key 所储存的值加上给定的增量值(increment) 。 |
Incrbyfloat | 将 key 所储存的值加上给定的浮点增量值(increment) 。 |
Setrange | 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。 |
Psetex | 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。 |
Append | 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。 |
Getset | 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 |
Mget | 获取所有(一个或多个)给定 key 的值。 |
Incr | 将 key 中储存的数字值增一。 |
1.set与get指令
设定键值:set key_name value
获取键值:get key_name value
2.getset指令
getset指令用于赋予已存在的键新的值,并显示该键之前的值
基本语法为:getset key_name new_value
3.mset与mget指令
使用mset命令,可以同时为多个键指定值
基本语法为:mset key_name1 value1 key_name2 value2.....
使用mget命令,可以同时获取多个键的值
基本语法为:mget key_name1 key_name2.....
4.setnx指令
只有在key不存在时设置 key 的值。防止误将本来存在的键以及对应的值进行覆盖,造成数据丢失
5.strlen指令
该指令用于返回key所储存的字符串值的长度。
基本语法为:strlen key_name
(二)哈希命令
哈希列表的命令操作语法与字符串命令基本一致
命令 | 描述 |
Hmset | 同时将多个field-value(域-值)对设置到哈希表key中。 |
Hmget | 获取所有给定字段的值 |
Hset | 将哈希表key中字段field的值设为value。旧版本使用,较新版本与Hmset合并 |
Hgetall | 获取在哈希表中指定key的所有字段和值 |
Hget | 获取存储在哈希表中指定字段的值/td> |
Hexists | 查看哈希表key中,指定的字段是否存在。 |
Hincrby | 为哈希表key中的指定字段的整数值加上增量increment。 |
Hlen | 获取哈希表中字段的数量 |
Hdel | 删除一个或多个哈希表字段 |
Hvals | 获取哈希表中所有值 |
Hincrbyfloat | 为哈希表key中的指定字段的浮点数值加上增量increment。 |
Hkeys | 获取所有哈希表中的字段 |
Hsetnx | 只有在字段field不存在时,设置哈希表字段的值。 |
1.hmset指令
hmset 命令用于为哈希表中的字段赋值 。
如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。
如果字段已经存在于哈希表中,旧值将被覆盖。
基本语法为:hmest key_name filed1 value1 filed2 value2.....
2.hmget指令
hmget指令用来获取指定哈希表中给定字段的值
基本语法为hmget key_name filed1 [filed2....]
3.Hdel指令
删除哈希表中一个或多个字段
基本语法为:hdel key_name filed [filed....]
(三)列表命令
命令 | 描述 |
Lindex | 通过索引获取列表中的元素 |
Rpush | 在列表中添加一个或多个值 |
Lrange | 获取列表指定范围内的元素 |
Rpoplpush | 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
Blpop | 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹 出元素为止。 |
Brpop | 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可 弹出元素为止。 |
Brpoplpush | 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元 素会阻塞列表直到等待超时或发现可弹出元素为止。 |
Lrem | 移除列表元素 |
Llen | 获取列表长度 |
Ltrim | 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内 的元素都将被删除。 |
Lpop | 移出并获取列表的第一个元素 |
Lpushx | 将一个或多个值插入到已存在的列表头部 |
Linsert | 在列表的元素前或者后插入元素 |
Rpop | 移除并获取列表最后一个元素 |
Lset | 通过索引设置列表元素的值 |
Lpush | 将一个或多个值插入到列表头部 |
Rpushx | 为已存在的列表添加值 |
1.rpush指令
在列表中添加一个或多个值
基本语法为:rpush key_name value0 value1....
2.lrange指令
获取列表指定范围内的元素
基本语法为:lrange key_name start stop
3.lpush指令
将一个或多个值插入到列表头部
基本语法为:lpush key_name value0 value1....
4.lindex指令
通过索引获取列表中的元素
基本语法为:lindex key_name
(四)集合命令
命令 | 描述 |
Sunion | 返回所有给定集合的并集 |
Scard | 获取集合的成员数 |
Srandmember | 返回集合中一个或多个随机数 |
Smembers | 返回集合中的所有成员 |
Sinter | 返回给定所有集合的交集 |
Srem | 移除集合中一个或多个成员 |
Smove | 将 member 元素从 source 集合移动到 destination 集合 |
Sadd | 向集合添加一个或多个成员 |
Sismember | 判断 member 元素是否是集合 key 的成员 |
Sdiffstore | 返回给定所有集合的差集并存储在 destination 中 |
Sdiff | 返回给定所有集合的差集 |
Sscan | 迭代集合中的元素 |
Sinterstore | 返回给定所有集合的交集并存储在 destination 中 |
Sunionstore | 所有给定集合的并集存储在 destination 集合中 |
Spop | 移除并返回集合中的一个随机元素 |
1.sadd与smembers指令
sadd指令用于向集合添加多个成员
基本语法为:sadd key_name member [member ...]
smembers指令用于返回集合中的所有成员
基本语法为:smembers key_name
2.srem与smove指令
srem指令移除集合中一个或多个成员
基本语法为:srem key_name member [member ...]
smove指令用于将 member 元素从 source 集合移动到 destination 集合
基本语法为:smove source destination member
(五)有序集合命令
命令 | 描述 |
Zrevrank | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 序号从0开始,0为第一名 |
Zlexcount | 在有序集合中计算指定字典区间内成员数量 |
Zunionstore | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
Zremrangebyrank | 移除有序集合中给定的排名区间的所有成员 |
Zcard | 获取有序集合的成员数 |
Zrem | 移除有序集合中的一个或多个成员 |
Zinterstore | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 |
Zrank | 返回有序集合中指定成员的索引 |
Zincrby | 有序集合中对指定成员的分数加上增量 increment |
Zrangebyscore | 通过分数返回有序集合指定区间内的成员 |
Zrangebylex | 通过字典区间返回有序集合的成员 |
Zscore | 返回有序集中,成员的分数值 |
Zremrangebyscore | 移除有序集合中给定的分数区间的所有成员 |
Zscan | 迭代有序集合中的元素(包括元素成员和元素分值) |
Zrevrangebyscore | 返回有序集中指定分数区间内的成员,分数从高到低排序 |
Zremrangebylex | 移除有序集合中给定的字典区间的所有成员 |
Zrevrange | 返回有序集中指定区间内的成员,通过索引,分数从高到底 |
Zrange | 通过索引区间返回有序集合成指定区间内的成员 |
Zcount | 计算在有序集合中指定区间分数的成员数 |
Zadd | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
1.zadd指令
向有序集合添加一个或多个成员,或者更新已存在成员的分数
基本语法为:zadd key [NX|XX] [CH] [INCR] score member [score member ...]
NX:仅当成员不存在时添加成员XX:仅当成员存在时修改成员CH(changed):返回变更的成员数量
*默认返回新增的成员数量incr:累加分数
*选择incr时,只能操作一个分数-成员对score member:分数及成员名称
修改分数,使用incr选项
ch选项进行判断
2.zrem指令
zrem指令用于移除一个或多个成员
(六)其它命令
在redis当中还有许多其它的命令类型,如键(key) 命令、连接命令、 服务器命令、事务命令、 脚本命令等。
命令 | 描述 |
Flushdb | 清空当前数据库的所有键。 |
Flushall | 清空所有数据库的所有键。 |
Dbsize | 返回当前数据库中键的数目。 |
Type | 返回 key 所储存的值的类型。 |
Rename | 修改 key 的名称 |
Renamenx | 仅当 newkey 不存在时,将 key 改名为 newkey 。 |
Keys | 查找所有符合给定模式( pattern)的 key 。 |
DEL | 该命令用于在 key 存在时删除 key。 |
Move | 将当前数据库的 key 移动到给定的数据库 db 当中。 |
select | 切换库 |
本文只讲解了一些命令的基本使用方法,更详细的使用方法,可以参考官方文档的
官方文档:Commands | Redis
中文文档:redis命令手册
三、持久化
持久化是redis当中一个非常重要的功能,因为redis是一个基于内存的数据库,如果没有持久化,一旦关机或者重启,之前所有的数据都会丢失,这对一个数据库来说是非常致命的,持久化就是为解决这个问题而诞生了
(一)redis持久化方式
1.RDB(Redis DataBase)方式
RDB 是 Redis 默认的持久化方式,通过定期将内存中的数据以二进制的形式保存到磁盘上的RDB文件中,实现数据的持久化。这个过程可以通过Redis服务器自动触发(例如通过save
配置指令设置触发条件),也可以手动执行(通过bgrewriteaof
命令)。
RDB 文件是经过压缩的二进制文件,便于备份和恢复,同时加载速度快,但可能会丢失最后一次触发快照后到Redis宕机之间这段时间的数据。
2.AOF (Append Only File) 持久化
AOF 持久化则是将每一次对Redis服务器的写操作以Redis协议的格式追加到一个单独的日志文件(也就是AOF文件)中。相比RDB,AOF提供了更高的数据安全性,因为它的持久化粒度更细,理论上可以达到每一笔写操作都不会丢失的程度。
AOF 文件随着时间推移会不断增大,Redis 提供了AOF重写机制(bgrewriteaof
命令触发),用来压缩AOF文件,去掉无效的命令和合并连续的写操作。
AOF模式可以配置不同的同步策略,包括“每条命令都同步”、“每秒同步一次”和“在写入后至少等待指定数量的写操作再同步”。
(二)持久化过程
1..RDB持久化过程
1.1 触发RDB持久化
RDB持久化可以通过配置文件中的save指令自动触发,例如当满足一定条件(如过去5分钟内有10个key发生变化)时,Redis会自动执行一次快照操作。也可以通过手动执行SAVE或BGSAVE命令触发。SAVE命令会阻塞Redis服务器直到RDB文件创建完成,而BGSAVE命令会在后台异步执行持久化操作。
1. 2 父进程fork子进程
触发RDB持久化后,父进程会fork一个子进程,这个过程中父进程是阻塞的,不能接受其它的客户端命令
1.3 fork子进程完成
子进程负责将内存中的数据以二进制格式写入到RDB文件中,而主进程继续处理客户端请求。
1.4 子进程生成RDB文件
子进程将数据库中的数据转换为一系列序列化格式的键值对,然后写入磁盘文件。写入完成后,原来的RDB文件(如果存在)会被新的RDB文件替换。
1.5 子进程向父进程发送信号
子进程发送信号给父进程表示完成,父进程更新统计信息
2.AOF持久化过程
AOF持久化过程主要包括三个方面,命令追加、文件写入与文件同步、文件重写。
2.1 命令追加
每次客户端发送的写命令在Redis服务器中执行完成后,都会被以Redis协议格式追加到AOF缓冲区,而后统一写入到磁盘当中。主要是为了防止每次写命令都直接继续如磁盘,导致磁盘IO负载过高。造成瓶颈
2.2 文件写入与文件同步
启用AOF持久化后,Redis会将所有的写命令追加到AOF文件的末尾,可以配置不同的同步策略(always、everysec、no)来平衡数据安全性和性能。根据配置的同步策略,Redis会在命令执行完成后立即(always)、每秒(ecerysec)或在操作系统缓冲区满时(no)将命令刷入磁盘。
appendfsync always
设置为 always 表示每次Redis接收到写命令后,都会调用操作系统提供的 fsync() 或类似函数强制将AOF缓冲区的内容同步到磁盘中。这种方式能够确保每个写命令都立即被持久化,因此在Redis服务器崩溃的情况下,数据丢失的可能性最小。但是,频繁的同步操作会显著降低Redis的性能,因为它涉及到磁盘I/O操作,而磁盘I/O通常比内存操作要慢得多。
appendfsync everysec
这是Redis AOF的默认设置。在这种模式下,Redis会在每一秒结束时(大约每秒)将AOF缓冲区的内容同步到磁盘。这意味着在最坏情况下,如果Redis在同步后立即崩溃,可能会丢失这一秒内的写操作数据。然而,这种策略在保证数据相对安全的同时,也能保持较好的性能表现。
appendfsync no
当设置为 no 时,Redis不会主动调用同步操作,而是依赖操作系统的缓存策略来决定何时将AOF缓冲区内容刷到磁盘。这种配置下,Redis的写性能将会是最高的,因为它减少了与磁盘交互的频率。然而,这也意味着在服务器突然断电或无预警关机的情况下,可能丢失大量未写入磁盘的数据,因此数据安全性极低。
总结来说,appendfsync 的不同设置允许用户在数据安全性和性能之间进行权衡选择。在实际应用中,大多数场景推荐使用 appendfsync everysec 来达到较好的折衷效果。对于极度关注数据安全的应用,可以选择 appendfsync always,但在牺牲性能的前提下;而对于对性能要求极高且能接受一定数据丢失风险的应用,则可考虑 appendfsync no。
2.3 AOF重写
① 随着AOF文件的持续增长,Redis提供了AOF重写功能(可通过bgrewriteaof命令触发)来压缩AOF文件。
②Redis父进程首先判断当前是否存在正在执行bgsave/bgrewriteaof的子进程,如果存在则bgrewriteaof命令直接返回,如果存在 bgsave命令则等bgsave执行完成后再执行。父进程执行fork操作创建子进程,这个过程中父进程是阻塞的。
③父进程fork后,bgrewriteaof命令返回信息并不再阻塞父进程。而后将所有的命令写入缓冲区,而后根据同步方式追加到AOF文件的末尾,同时命令也进入重写缓冲区
④ 子进程首先生成新的AOF文件,而后向父进程发送信号,更新统计信息
⑤重写缓冲区会遍历内存中的数据构建最小化且有效的命令集合,将这些命令写入新的AOF文件。
新的AOF文件创建完成后,Redis会原子地用新的AOF文件替换旧文件。
重写的作用
将过期的数据不再写入文件,最后一条错误语句不写入
无效的命令不在写入,比如创建set key value,在后面又执行了del key。这样创建又删除的操作将自动被忽略
将多条命令合并,比如将sadd key_set value1, sadd key_set value2, saddkey_set value3,合并成sadd key_set value1 value2 value3
(三)开启持久化
1.开启RDB持久化
需要修改/etc/redis/6379.conf配置文件
save 900 1
#这是Redis的RDB快照保存策略,表示如果在过去的900秒(15分钟)内,至少有1个key的数据发生
#变化,Redis就会自动触发一次持久化操作,将当前内存中的数据生成一份RDB文件保存在磁盘上。save 300 10
#在过去的300秒(5分钟)内,至少有10个key的数据发生变化,Redis也将触发RDB持久化。save 60 10000
#在过去的60秒内,有10000个key的数据发生变化,Redis会执行RDB持久化。rdbcompression yes
#这个配置项表示在生成RDB文件时启用压缩功能,以减小RDB文件的体积,从而节省存储空间。
#启用压缩会影响RDB文件的生成速度和恢复速度,但通常压缩率较高,总体上利大于弊。dbfilename dump.rdb
#设置RDB文件的名称为dump.rdb。当Redis执行RDB持久化时,生成的文件会以这个名字存储。dir /var/lib/redis/6379
#设置RDB文件和AOF文件(如果开启的话)的存放目录为/var/lib/redis/6379。
#当Redis需要保存或加载持久化文件时,会在这个目录下查找相应文件。
2.开启AOF持久化
appendonly yes
#这行配置表示启用Redis的AOF持久化方式。appendfilename "appendonly.aof"
#设置AOF文件的名称为"appendonly.aof"。每次Redis执行写操作时,都会同步更新这个文件。# appendfsync always
appendfsync everysec
# appendfsync no
#选择同步策略aof-load-truncated yes
#是否忽略最后一条可能存在问题的指令
#表示当Redis启动时发现AOF文件已被截断或者损坏(非正常关闭导致),依然尝试加载该文件
#并继续运行,而不是直接报错退出。这对于应对一些意外情况非常有用,因为即使AOF文件不完
#整,也有可能部分恢复之前的数据状态
(四)RDB与AOF的优缺点
1.RDB持久化方式的优点与缺点
1.1 优点
性能优异:RDB持久化在生成快照时会对主线程进行fork操作创建一个子进程,子进程完成数据持久化工作,不会阻塞主线程处理客户端请求,故对Redis服务性能影响较小。
数据恢复快:RDB文件是二进制格式的,紧凑且易于加载,Redis在重启时可以直接读取RDB文件恢复数据,速度较快。
易于备份与迁移:RDB文件可以方便地用于备份或迁移到其他Redis服务器,而且由于文件体积相对较小,传输和存储成本较低。
1.2 缺点
数据安全性略低:在发生故障时,最后一次持久化和故障之间的时间段内的数据可能丢失。如果RDB文件生成周期较长,潜在的数据丢失风险就越大。
资源消耗:虽然fork操作在现代操作系统中代价相对较小,但对于大容量数据的Redis实例,fork操作仍可能引起暂时的性能下降和较大的内存开销。
不适合大型在线更新场景:如果应用中有大量的写入操作,且需要非常严格的实时持久化保证,RDB可能不是最佳选择,因为RDB是以周期性快照方式进行持久化的。
2.AOF持久化方式的优点与缺点
2.1 优点
数据安全性高:AOF持久化以命令追加的方式记录,可以设置不同的同步策略(如appendfsync everysec),接近于实时持久化,大大降低了数据丢失的可能性。
容错性强:即便AOF文件损坏,Redis提供了redis-check-aof工具进行修复,可以从中找回大部分数据。
重写功能:缩小文件体积,减少磁盘的空间占用,优化存储效率,提示性能。
精确恢复:AOF记录了所有写操作,因此在Redis重启时可以按照写入命令的顺序逐条执行,精确恢复数据状态。
2.2 缺点
性能损耗:根据不同的同步策略,AOF可能需要频繁地将命令写入硬盘,尤其在always同步策略下,对性能影响较大。
文件体积增长较快:随着写操作的增多,AOF文件会逐渐变大,尽管Redis提供了AOF重写功能(bgrewriteaof)来压缩文件,但仍然需要一定的存储空间。
恢复速度相对较慢:AOF文件在Redis重启时需要逐条执行命令来恢复数据,相比于直接加载RDB文件,恢复速度较慢。
四、性能管理
首先了解一下什么是内存碎片
(一)内存碎片
内存碎片(Memory Fragmentation)是指在计算机内存管理中,由于分配和回收内存空间而导致的无法连续使用的内存区域。内存碎片分为两类:
内部碎片(Internal Fragmentation): 当内存分配器为一个程序分配内存时,分配的内存块可能会大于程序实际需要的空间。例如,分配器可能按照固定大小或者页大小分配内存,即使请求的内存小于分配单位大小,也会分配一个完整的单位。这部分分配给程序但未被使用的内存空间就是内部碎片。内部碎片不可用于分配给其他程序,即使它在物理上是可用的。
外部碎片(External Fragmentation): 随着程序的运行和内存的分配与回收,内存中可能会形成许多小的、不连续的空闲区域,虽然这些区域的总和足以满足一个大的内存请求,但由于它们彼此不连续,所以不能被分配给需要大块连续内存空间的程序。这些无法合并使用的空闲区域构成了外部碎片。
内存碎片的存在会降低内存利用率,尤其是在连续内存分配策略中,严重的内存碎片可能导致即使还有足够的内存总量,也无法分配给新的请求,这在资源有限的系统中尤为不利。现代内存管理系统通常会采用各种策略来减少或避免内存碎片,如动态内存分配算法、分页系统和垃圾回收机制等。
(二)Redis内存碎片率
内存碎片率是衡量Redis内存利用率的一个关键指标,表示Redis在分配和回收内存过程中未使用的内存空间与已使用内存之间的比例。公式通常定义为 mem_fragmentation_ratio = used_memory_rss / used_memory,
其中
used_memory_rss 是Redis进程在操作系统层面所占用的实际物理内存大小。
used_memory 是Redis为了存储数据所分配的内存总量。
碎片率较高意味着Redis分配了大量的内存但并未完全有效利用,可能是由于Redis在分配内存时倾向于分配整块空间,当存储的数据大小变化时,原有的内存块未被完全填满,形成了碎片。长期的碎片积累可能导致Redis内存效率低下,甚至在达到最大内存限制(maxmemory 设置)时因内存不足引发 OOM 错误
跟踪内存碎片率对理解Redis实例的资源性能是非常重要的:
内存碎片率稍大于1是合理的,这个值表示内存碎片率比较低,也说明 Redis 没有发生内存交换
内存碎片率超过1.5,说明Redis消耗了实际需要物理内存的150%,其中50%是内存碎片率。需要在redis-cli工具上输入shutdown save 命令,让 Redis 数据库执行保存操作并关闭 Redis 服务,再重启服务器。
内存碎片率低于1的,说明Redis内存分配超出了物理内存,操作系统正在进行内存交换。需要增加可用物理内存或减少 Redis 内存占用。
(三)Redis内存使用率
内存使用率是指Redis已经使用的内存占总内存(或分配给Redis的最大内存)的比例。虽然Redis本身并不直接显示内存使用率这个百分比,但我们可以通过计算得出大致的使用情况。例如,如果你知道Redis实例的最大可用内存(即maxmemory设定值),则内存使用率可近似表示为 used_memory / maxmemory * 100%
可以使用 info memor命令查看内存使用情况
redis实例的内存使用率超过可用最大内存,操作系统将开始进行内存与swap空间交换
避免内存交换发生的方法:
针对缓存数据大小选择安装 Redis 实例
尽可能的使用Hash数据结构存储
设置key的过期时间
(四)Redis内部Key回收策略
为了管理内存资源并防止内存溢出,Redis提供了多种数据淘汰策略( eviction policies ),当内存达到maxmemory限制时,Redis会根据选择的策略自动删除部分Key以释放内存空间
开启key回收,取消配置文件(通常为/etc/redis/6379.conf)中598行的注释,开启key回收
volatile-lru:仅针对设置了过期时间(TTL)的Key,按照最近最少使用(LRU)算法剔除最久未访问的Key。
allkeys-lru:对所有Key均采用LRU算法剔除。
volatile-ttl:剔除即将过期的Key中,剩余生存时间(TTL)最短的Key。
noeviction:不主动删除任何Key,但在尝试写入新的数据时,如果内存已满,则拒绝执行会导致内存增长的命令。
volatile-random 和 allkeys-random:随机剔除具有过期时间或所有Key中的某个Key。
除了上述策略外,管理员还可以通过手动执行 DEL 或 KEYS 指令配合 UNLINK (非阻塞版本的删除指令)来删除特定Key,以减少内存占用。
总结
在生产环境中,redis是一个处理大批量数据的一个好帮手,与此同时,也需要注意数据的完整性,比如提取大批量的日志信息,可以使用redis
本章的重点内容
1.持久化
理解持久化的过程,需要熟练掌握持久化的操作过程,以及数据流向,可以很好的处理持久化的文件,保存数据,保证数据的完整性。
2.Key回收策略
了解key回收的策略,根据情况,选择不同的回收策略,释放内存空间,提高redis性能。
更多的详细解释,可以查看redis的官网进行查看
redis官方文档:Redis | The Real-time Data Platform
redis中文网:Redis中文网