一篇文章带你了解redis
1.NoSql
NoSQL:即 Not-Only SQL( 泛指非关系型的数据库),作为关系型数据库的补充。
作用:应对基于海量用户和海量数据前提下的数据处理问题
特征:
-
List item
-
可扩容,可伸缩
-
大数据量下高性能
-
灵活的数据模型
-
高可用
常见 Nosql 数据库:
- Redis
- memcache
- HBase
- MongoDB
2.redis基础
2.1 redis的介绍
概念:Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库。
特征:
- 数据间没有必然的关联关系
- 内部采用单线程机制进行工作(新版本是多线程)
- 高性能。官方提供测试数据,50个并发执行100000 个请求,读的速度是110000 次/s,写的速度是81000次/s。
- 多数据类型支持
- 字符串类型 string
- 列表类型 list
- 散列类型 hash
- 集合类型 set
- 有序集合类型 sorted_set
- 持久化支持。可以进行数据灾难恢复
2.2 redis的应用
- 为热点数据加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等
- 任务队列,如秒杀、抢购、购票排队等
- 即时信息查询,如各位排行榜、各类网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设备信号等
- 时效性信息控制,如验证码控制、投票控制等
- 分布式数据共享,如分布式集群架构中的 session 分离
- 消息队列
- 分布式锁
2.3 redis的下载和安装
windows版
下载地址:https://github.com/microsoftarchive/redis/tags
linux版
2.6 redis配置
2.6.1 服务器基础配置
设置服务器以守护进程的方式运行
daemonize yes|no
绑定主机地址
bind 127.0.0.1
设置服务器端口号
port 6379
设置数据库数量
databases 16
2.6.2 日志配置
设置服务器以指定日志记录级别
loglevel debug|verbose|notice|warning
日志记录文件名
logfile 端口号.log
注意:日志级别开发期设置为verbose即可,生产环境中配置为notice,简化日志输出量,降低写日志IO的频度
2.6.3 客户端配置
设置同一时间最大客户端连接数,默认无限制。当客户端连接到达上限,Redis会关闭新的连接
maxclients 0
客户端闲置等待最大时长,达到最大值后关闭连接。如需关闭该功能,设置为 0
timeout 300
2.6.4 多服务器快捷配置
导入并加载指定配置文件信息,用于快速创建redis公共配置较多的redis实例配置文件,便于维护
include /path/server-端口号.conf
2.5redis基本操作
1.信息添加
功能:设置 key,value 数据
命令:
set key value
用例
set name xiaoming
2.信息查询
功能:根据 key 查询对应的 value,如果不存在,返回空(nil)
命令
get key
用例
get name
3.清屏
功能:清除屏幕中的信息
命令:
clear
4.帮助
功能:获取命令帮助文档,获取组中所有命令信息名称
help 命令名称
help @组名
5.退出客户端
功能:退出客户端
命令
quite
exit
<ESC>
3.数据类型
redis 数据存储格式
redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形式存储
数据类型指的是存储的数据的类型,也就是 value 部分的类型,key 部分永远都是字符串
3.1 String
存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
存储数据的格式:一个存储空间保存一个数据
存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用
3.1.1 基本操作
1.增
添加/修改数据
set key value
添加/修改多个数据(如果插入过多的数据的时候,这个操作是比较快的)
mset key1 value1 key2 value2 …
2.删
删除数据
del key
3.改
追加信息到原始信息后部(如果原始信息存在就追加,否则新建)
append key value
4.查
获取数据
get key
获取多个数据
mget key1 key2 …
获取数据字符个数(字符串长度)
strlen key
3.1.2 扩展操作
- string 作为数值操作
- string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算。
- redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发
带来的数据影响。 - 注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围,将报错。
9223372036854775807(java中long型数据最大值,Long.MAX_VALUE)
设置数值数据增加指定范围的值
incr key
incrby key increment
incrbyfloat key increment
设置数值数据减少指定范围的值
decr key
decrby key increment
- redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作
设置数据具有指定的生命周期
setex key seconds value
psetex key milliseconds value
3.1.3 注意事项
- 数据操作不成功的反馈与数据正常操作之间的差异
- 表示运行结果是否成功
- (integer) 0 → false 失败
- (integer) 1 → true 成功
- 表示运行结果值
- (integer) 3 → 3 3个
- (integer) 1 → 1 1个
- 表示运行结果是否成功
- 数据未获取到
- (nil)等同于null
- 数据最大存储量
- 512MB
- 数值计算最大范围(java中的long的最大值)
- 9223372036854775807
3.1.4业务场景
1.主页高频访问信息显示控制,例如新浪微博大V主页显示粉丝数与微博数量
3.2 list(LinkedList)
- 数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
- 需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
- list类型:保存多个数据,底层使用双向链表存储结构实现
3.2.1 基本操作
添加/修改数据
lpush key value1 [value2] ……
rpush key value1 [value2] ……
获取数据
lrange key start stop
lindex key index
llen key
获取并移除数据
lpop key
rpop key
3.2.2扩展操作
规定时间内获取并移除数据
blpop key1 [key2] timeout
brpop key1 [key2] timeout
brpoplpush source destination timeout
移除指定数据
lrem key count value
3.2.3注意事项
- list中保存的数据都是string类型的,数据总容量是有限的,最多2的31次方 个元素 (4294967295)。
- list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作
- 获取全部数据操作结束索引设置为-1
- list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载
3.2.4应用场景
3.3 set(HashSet)
- 新的存储需求:存储大量的数据,在查询方面提供更高的效率
- 需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
- set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的
3.3.1基本操作
添加数据
sadd key member1 [member2]
获取全部数据
smembers key
删除数据
srem key member1 [member2]
获取集合数据总量
scard key
随机获取集合中指定数量的数据
srandmember key [count]
随机获取集合中的某个数据并将该数据移出集合
spop key [count]
判断集合中是否包含指定数据
sismember key member
3.3.2扩展操作
求两个集合的交、并、差集
sinter key1 [key2]
sunion key1 [key2]
sdiff key1 [key2]
求两个集合的交、并、差集并存储到指定集合中
sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2]
将指定数据从原始集合中移动到目标集合中
smove source destination member
3.3.3注意事项
- set 类型不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份
- set 虽然与hash的存储结构相同,但是无法启用hash中存储值的空间
3.3.4 应用场景
3.4 sorted_set(TreeSet)
- 新的存储需求:数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式
- 需要的存储结构:新的存储模型,可以保存可排序的数据
- sorted_set类型:在set的存储结构基础上添加可排序字段
3.4.1基本操作
添加数据
zadd key score1 member1 [score2 member2]
获取全部数据
zrange key start stop [WITHSCORES]
zrevrange key start stop [WITHSCORES]
删除数据
zrem key member [member ...]
按条件获取数据
zrangebyscore key min max [WITHSCORES] [LIMIT]
zrevrangebyscore key max min [WITHSCORES]
条件删除数据
zremrangebyrank key start stop
zremrangebyscore key min max
获取集合数据总量
zcard key
zcount key min max
集合交、并操作
zinterstore destination numkeys key [key ...]
zunionstore destination numkeys key [key ...]
min与max用于限定搜索查询的条件
start与stop用于限定查询范围,作用于索引,表示开始和结束索引
offset与count用于限定查询范围,作用于查询结果,表示开始位置和数据总量
3.4.2 扩展操作
获取数据对应的索引(排名)
zrank key member
zrevrank key member
score值获取与修改
zscore key member
zincrby key increment member
3.4.3注意事项
- score保存的数据存储空间是64位,如果是整数范围是-9007199254740992~9007199254740992
- score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重
- sorted_set 底层存储还是基于set结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果
3.4.4应用场景
3.5 hash(HashMap)
新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
需要的存储结构:一个存储空间保存多个键值对数据
hash类型:底层使用哈希表结构实现数据存储
hash存储结构优化
- 如果field数量较少,存储结构优化为类数组结构
- 如果field数量较多,存储结构使用HashMap结构
3.5.1 基本操作
增
添加/修改数据
hset key field value
添加/修改多个数据
hmset key field1 value1 field2 value2 …
删
删除数据
hdel key field1 [field2]
查
获取数据
hget key field
hgetall key
获取多个数据
hmget key field1 field2 …
获取哈希表中是否存在指定的字段
hexists key field
获取哈希表中字段的数量
hlen key
3.5.2 扩展操作
获取哈希表中所有的字段名或字段值
hkeys key
hvals key
设置指定字段的数值数据增加指定范围的值
hincrby key field increment
hincrbyfloat key field increment
3.5.3 注意事项
- hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到,对应的值为(nil)
- 每个 hash 可以存储 2的32次方-1个键值对
- hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
- hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就很会低,有可能成为数据访问瓶颈。
3.5.4应用场景
redis高级数据类型
3.6 Bitmaps
3.6.1 基本操作
获取指定key对应偏移量上的bit值
getbit key offset
设置指定key对应偏移量上的bit值,value只能是1或0
setbit key offset value
3.6.2 扩展操作
对指定key按位进行交、并、非、异或操作,并将结果保存到destKey中
bitop op destKey key1 [key2...]
and:交
or:并
not:非
xor:异或
统计指定key中1的数量
bitcount key [start end]
3.6.3场景
3.7 HyperLogLog
3.7.1基本操作
添加数据
pfadd key element [element ...]
统计数据
pfcount key [key ...]
合并数据
pfmerge destkey sourcekey [sourcekey...]
3.8 GEO
3.8.1基本操作
添加坐标点
geoadd key longitude latitude member [longitude latitude member ...]
获取坐标点
geopos key member [member ...]
计算坐标点距离
geodist key member1 member2 [unit]
添加坐标点
georadius key longitude latitude radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]
获取坐标点
georadiusbymember key member radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]
计算经纬度
geohash key member [member ...]
4. redis通用命令
4.1 key通用指令
key是一个字符串,通过key获取redis中保存的数据
4.1.1key基本操作
删除指定key
del key
获取key是否存在
exists key
获取key的类型
type key
4.1.2 key 扩展操作(时效性控制)
为指定key设置有效期
expire key seconds
pexpire key milliseconds
expireat key timestamp
pexpireat key milliseconds-timestamp
获取key的有效时间
ttl key
pttl key
切换key从时效性转换为永久性
persist key
4.1.3 key 扩展操作(查询模式)
查询key
keys pattern
4.1.4 key 其他操作
为key改名
rename key newKey
renamenx key newKey
对所有key排序
sort
其他key通用操作
help @generic
4.2 数据库通用指令
key 的重复问题
- key是由程序员定义的
- redis在使用过程中,伴随着操作数据量的增加,会出现大量的数据以及对应的key
- 数据不区分种类、类别混杂在一起,极易出现重复或冲突
解决方案
- redis为每个服务提供有16个数据库,编号从0到15
- 每个数据库之间的数据相互独立
4.2.1 db基本操作
切换数据库
select index
其他操作
quite
ping
echo message
4.2.2 db相关操作
数据移动
move key dbIndex
数据清除
dbsize 用于查看当前数据库中key的数量。
flushdb 清空当前数据库中的所有 key
flushall 清空整个 Redis 服务器的数据(删除所有数据库的所有 key )
5.redis持久化
什么是持久化?
利用永久性存储介质(硬盘,磁盘等)将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。
为什么要进行持久化?
防止数据的意外丢失,确保数据安全性。
持久化过程保存什么?
将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据。
将数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程。
5.1 RDB
5.1.1 save方式
- 谁:redis操作者(用户)
- 什么时间:即时(随时进行)
- 干什么事情:保存数据
命令
RDB启动方式 —— save指令
作用:手动执行一次保存操作
save
save指令相关配置?
dbfilename 文件名.rdb
说明:设置本地数据库文件名,默认值为 dump.rdb
经验:通常设置为dump-端口号.rdb
dir 路径字符串
说明:设置存储.rdb文件的路径
经验:通常设置成存储空间较大的目录中,目录名称data
rdbcompression yes
说明:设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩
经验:通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大(巨大)
rdbchecksum yes
说明:设置是否进行RDB文件格式校验,该校验过程在写文件和读文件过程均进行
经验:通常默认为开启状态,如果设置为no,可以节约读写性过程约10%时间消耗,但是存储一定的数据损坏风险
save指令原理
注意:save指令的执行会阻塞当前Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用。
5.1.2 bgsave指令
数据量过大,单线程执行方式造成效率过低如何处理?
后台执行
- 谁:redis操作者(用户)发起指令;redis服务器控制指令执行
- 什么时间:即时(发起);合理的时间(执行)
- 干什么事情:保存数据
命令
作用:手动启动后台保存操作,但不是立即执行
bgsave
指令相关配置
dbfilename dump.rdb
dir
rdbcompression yes
rdbchecksum yes
stop-writes-on-bgsave-error yes
说明:后台存储过程中如果出现错误现象,是否停止保存操作
经验:通常默认为开启状态
原理
bgsave命令是针对save阻塞问题做的优化。Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用。
5.1.3 save的另一种方式
反复执行保存指令,忘记了怎么办?不知道数据产生了多少变化,何时保存?
自动执行
- 谁:redis服务器发起指令(基于条件)
- 什么时间:满足条件
- 干什么事情:保存数据
命令
作用:满足限定时间范围内key的变化数量达到指定数量即进行持久化
save second changes
参数
second:监控时间范围
changes:监控key的变化量
位置
在conf文件中进行配置
示例
save 900 1
save 300 10
save 60 10000
配置
dbfilename dump.rdb
dir
rdbcompression yes
rdbchecksum yes
指令原理
注意:
- save配置要根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的。
- save配置中对于second与changes设置通常具有互补对应关系,尽量不要设置成包含性关系。
- save配置启动后执行的是bgsave操作
5.1.4 RDB其他内容
三种方式对比
rdb特殊启动形式
服务器运行过程中重启
debug reload
关闭服务器时指定保存数据
shutdown save
注意:默认情况下执行shutdown命令时,自动执行bgsave(如果没有开启AOF持久化功能)
RDB优点
- RDB是一个紧凑压缩的二进制文件,存储效率较高
- RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据备份,全量复制等场景
- RDB恢复数据的速度要比AOF快很多
- 应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复。
RDB缺点
- RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据。
- bgsave指令每次运行要执行fork操作创建子进程,要牺牲掉一些性能。
- Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象。
- 大数据量下的IO性能较低。
- 存储数据量较大,效率较低基于快照思想,每次读写都是全部数据,当数据量巨大时,效率非常低。
解决思路
- 不写全数据,仅记录部分数据
- 降低区分数据是否改变的难度,改记录数据为记录操作过程
- 对所有操作均进行记录,排除丢失数据的风险
5.2 AOF
AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程。
AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式
5.2.1AOF原理
5.2.2 AOF写数据三种策略(appendfsync)
- always(每次)
- 每次写入操作均同步到AOF文件中,数据零误差,性能较低。
- everysec(每秒)
- 每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高,在系统突然宕机的情况下丢失1秒内的数据。
- no(系统控制)
- 由操作系统控制每次同步到AOF文件的周期,整体过程不可控。
5.2.3 AOF配置
配置
appendonly yes|no
作用:是否开启AOF持久化功能,默认为不开启状态
appendfsync always|everysec|no
作用:AOF写数据策略
appendfilename filename
作用:AOF持久化文件名,默认文件名未appendonly.aof,建议配置为appendonly-端口号.aof
dir 路径地址
作用:AOF持久化文件保存路径,与RDB持久化文件保持一致即可
5.2.4 AOF重写
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制压缩文件体积。AOF文件重写是将Redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将对同一个数据的若干个条命令执行结果转化成最终结果数据对应的指令进行记录。
AOF重写作用?
- 降低磁盘占用量,提高磁盘利用率
- 提高持久化效率,降低持久化写时间,提高IO性能
- 降低数据恢复用时,提高数据恢复效率
AOF重写规则?
- 进程内已超时的数据不再写入文件
- 忽略无效指令,重写时使用进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令
- 如del key1、 hdel key2、srem key3、set key4 111、set key4 222等
- 对同一数据的多条写命令合并为一条命令
- 如lpush list1 a、lpush list1 b、 lpush list1 c 可以转化为:lpush list1 a b c。
- 为防止数据量过大造成客户端缓冲区溢出,对list、set、hash、zset等类型,每条指令最多写入64个元素
5.2.4.1 重写命令
手动重写
bgrewriteaof
自动重写触发条件设置
auto-aof-rewrite-min-size size
auto-aof-rewrite-percentage percentage
自动重写触发比对参数( 运行指令info Persistence获取具体信息 )
aof_current_size
aof_base_size
自动重写触发条件
5.2.4.2 重写原理
5.2.4.3工作流程
5.2.5 AOF缓冲区同步文件策略
由参数appendfsync控制,系统调用write和fsync说明:
- write操作会触发延迟写(delayed write)机制,Linux在内核提供页缓冲区用来提高硬盘IO性能。write操作在写入系统缓冲区后直接返回。同步硬盘操作依赖于系统调度机制,列如:缓冲区页空间写满或达到特定时间周期。同步文件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
- fsync针对单个文件操作(比如AOF文件),做强制硬盘同步,fsync将阻塞知道写入硬盘完成后返回,保证了数据持久化。
- 除了write、fsync、Linx还提供了sync、fdatasync操作,具体API说明参见:
5.3 RDB与AOF区别
5.4 RDB与AOF的选择之惑
-
对数据非常敏感,建议使用默认的AOF持久化方案
- AOF持久化策略使用everysecond,每秒钟fsync一次。该策略redis仍可以保持很好的处理性能,当出现问题时,最多丢失0-1秒内的数据。
- 注意:由于AOF文件存储体积较大,且恢复速度较慢
-
数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人员手工维护的),且恢复速度较快,阶段点数据恢复通常采用RDB方案
- 注意:利用RDB实现紧凑的数据持久化会使Redis降的很低,慎重总结:
-
综合比对
- RDB与AOF的选择实际上是在做一种权衡,每种都有利有弊
- 如不能承受数分钟以内的数据丢失,对业务数据非常敏感,选用AOF
- 如能承受数分钟以内的数据丢失,且追求大数据集的恢复速度,选用RDB
- 灾难恢复选用RDB
- 双保险策略,同时开启 RDB 和 AOF,重启后,Redis优先使用 AOF 来恢复数据,降低丢失数据的量
5.5 持久化应用场景
6.redis事务
什么是事务?
Redis执行指令过程中,多条连续执行的指令被干扰,打断,插队。
redis事务就是一个命令执行的队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰。
一个队列中,一次性、顺序性、排他性的执行一系列命令
6.1事务基本操作
开启事务
作用:设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中
multi
执行事务
作用:设定事务的结束位置,同时执行事务。与multi成对出现,成对使用
exec
取消事务
作用:终止当前事务的定义,发生在multi之后,exec之前
discard
加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行
注意事项:
定义事务的过程中,命令格式输入错误怎么办?
- 语法错误
- 指命令书写格式有误
- 处理结果
- 如果定义的事务中所包含的命令存在语法错误,整体事务中所有命令均不会执行。包括那些语法正确的命令
定义事务的过程中,命令执行出现错误怎么办?
- 运行错误
- 指命令格式正确,但是无法正确的执行。例如对list进行incr操作
- 处理结果
- 能够正确运行的命令会执行,运行错误的命令不会被执行
注意:已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚。
手动进行事务回滚
- 记录操作过程中被影响的数据之前的状态
- 单数据:string
- 多数据:hash、list、set、zset
- 设置指令恢复所有的被修改的项
- 单数据:直接set(注意周边属性,例如时效)
- 多数据:修改对应值或整体克隆复制
6.2锁
6.2.1基于特定条件的事务执行——锁
对 key 添加监视锁,在执行exec前如果key发生了变化,终止事务执行
watch key1 [key2……]
取消对所有 key 的监视
unwatch
6.2.2基于特定条件的事务执行——分布式锁
使用 setnx 设置一个公共锁
setnx lock-key value
利用setnx命令的返回值特征,有值则返回设置失败,无值则返回设置成功
- 对于返回设置成功的,拥有控制权,进行下一步的具体业务操作
- 对于返回设置失败的,不具有控制权,排队或等待
操作完毕通过del操作释放锁
6.2.3 基于特定条件的事务执行——分布式锁改良
使用 expire 为锁key添加时间限定,到时不释放,放弃锁
expire lock-key second
pexpire lock-key milliseconds
由于操作通常都是微秒或毫秒级,因此该锁定时间不宜设置过大。具体时间需要业务测试后确认。
- 例如:持有锁的操作最长执行时间127ms,最短执行时间7ms。
- 测试百万次最长执行时间对应命令的最大耗时,测试百万次网络延迟平均耗时
- 锁时间设定推荐:最大耗时120%+平均网络延迟110%
- 如果业务最大耗时<<网络平均延迟,通常为2个数量级,取其中单个耗时较长即可
6.3 redssion
7.删除策略
7.1过期数据
Redis中的数据特征:
- Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态
- XX :具有时效性的数据
- -1 :永久有效的数据
- -2 :已经过期的数据 或 被删除的数据 或 未定义的数据
7.2数据删除策略
在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能的下降,甚至引发服务器宕机或内存泄露。
7.2.1 定时删除
- 创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
- 优点:节约内存,到时就删除,快速释放掉不必要的内存占用
- 缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
- 总结:用处理器性能换取存储空间(拿时间换空间)
- 惰性删除
- 数据到达过期时间,不做处理。等下次访问该数据时
- 如果未过期,返回数据
- 发现已过期,删除,返回不存在
- 优点:节约CPU性能,发现必须删除的时候才删除
- 缺点:内存压力很大,出现长期占用内存的数据
- 总结:用存储空间换取处理器性能 expireIfNeeded() (拿时间换空间)
- 定期删除
- 周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度
- 特点1:CPU性能占用设置有峰值,检测频度可自定义设置
- 特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理
- 总结:周期性抽查存储空间expireIfNeeded()(随机抽查,重点抽查)
对比
7.3逐出算法
影响数据逐出的相关配置
最大可使用内存
占用物理内存的比例,默认值为0,表示不限制。生产环境中根据需求设定,通常设置在50%以上。
maxmemory
每次选取待删除数据的个数
选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据
maxmemory-samples
删除策略
达到最大内存后的,对被挑选出来的数据进行删除的策略
maxmemory-policy
影响数据逐出的相关配置
- 检测易失数据(可能会过期的数据集server.db[i].expires )
① volatile-lru:挑选最近最少使用的数据淘汰
② volatile-lfu:挑选最近使用次数最少的数据淘汰
③ volatile-ttl:挑选将要过期的数据淘汰
④ volatile-random:任意选择数据淘汰 - 检测全库数据(所有数据集server.db[i].dict )
⑤ allkeys-lru:挑选最近最少使用的数据淘汰
⑥ allkeys-lfu:挑选最近使用次数最少的数据淘汰
⑦ allkeys-random:任意选择数据淘汰 - 放弃数据驱逐
⑧ no-enviction(驱逐):禁止驱逐数据(redis4.0中默认策略),会引发错误OOM(Out Of Memory)
数据逐出策略配置依据
使用INFO命令输出监控信息,查询缓存 hit 和 miss 的次数,根据业务需求调优Redis配置