花了一周左右,全面的学习redis的知识,并记录学习笔记
原文请访问我的技术博客番茄技术小栈
redis初识
导学
盛赞redis
- 高性能key-value服务器
- 多种数据结构
- 丰富的功能
- 高可用的分布式支持
redis初识
定义
Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库
特性
- 开源
- 多种数据结构
- 基于键值的存储服务系统
- 高性能,功能服务
redis的前世今生
谁在使用redis
- github
- 微博
- Stack Overflow
- 阿里巴巴
- 百度
- 美团
- 搜狐
- ......
redis特性目录
- 速度快
- 持久化
- 多种数据结构
- 支持多种编程语言
- 功能丰富
- 简单:代码短小精悍
- 主从复制
- 高可用、分布式
特性1:速度快
10w QPS
原因
- 数据存在内存
- c语言编写
- 单线程编写
特性2:持久化
- redis所有的数据保存在内存中,对数据的更新将异步地保存到磁盘上
特性3:数据结构
特性4:多语言客户端
特性5:功能丰富
- 发布订阅
- lua脚本
- 事务
- pipeline
特性6:简单
- 23000行代码实现核心功能
- 不依赖外部库
- 单线程模型
特性7:复制
特性8: 高可用
- redis-sentinel支持高可用
- 分布式 redis-cluster支持分布式
redis典型使用场景
- 缓存系统
- 计数器
- 消息队列系统
- 排行榜
- 社交网络
- 实时系统
redis三种启动方式
redis安装(mac&linux)
$ wget http://download.redis.io/releases/redis-4.0.8.tar.gz
$ tar xzf redis-4.0.8.tar.gz
$ cd redis-4.0.8
$ make
复制代码
redis可执行文件说明
命令名 | 命令说明 |
---|---|
redis-server | redis服务器 |
redis-cli | redis命令行客户端 |
redis-benchmark | redis性能测试工具 |
redis-check-aof | aof文件修复工具 |
redis-check-dump | RDB文件检查工具 |
redis-sentinel | sentinel服务器(2.8以后) |
reids三种启动方法
- 最简启动(采用默认配置文件启动)
redis-server
复制代码
验证
ps aux | grep redis
复制代码
redis-cli -h 127.0.0.1 -p 6379 ping
复制代码
- 配置文件启动 (将需要配置的参数写入文件)
redis-server configPath
复制代码
- 动态参数启动
redis-server --port 6380
复制代码
三种启动方式比较
- 生产环境选择配置启动
- 单机多实例配置文件可以用端口区分开
redis客户端连接
redis-cli -h 127.0.0.1 -p 6379
复制代码
redis客户端返回值
返回值 | 返回值说明 |
---|---|
状态回复 | ping -> pong |
错误回复 | hget hello field -> (error) ERR wrong number of arguments for 'hget' command |
整数回复 | incr hello -> (integer) 1 |
字符串回复 | get hello -> "1" |
多行字符串回复 | mget hello foo -> 1) "1" 2) (nil) |
redis常用配置
配置名 | 说明 |
---|---|
daemonize | 是否是守护进程(no/yes) |
port | redis对外端口号 |
logfile | redis系统日志 |
dir | redis工作目录 |
redis安装启动(配置文件方式)
配置方式
- 配置文件
vim redis-6382.conf
port 6382
daemonize yes
logfile "6382.log"
dir ./workdata/
复制代码
- 启动
redis-server redis-6382.conf
复制代码
- 检查
ps -aux | grep -v redis-server | grep 6382
复制代码
- 日志文件
vim workdata/6382.log
复制代码
API的理解和使用
通用命令
命令 | 说明 | 时间复杂度 |
---|---|---|
keys [pattern] | 遍历所有key | O(N) |
dbsize | 遍历所有key | O(1) |
exists | 检查key是否存在 | O(1) |
del key | 删除指定的key-value | O(1) |
expire key seconds | key在seconds秒后过期 | O(1) |
ttl key | 查看key剩余的过期时间 | O(1) |
persist key | 去掉key的过期时间 | O(1) |
type key | 返回key的类型 | O(1) |
注意 keys命令一般不再生产环境使用
** 演示**
➜ redis-4.0.8 redis-cli -h 127.0.0.1 -p 6382
127.0.0.1:6382> set hello word
OK
127.0.0.1:6382> set php good
OK
127.0.0.1:6382> set java best
OK
127.0.0.1:6382> keys *
1) "java"
2) "hello"
3) "php"
127.0.0.1:6382> dbsize
(integer) 3
127.0.0.1:6382> exists php
(integer) 1
127.0.0.1:6382> del php java
(integer) 2
127.0.0.1:6382> keys *
1) "hello"
127.0.0.1:6382> expire hello 20
(integer) 1
127.0.0.1:6382> ttl hello
(integer) 16
127.0.0.1:6382> ttl hello
(integer) 12
127.0.0.1:6382> persist hello
(integer) 1
127.0.0.1:6382> ttl hello
(integer) -1
127.0.0.1:6382> type hello
string
复制代码
数据结构和内部编码
图示
reidsObject
单线程
定义
单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。
单线程为什么这么快
- 纯内存
- 非阻塞IO
- 避免线程切换和竞态消耗
使用单线程要注意什么
- 一次只能运行一条命令
- 拒绝长(慢)命令
- keys
- flushall
- flushdb
- slow lua script
- mutil/exec
- operate big value(collection)
string
结构
key | value |
---|---|
hello | world |
counter | 1 |
bits | 101111101110 |
可以是字符串(json);数字,以及二进制
使用场景
- 缓存
- 计数器
- 分布式锁
API
命令 | 说明 | 时间复杂度 |
---|---|---|
get key | 获取key对应的value | O(1) |
set key value | 设置key value | O(1) |
del key | 删除key-value | O(1) |
incr | key自增1, 如果key不存在,自增后get(key) = 1 | O(1) |
decr | key自减1, 如果key不存在,自增后get(key) = -1 | O(1) |
incrby key k | key自增k, 如果key不存在,自增后get(key) = k | O(1) |
decr key k | key自减k, 如果key不存在,自增后get(key) = -k | O(1) |
set key value | 不管可以是否存在 | O(1) |
setnx key value | key不存在,才设置 | O(1) |
set key value xx | key存在,才设置 | O(1) |
mget key1 key2 key3 | 批量获取key,原子操作 | O(N) |
mset key1 value1 key2 value2 | 批量设置key-value | O(1) |
getset key newvalue | set key newvalue并返回旧的value | O(1) |
append key value | 将value追加到旧的value | O(1) |
strlen key | 返回字符串的长度(注意中文,utf8下一个中文占用3个字符) | O(1) |
incrbyfloat key 3.5 | 增加key对应的值3.5 | O(1) |
getrange key start end | 获取字符串指定下标所有的值 | O(1) |
setrange key index value | 设置指定下标所有对应的值 | O(1) |
练习
127.0.0.1:6382> set hello "world"
OK
127.0.0.1:6382> get hell
(nil)
127.0.0.1:6382> get hello
"world"
127.0.0.1:6382> del hello
(integer) 1
127.0.0.1:6382> get hello
(nil)
127.0.0.1:6382> get counter
(nil)
127.0.0.1:6382> incr counter
(integer) 1
127.0.0.1:6382> get counter
"1"
127.0.0.1:6382> incrby counter 99
(integer) 100
127.0.0.1:6382> get counter
"100"
127.0.0.1:6382> decr counter
(integer) 99
127.0.0.1:6382> get counter
"99"
127.0.0.1:6382> decrby counter 100
(integer) -1
127.0.0.1:6382> get counter
"-1"
127.0.0.1:6382> exists php
(integer) 0
127.0.0.1:6382> set php good
OK
127.0.0.1:6382> setnx php bad
(integer) 0
127.0.0.1:6382> set php best xx
OK
127.0.0.1:6382> get php
"best"
127.0.0.1:6382> exists java
(integer) 0
127.0.0.1:6382> setnx java best
(integer) 1
127.0.0.1:6382> set java easy xx
OK
127.0.0.1:6382> get java
"easy"
127.0.0.1:6382> set hello world
OK
127.0.0.1:6382> getset hello php
"world"
127.0.0.1:6382> get hello
"php"
127.0.0.1:6382> append hell ",php"
(integer) 4
127.0.0.1:6382> get hello
"php"
127.0.0.1:6382> append hello ",php"
(integer) 7
127.0.0.1:6382> get hello
"php,php"
127.0.0.1:6382> strlen hello
(integer) 7
127.0.0.1:6382> set hello "吴军旗"
OK
127.0.0.1:6382> strlen hello
(integer) 9
复制代码
n次get操作
** 1次mget操作**
实战
- 记录网站每个用户个人主页的访问量
incr userid: pageview (**主要的是:单线程,所以无竞争)**)
复制代码
- 缓存视频的基本信息(数据源在mysql中)伪代码
- 分布式id生成器(单线程的好处)
incr id
复制代码
hash
哈希键值结构
特点
- mapmap
- small redis
- field不能相同,value可以相同
API
命令 | 说明 | 时间复杂度 |
---|---|---|
hget key field | 获取hash key对应field的value | O(1) |
hset key field value | 设置has key 对应的field的value | O(1) |
hexists key field | 判断hash key 是否有field | O(1) |
hlen key | 获取hash key field的数量 | O(1) |
hmget key field1 field2...fieldN | 批量获取hash key的一批field对应的值 | O(N) |
hset key field1 value1 field2 value2...fieldN valueN | 批量设置hash key的一批field value | O(1) |
hgetall key | 返回hash key对应所有的field和value | O(N) |
hvals key | 返回hash key对应所有的field的value | O(N) |
hkeys key | 返回hash key对应所有的field | O(N) |
hsetnx key field value | 设置has key 对应的field的value(如果field已经存在,则失败) | O(1) |
hincrby key field intCounter | hash key对应的field的value自增intCounter | O(1) |
hincrbyfloat key field floatCounter | 浮点数版本 | O(1) |
注意 小心使用hgetall(牢记单线程)
练习
127.0.0.1:6382> hset user1 age 26
(integer) 1
127.0.0.1:6382> hset user1 name wujunqi
(integer) 1
127.0.0.1:6382> hget all user1
(nil)
127.0.0.1:6382> hgetall user1
1) "age"
2) "26"
3) "name"
4) "wujunqi"
127.0.0.1:6382> hdel user1 age
(integer) 1
127.0.0.1:6382> hgetall user1
1) "name"
2) "wujunqi"
127.0.0.1:6382> hget user1 name
"wujunqi"
127.0.0.1:6382> hexists user1 name
(integer) 1
127.0.0.1:6382> hlen user1
(integer) 1
127.0.0.1:6382> hmset user2 name xiaofang age 26
OK
127.0.0.1:6382> hmget user2 name age
1) "xiaofang"
2) "26"
127.0.0.1:6382> hgetall user2
1) "name"
2) "xiaofang"
3) "age"
4) "26"
127.0.0.1:6382> hvals user2
1) "xiaofang"
2) "26"
127.0.0.1:6382> hkeys user2
1) "name"
2) "age"
127.0.0.1:6382> hincrby user age 2
(integer) 2
127.0.0.1:6382> hgetall user2
1) "name"
2) "xiaofang"
3) "age"
4) "26"
127.0.0.1:6382> hincrby user2 age 2
(integer) 28
127.0.0.1:6382> hgetall user2
1) "name"
2) "xiaofang"
3) "age"
4) "28"
127.0.0.1:6382> hincrbyfloat user2 age 2.0
"30"
127.0.0.1:6382> hincrbyfloat user2 age 2.5
"32.5"
127.0.0.1:6382> hgetall user2
1) "name"
2) "xiaofang"
3) "age"
4) "32.5"
复制代码
list
列表结构
特点
- 有序
- 可以重复
- 左右两边插入弹出
API
练习
127.0.0.1:6382> rpush list1 a b c d
(integer) 4
127.0.0.1:6382> lpush list1 e f g h i
(integer) 9
127.0.0.1:6382> lrange list1 0 -1
1) "i"
2) "h"
3) "g"
4) "f"
5) "e"
6) "a"
7) "b"
8) "c"
9) "d"
127.0.0.1:6382> linsert list1 before i wu
(integer) 10
127.0.0.1:6382> lrange list1 0 -1
1) "wu"
2) "i"
3) "h"
4) "g"
5) "f"
6) "e"
7) "a"
8) "b"
9) "c"
10) "d"
127.0.0.1:6382> linsert list1 after i jun
(integer) 11
127.0.0.1:6382> lrange list1 0 -1
1) "wu"
2) "i"
3) "jun"
4) "h"
5) "g"
6) "f"
7) "e"
8) "a"
9) "b"
10) "c"
11) "d"
127.0.0.1:6382> lpop list1
"wu"
127.0.0.1:6382> rpop list1
"d"
127.0.0.1:6382> lrange list1 0 -1
1) "i"
2) "jun"
3) "h"
4) "g"
5) "f"
6) "e"
7) "a"
8) "b"
9) "c"
127.0.0.1:6382> lrem list1 1 i
(integer) 1
127.0.0.1:6382> lrange list1 0 -1
1) "jun"
2) "h"
3) "g"
4) "f"
5) "e"
6) "a"
7) "b"
8) "c"
127.0.0.1:6382> rpush list1 c c c c c
(integer) 13
127.0.0.1:6382> ltrem list1 -3 c
(error) ERR unknown command 'ltrem'
127.0.0.1:6382> lrem list1 -3 c
(integer) 3
127.0.0.1:6382> lrange list1 0 -1
1) "jun"
2) "h"
3) "g"
4) "f"
5) "e"
6) "a"
7) "b"
8) "c"
9) "c"
10) "c"
127.0.0.1:6382> lindex list 0
(nil)
127.0.0.1:6382> lindex list1 0
"jun"
127.0.0.1:6382> llen list1
(integer) 10
127.0.0.1:6382> lset list 0 wu
(error) ERR no such key
127.0.0.1:6382> lset list1 0 wu
OK
127.0.0.1:6382> lrange list1 0 -1
1) "wu"
2) "h"
3) "g"
4) "f"
5) "e"
6) "a"
7) "b"
8) "c"
9) "c"
10) "c"
复制代码
应用
set
定义
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。 Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
特点
- 无序
- 无重复
- 集合间操作
API
- 集合内的操作
命令 | 说明 | 时间复杂度 |
---|---|---|
sadd key element | 向集合key添加element(如果element已经存在,添加失败) | O(1) |
srem key element | 将集合key中的element移除掉 | O(1) |
scard key | 计算集合大小 | O(1) |
sismember key element | 判断element 是否在集合中 | O(1) |
srandmember key count | 从集合中随机挑count个元素 | O(1) |
spop key | 从集合中随机弹出一个元素 | O(1) |
smembers key | 获取集合所有元素 | O(1) |
srem key element | 将集合key中的element移除掉 | O(1) |
- 集合间的操作
命令 | 说明 | 时间复杂度 |
---|---|---|
sdiff key1 key2 | 差集 | O(1) |
sinter key1 key2 | 交集 | O(1) |
sunion key1 key2 | 并集 | O(1) |
sidff/sinter/suion + store destkey | 将差集、交集、并集保存在destkey中 | O(1) |
注意
- srandmember不会破坏集合
- spop会破会
- smembers 返回的是无序集合,并且要注意量很大的时候回阻塞
练习
127.0.0.1:6382> sadd set1 a b c d
(integer) 4
127.0.0.1:6382> srem set1 a
(integer) 1
127.0.0.1:6382> smembers set1
1) "d"
2) "c"
3) "b"
127.0.0.1:6382> scard set1
(integer) 3
127.0.0.1:6382> sismember set1 d
(integer) 1
127.0.0.1:6382> srandmember set1 2
1) "d"
2) "b"
127.0.0.1:6382> srandmember set1 2
1) "b"
2) "c"
127.0.0.1:6382> spop set1
"c"
127.0.0.1:6382> smembers set1
1) "d"
2) "b"
127.0.0.1:6382> srem set1 d
(integer) 1
127.0.0.1:6382> smembers set1
1) "b"
127.0.0.1:6382> sadd set1 1 2 3 4 5
(integer) 5
127.0.0.1:6382> sadd set2 a b c 12 8 9 1 2
(integer) 8
127.0.0.1:6382> sdiff set1 set2
1) "3"
2) "4"
3) "5"
127.0.0.1:6382> sinter set1 set2
1) "2"
2) "b"
3) "1"
127.0.0.1:6382> sunion set1 set2
1) "5"
2) "2"
3) "4"
4) "1"
5) "a"
6) "8"
7) "3"
8) "b"
9) "9"
10) "12"
11) "c"
127.0.0.1:6382>
复制代码
实战
- 抽奖系统, 用spop
- 赞过的文章,收藏过的文章等
- 标签
- 共同关注
总结
zset
定义
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
API
命令 | 说明 | 时间复杂度 |
---|---|---|
zadd key score element | 添加score和element | O(logN) |
zrem key element(可以是多个) | 将集合key中的element移除掉 | O(1) |
zscore key element | 返回元素的分数 | O(1) |
zincrby key increScore element | 增加或减少元素的分数 | O(1) |
zcard key | 返回元素的总个数 | O(1) |
zrank(zrevrank) key member | 返回元素的排名 | O(1) |
zrange(zrevrank) key start end [WITHSCORES] | 返回指定索引范围内的升序元素[分值] | O(logN + m) |
zrangebyscore(zrevrangebyscore) key minScore maxScore | 返回指定分数范围内的升序元素 | O(logN + m) |
zcount key minScore maxScore | 返回有序集合内在指定分数范围内的个数 | O(logN + m) |
zremrangebyrank key start end | 删除指定排名内的升序元素 | O(logN + m) |
zremrangebyscore key minScore maxScore | 删除指定分数内的升序元素 | O(logN + m) |
ZINTERSTORE destination numkeys(表示key的个数) key [key ...] | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 | |
ZUNIONSTORE destination numkeys key [key ...] | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
实战
- 各种榜单(score:timestamp, saleCount, followCount)
redis客户端的使用
下载
找相应语言的下载(一般选择有笑脸和星星的)
https://redis.io/clients#php
复制代码
redis的其他功能
慢查询
生命周期
两点说明
- 慢查询发生在第3阶段
- 客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素
两个配置
- slowlog-max-len
- slowlog-log-slower-than
如何配置
慢查询命令
- slowlog get [n] : 获取慢查询队列
- slowlog len: 获取慢查询队列长度
- slowlog reset: 清空慢查询队列
运维经验
pipeline:流水线
什么是流水线
- 1次网络命令通信模型
- 批量网络命令通信模型
什么是流水线
流水线的作用
两点注意
- redis的命令时间是微秒级别
- pipeline每次条数要控制(网络)
与原生操作对比
- M操作
- pipeline
使用建议
- 注意每次pipeline携带数据量
- pipeline每次只能作用在一个redis节点上
- M操作与pipeline区别
发布订阅
角色
- 发布者
- 订阅者
- 频道
模型
API
- publish channel message
- subscribe [channel] 一个或者多个
- unsubscribe [channel] 一个或者多个
练习
127.0.0.1:6382> publish weibomovie "hello world"
(integer) 1
127.0.0.1:6382> publish weibomovie "hello world2"
(integer) 1
复制代码
另外一个cli
127.0.0.1:6382> SUBSCRIBE weibomovie
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "weibomovie"
3) (integer) 1
1) "message"
2) "weibomovie"
3) "hello world"
1) "message"
2) "weibomovie"
3) "hello world2"
复制代码
发布订阅与消息队列
Bitmap
位图
API
命令 | 说明 | 时间复杂度 |
---|---|---|
setbit key offset value | 给位图指定索引设置值 | O(1) |
getbit key offset | 获取位图指定索引的值 | O(1) |
bitcount key start end | 获取位图指定范围(start 到end,单位为字节,如果不指定就获取全部)位值为1的个数 | O(1) |
bitop op destkey key [key...] | 做多个bitmap的and,or,not,xor操作并将结果保存在destkey中 | O(1) |
bitpos key targetBit [start][end | 计算位图指定范围(start到end,单位为字节,如果不指定就是获取全部)第一个偏移量对应的值等于targetBit的位置 | O(1) |
练习
127.0.0.1:6382> set hello big
OK
127.0.0.1:6382> getbit hello
(error) ERR wrong number of arguments for 'getbit' command
127.0.0.1:6382> getbit hello 0
(integer) 0
127.0.0.1:6382> setbit hello 0 1
(integer) 0
127.0.0.1:6382> get hello
"\xe2ig"
127.0.0.1:6382> set hell a
OK
127.0.0.1:6382> bitcount hell
(integer) 3
127.0.0.1:6382> bitop and hell hello
(integer) 3
127.0.0.1:6382> set a a
OK
127.0.0.1:6382> set b b
OK
127.0.0.1:6382> bitop and c a b
(integer) 1
127.0.0.1:6382> get c
"`"
127.0.0.1:6382> bitpos a 1
(integer) 1
127.0.0.1:6382> bitpos a 0
(integer) 0
127.0.0.1:6382> set user2 100
OK
复制代码
独立用户统计
重要理解 使用位图去记录用户uid,其实就是记录索引值,比如userid=100代表位图下标100的值为1
使用经验
- type=string,最大512MB
- 注意setbit时的偏移量,可能有较大耗时
- 位图不是绝对好
HyperLogLog
新的数据结构
API
命令 | 说明 |
---|---|
pfaddd key element [element...] | 向hyperloglog添加元素 |
pfcount key [key...] | 计算hyperloglog的独立总数 |
pfmerge destkey sourceKey [sourcekey...] | 合并多个hyperloglog |
练习
127.0.0.1:6382> pfadd puser1 "u1" "u2" "u3"
(integer) 1
127.0.0.1:6382> pfcount puser1
(integer) 3
127.0.0.1:6382> pfadd puser2 "u3" "u4" "u5"
(integer) 1
127.0.0.1:6382> pfmerge puser puser1 puser2
OK
127.0.0.1:6382> pfcount puser
(integer) 5
复制代码
内存消耗
使用经验
- 是否能容忍错误(错误率:0.81%)
- 是否需要单条数据(没有办法取出)
GEO
GEO是什么
5个城市经纬度
API
命令 | 说明 |
---|---|
geoadd key longitude latitude member [longitude latitude member ...] | 增加地理位置信息 |
geopos key member[member... | 获取地理位置信息 |
geodist key member1 member2[unit] | 获取两个地理位置的距离,unit:m,km,mi,ft |
georadius | 获取指定位置范围内的地理位置信息集合 |
练习
127.0.0.1:6382> geoadd beijing 116.28 39.55
(error) ERR wrong number of arguments for 'geoadd' command
127.0.0.1:6382> geoadd geo 116.28 39.55 beijing 117.12 39.08 tianjin
(integer) 2
127.0.0.1:6382> geopos geo beijing
1) 1) "116.28000229597091675"
2) "39.5500007245470826"
127.0.0.1:6382> geodist geo beijing tianjin
"89206.0576"
127.0.0.1:6382>
复制代码
相关说明
- since 3.2+
- type geoKey = zset
- 没有删除API:zrem key member
redis持久化的取舍和选择
持久化的作用
什么是持久化
redis所有数据保存在内存中, 对数据的更新将异步地保存到磁盘上
持久化的实现方式
- 快照
- mysql dump
- redis RDB
- 写日志
- mysql binlog
- hbase hLog
- redis AOF
RDB
什么是RDB
触发机制-主要三种方式
- save(同步)
* 文件策略:如存在老的RDB文件,新替换老
* 复杂度:O(N)
复制代码
- bgsave(异步)
- 自动配置
**相关配置
配置参数 | 值 |
---|---|
save | 900 1 |
save | 300 10 |
save | 60 10000 |
dbfilename | dump-${port}.rdb |
dir | /bigdishpath |
stop-writes-on-bgsav-error | yes |
rdbcompression | yes |
save与bgsave
触发机制-不容忽略的方式
其他的方式也会触发生成RDB文件
- 全量复制
- debug reload
- shutdown
总结
- RDB是Redis内存到硬盘的快照,用于持久化
- save通常会阻塞Redis
- bgsave不会阻塞redis,但是会fork新进程
- save自动配置满足任一就会被执行
- 有些触发机制不容忽视
AOF
RDB现存问题
- 耗时,好性能
- 不可控,丢失数据
什么是AOF
- 创建
- 恢复
AOF三种策略
- always
- everysec
- no
三种策略比较
AOF重写
AOF重写的作用
- 减少硬盘占用量
- 加速恢复速度
AOF重写实现的两种方式
- bgrewriteaof
- aof重写配置
AOF重写流程
配置
RDB与AOF的选择
RDB最佳策略
- 关
- 集中管理
- 主从,从开
AOF最佳策略
- 开,缓存和存储
- AOF重写集中管理
- everysec
-------------------------华丽的分割线--------------------
看完的朋友可以点个喜欢/关注,您的支持是对我最大的鼓励。
想了解更多,欢迎关注我的微信公众号:番茄技术小栈
作者:吴军旗
链接:https://juejin.im/post/5a912b3f5188257a5c608729
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。