Redis笔记第二篇—Redis高级
本文目录
Redis学习系列第二篇笔记,将学习Redis持久化、Redis事务、Redis删除策略、Redis配置文件以及高级数据类型。
1. Linux环境的Redis安装
1.1 从Redis源码编译安装
$tar -xvf redis-VERSION.tar.gz
$cd redis-VERSION
$make install
1.2 从指定端口号启动
#服务端从6380端口启动
$redis-server --port 6380
#客户端从6380端口连接
$redis-cli -p 6380
1.3 从配置文件启动
配置文件如下:
bind 127.0.0.1
port 6379
daemonize yes
按照守护进程方式启动logfile "6379.log"
日志文件的存储路径dir ./
上面的文件存储在哪儿
从配置文件启动:
$redis-server redis.conf
如果想启动多个Redis服务,只需稍微修改下配置文件即可。
2. Redis持久化
2.1 什么是持久化
- 比如意外断电。
利用永久性介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制叫做持久化。
为了防止数据丢失。
数据持久化的两种形式:
- 保存数据(快照)----RDB
- 保存操作过程(日志)----AOF
2.2 RDB
2.2.1 save
手动执行save
指令,会立即生成dump.rdb文件。
rdb相关配置
dbfilename dump.rdb
一般设置为dump-端口号.rdb,方便查看。dir
存储rdb文件的路径。rdbcompression yes
默认会压缩数据。rdbchecksum yes
默认会开启,数据校验,防止数据出错。
save指令工作原理
save指令会阻塞服务器,有可能造成长时间阻塞。不建议线上环境使用。
2.2.2 bgsave
后台会在某个时间执行保存操作。
执行过程:
客户端发送bgsave
指令,服务端返回给客户端Background saving started
消息,同时调用fork函数生成一个子进程来创建rdb文件。
注意:
bgsave命令对save的阻塞进行了优化,Redis内部所有涉及到RDB的操作都采用了bgsave的方式。
stop-writes-on-bgsave-error yes
后台存储时如果出现了错误,是否停止保存。默认是yes。
2.2.3 自动执行的保存
在conf文件内进行配置。
save seconds changes
- 满足特定时间内key的变化数量时即执行save操作。
2.2.4 两种保存方式对比
方式 | save | bgsave |
---|---|---|
读写 | 同步 | 异步 |
是否阻塞服务端 | 是 | 否 |
额外内存 | 否 | 是 |
启动新进程 | 否 | 是 |
2.2.5 RDB的特殊启动形式
- 全量复制
- 主从复制中详细讲解。
- 服务器运行过程中重启
debug reload
- 关闭服务器时指定保存数据
shutdown save
2.2.6 RDB的优缺点
优点:
- 内部是压缩的二进制文件,存储效率高。
- 存储的是某个时间点的快照,适合进行数据备份。
- 恢复数据比AOF快得多。
- 应用于每隔x小时进行一次备份,用于灾备。
缺点:
- 无法实时持久化,有丢失数据的可能。
- bgsave会牺牲性能。
- 可能多个版本的Redis之间不兼容。
2.3 AOF
AOF
, append only file, 目前是Redis实时持久化的主流方式。
- 记录操作过程。
2.3.1 AOF写数据的过程
AOF写数据的三种策略:
always
每次,数据零误差,性能较低。不建议使用。everysec
每秒,每秒将缓冲区的命令同步到AOF文件内,可能会丢失一秒的数据。Redis默认。no
系统控制,过程不可控。
在conf文件中启用AOF:
# 开启AOF, 默认是no
appendonly yes|no
# 配置AOF写数据策略
appendfsync always|everysec|no
# 配置AOF文件名
appendfilename filename
2.3.2 AOF重写
- 降低磁盘占用量
- 降低恢复时的数据量,提高恢复成功率。
重写规则:
- 进程内超时的数据不再写入。
- 忽略无效指令,set name 1, set name 2,只保留最后一条。
- 合并数据,lpush a 1, lpush a 2, 合并为lpush a 1 2。每条指令最多64个元素。
重写命令
手动重写:
bgrewriteaof
自动重写:
3. Redis事务
3.1 事务简介
Redis事务就是一个命令执行的队列,将一系列预定义的命令包装成一个整体。当执行时,一次性按照顺序执行,中间不会被打断。
3.2 事务基本操作
3.2.1 基本命令
事务的边界:
开头:multi
, 结尾:exec
。
取消事务:discard
3.2.2 事务的工作流程
3.2.3 事务的注意事项
- 如果输入的命令格式错误了怎么办?
如果有错误的指令,那么所有的操作都会被清除。
- 如果事务执行过程中出错了怎么办?
正确的命令会执行,错误的指令不会执行。
已经执行完毕的命令对应的数据不会自动回滚。
3.3 锁
基于特定条件的事务执行----锁。
对key添加监视锁,在exec之前如果key发生了变化,则不执行。
watch key1 [key2...]
unwatch
取消对所有key的监视。
注意:事务中不能watch。
3.4 分布式锁
如何避免最后一件商品被多个人买到?
分布式锁,类似于Java的同步代码块。
-
使用setnx设置一个公共锁
setnx lock-key value
有值则返回失败,没有值则返回设置成功。
可以理解为厕所钥匙。
操作完毕后通过
del
删除锁。
3.5 分布式锁的客户端问题
如果客户端拿到分布式锁后客户端宕机了怎么办?
给锁设置时效性。
expire lock-key second
pexpire lock-key 毫秒
4. Redis删除策略
已经过期的数据真的被删除了吗?
Redis数据有三种状态:
- XX:具有时效性的数据。
- -1:永久有效的数据。
- -2:过期的数据。
set和get的优先级比较高,del优先级低。过期的数据不一定被立刻删除,可能还会留一段时间。
4.1 数据删除策略
Redis内部会有一个expires空间,里面是[数据的内存地址-过期时间]
的形式。
删除策略:在CPU和内存之间找一个平衡。
4.1.1 定时删除
key的过期时间到了后定时器立刻去删除数据。
- 优点:省内存。
- 缺点:CPU压力大。
4.1.2 惰性删除
数据到期后不做处理,如果过期后有人访问这个数据,发现过期了,删除,返回不存在。
- 优点:省CPU。
- 缺点:费内存。
4.1.3 定期删除
启动时,将server.hz设置为10,每秒钟执行hz次serverCron()->databaseCron()->activeExpireCycle()。
activeExpireCycle()对每个expire空间逐一进行检测,每次执行(250/hz) ms
随机挑w个key进行检测,如果key超时,就删除。如果删除的量超过了w的25%,那么就会接着执行这个过程。
参数current_db用以记录activeExpireCycle()执行到了哪个db。
w取值由配置文件决定。ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
4.3 数据逐出算法
如果数据进入Redis时内存不够了怎么办?
临时删除一些数据,称为数据逐出/淘汰,这个策略称为逐出算法。
逐出算法可能会失败,如果失败了,会报错。
影响逐出算法的配置:
-
maxmemory
- 最大可用内存,默认是0,表示不受限制,一般设为50%以上。
-
maxmemory-samples
每次选取待删除数据的个数。 -
maxmemory-policy
- 逐出策略。
-
检查易失数据。(在expires里面删除数据)
- volatile-lru 最近使用时间离得最远的数据。(Recently)(早期Redis默认操作)
- volatile-lfu 最近使用次数最少。 (Frequently)
- volatile-ttl 挑选即将过期的数据。
- volatile-random 任意选择。
-
检测全库数据(在dict中删除数据)
- allkeys-lru
- allkeys-lfu
- allkeys-random
-
放弃数据逐出(Redis4.0开始的默认操作)
- no-enviction 禁止取出数据,可能会Out Of Memory。
配置文件:maxmemory-policy 逐出策略
注意:
查看INFO信息中的命中缓存次数及未命中次数,根据这个信息来调优。
5. redis.conf
服务器基础配置
-
设置服务器以守护进程的方式运行
daemonize yes|no
-
绑定主机地址(使之只能让这个地址来访问)
bind 127.0.0.1
-
设置端口
port 6379
-
设置数据库数量
databases 16
日志配置
-
指定日志级别
loglevel debug|verbose|notice|warning
-
日志记录文件名
logfile 端口号.log
服务端对客户端的配置
-
设定同一时间内最大客户端连接数,0代表无限制。
maxclients 0
-
客户端闲置最大时长,0代表不关闭。
timeout 300
多服务器快捷配置
-
导入并加载指定位置的配置文件,用于快捷创建Redis公共配置较多的Redis实例配置文件。
include /path/某个端口号.conf
6. Redis高级数据类型
高级数据类型更倾向于解决一种问题,应用面比较狭窄。
6.1 Bitmaps
6.1.1 基本操作
-
获取指定key上对应偏移量上的bit值
getbit key offset
-
设定指定key上对应偏移量的值
setbit key offset value
6.1.2 扩展操作
-
统计指定key中1的个数
bitcount key [start end]
-
对指定的key进行位运算
bitop op destKey key1 [key2 key3...]
-
destKey 是目标key,结果存进这个key里。
-
op有四种,交并非异或。
-
and 交(&&)
-
or 并 (||)
-
not 非 (!)
-
xor 异或 (^)
-
-
6.2 HyperLogLog
比如统计UV独立用户,HyperLogLog应用面更窄,用来做基数统计。
内部用了LogLog算法。
-
添加数据
pfadd key value1 [value2 value3...]
-
统计数据
pfcount key1 [key2 key3...]
-
合并数据
pfmerge destKey key1 [key2 key3...]
注意:
- 不存储数据,只记录数量。
- 数量是估算的,不保证精确。误差接近0.81%。
- 占用空间极小。使用最多12KB的内存。
- 合并后占用的就是12K,不管合并前这几个key占用多大。
6.3 GEO
求两个点的距离(关联关系)。
-
添加坐标点
geoadd key 横坐标1 纵坐标1 value1 [横坐标2 纵坐标2 value2 ...]
-
取出来坐标
geopos key value
-
计算距离
geodist key value1 value2 [m/km/ft/mi]
- 后面四个是单位。ft和mi分别是英尺和英里。
- 这是计算地球上两个坐标的。
- 横纵坐标就是经纬度。
-
根据坐标求范围内的数据
georadius key 经度 维度 半径 m/km/ft/mi [WITHCOORD WITHDIST WITHHASH] [COUNT count]
- WITHCOORD 结果带坐标
- WITHDIST 结果带距离
- WITHHASH 结果带哈希
- COUNT count 只展示最近的count个
-
根据点求范围内数据
geiradiusbymember key value 半径 单位 [后面的同上]
-
求坐标哈希值
geohash key value1 [value2...]