网站建设第一步,工装设计案例网站,如何查询网站历史快照,徐州网站公司什么是Redis 什么是Redis一、特性1. 支持多种数据结构2. 读/写速度快#xff0c;性能高。3. 支持持久化。4. 实现高可用主从复制#xff0c;主节点做数据副本。5. 实现分布式集群和高可用。 二、基本数据类型string#xff08;字符串#xff09;list(双向链表)set(集合)zse… 什么是Redis 什么是Redis一、特性1. 支持多种数据结构2. 读/写速度快性能高。3. 支持持久化。4. 实现高可用主从复制主节点做数据副本。5. 实现分布式集群和高可用。 二、基本数据类型string字符串list(双向链表)set(集合)zset(排序set)Hash(hash表) 三、特殊数据类型geospatial地理位置Hyperloglog基数Bitmaps位存储 四、击穿出现原因解决方案 五、雪崩出现原因解决方案 六、穿透出现原因解决方案 七、集群同步1. 主从复制2. 哨兵sentinel3. 集群Cluster 八、持久化RDB快照何时触发自动触发1. save2. stop-writes-on-bgsave-error3. rdbcompression4. rdbchecksum5. dbfilename6. dir 手动触发1. save2. bgsave a. shutdown正常关闭b. flushall指令触发恢复数据停止 RDB 持久化 优势劣势 AOF优势劣势触发 RDB与AOF混合持久化 什么是Redis
Redis是一个高性能的key-value数据库是由 Salvatore Sanfilippo 用C语言开发的一款开源的、高性能的键值对存储数据库它采用 BSD 协议为了适应不同场景下的存储需求提供了多种键值数据类型。 支持的键值数据类型有字符串、列表、有序集合、散列及集合等。正是因为它有如此丰富的数据类型的支持才会有庞大的用户群体。 内置复制、Lua 脚本、LRU 收回、事务及不同级别磁盘持久化功能同时通过 Redis Sentinel 实现高可用通过 Redis Cluster 提供自动分区等相关功能。
一、特性
Redis 是一款功能强大、支持多语言多种数据类型的数据库它具有许多优秀的特性可以实现消息订阅发布、Lua 脚本、数据库事务、Pipeline管道即当指令达到一定数量后客户端才会执行。同时 Redis 是单线程的它不依赖外部库它的所有操作都是原子性的使用简单 具体如下
1. 支持多种数据结构
哈希、集合、位图多用于活跃用户数等的统计、HyperLogLog超小内存唯一值计数由于只有 12KB因而是有一定误差范围的、GEO地理信息定位。
2. 读/写速度快性能高。
官方给出的数据是Redis 能读的速度是 110 000次/s写的速度是 81 000次/s。之所以有这么快的读/写速度是因为这些数据都存储在内存中。
3. 支持持久化。
Redis 的持久化也就是备份数据它每隔一段时间就将内存中的数据保存在磁盘中在重启的时候会再次加载到内存中从而实现数据持久化。Redis 的持久化方式是 RDB 和 AOF。
通常来看数据放在内存中是不安全一旦发生断电或者故障重要的数据可能会丢失。因此Redis提供了两种持久化方式RDB和AOF这两种方式可以将数据保存到硬盘中这样就保证了数据的持久化。
4. 实现高可用主从复制主节点做数据副本。
Redis提供了复制功能实现多个相同数据的Redis副本。 复制功能是分布式Redis的基础。
5. 实现分布式集群和高可用。
2.8版本正式提供了高可用实现Redis Sentinel 它能保证Redis节点的故障发现和故障自动转移。 3.0版本正式提供了分布式实现Redis Cluster 它是是Redis真正的分布式实现提供了高可用读写和容量的扩展性。
二、基本数据类型
string字符串
它师最基本的类型可以理解为Memcached一模一样的类型一个key对应一个value 常用命令set、get、decr、incr、mget等 一个键最大能存储 512MB
// 批量设置mset key1 value1 key2 value2
// 批量获取mget key1 key2
// 获取长度strlen key
// 字符串追加内容append key xxx
// 获取指定区间的字符getrange key 0 5
// 整数值递增 (递增指定的值)incr intkey (incrby intkey 10)
// 当key 存在时将覆盖SETEX key seconds value
// 将 key 的值设为 value 当且仅当 key 不存在。SETNX key valuelist(双向链表)
Redis 列表是简单的字符串列表按照插入顺序排序。你可以添加一个元素到列表的头部左边或者尾部右边 常用命令lpush、rpush、lpop、rpop、lrange等 列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)
// 将一个或多个值 value 插入到列表 key 的表头LPUSH key value [value ...]
// 将一个或多个值 value 插入到列表 key 的表尾(最右边)。RPUSH key value [value ...]
// 移除并返回列表 key 的头元素。LPOP key
// 移除并返回列表 key 的尾元素。RPOP key
// BLPOP 是列表的阻塞式(blocking)弹出原语。BLPOP key [key ...] timeout
// BRPOP 是列表的阻塞式(blocking)弹出原语。BRPOP key [key ...] timeout
// 获取指点位置元素LINDEX key indexset(集合)
Redis 的 Set 是 string 类型的无序集合 集合是通过哈希表实现的所以添加删除查找的复杂度都是 O(1) 常用命令sadd、spop、smembers、sunion等 Set可包含的最大元素数量是4294967295
// 将一个或多个 member 元素加入到集合 key 当中已经存在于集合的 member 元素将被忽略。SADD key member [member ...]
// 返回集合 key 中的所有成员。SMEMBERS key
// 返回集合 key 的基数(集合中元素的数量)。SCARD key
// 如果命令执行时只提供了 key 参数那么返回集合中的一个随机元素。SRANDMEMBER key [count]
// 移除并返回集合中的一个随机元素。SPOP key
// 移除集合 key 中的一个或多个 member 元素不存在的 member 元素会被忽略。SREM key member [member ...]
// 判断 member 元素是否集合 key 的成员。SISMEMBER key member
// 获取前一个集合有而后面1个集合没有的sdiff huihuiset huihuiset1
// 获取交集sinter huihuiset huihuiset1
// 获取并集sunion huihuiset huihuiset1zset(排序set)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序 常用命令zadd、zrange、zrem、zcard等 zset的成员是唯一的,但分数(score)却可以重复
//将一个或多个 member 元素及其 score 值加入到有序集 key 当中。ZADD key score member [[score member] [score member] ...]
// 返回有序集 key 中指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序ZRANGE key start stop [WITHSCORES]
// 返回有序集 key 中指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。ZREVRANGE key start stop [WITHSCORES]
// 返回有序集 key 中所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
// 移除有序集 key 中的一个或多个成员不存在的成员将被忽略。ZREM key member [member ...]
// 返回有序集 key 的基数。ZCARD key
// 为有序集 key 的成员 member 的 score 值加上增量 increment 。ZINCRBY key increment member
// 返回有序集 key 中 score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。ZCOUNT key min max
// 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。ZRANK key memberHash(hash表)
Redis hash 是一个键名对集合 Redis hash是一个string类型的field和value的映射表hash特别适合用于存储对象 常用命令hget、hset、hgetall等 每个 hash 可以存储 232 -1 键值对40多亿
// 将哈希表 key 中的域 field 的值设为 value 。HSET key field value
// 返回哈希表 key 中给定域 field 的值。HGET key field
// 返回哈希表 key 中的所有域。HKEYS key
// 返回哈希表 key 中所有域的值。HVALS key
// 为哈希表 key 中的域 field 的值加上增量 increment 。HINCRBY key field increment
// 查看哈希表 key 中给定域 field 是否存在。HEXISTS key field三、特殊数据类型
geospatial地理位置
1.geospatial将指定的地理空间位置纬度、经度、名称添加到指定的key中。 这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。 2.sorted set使用一种称为Geohash的技术进行填充。经度和纬度的位是交错的以形成一个独特的52位整数。 sorted set的double score可以代表一个52位的整数而不会失去精度。有兴趣的同学可以学习一下Geohash技术使用二分法构建唯一的二进制串 3.有效的经度是-180度到180度 有效的纬度是-85.05112878度到85.05112878度
命令功能描述geoadd添加地理位置往key中添加地理位置的坐标经度、纬度、位置名称geopos查询经纬度返回指定成员的经纬度参数geodist查询距离返回指定2个成员之间的直线距离默认单位米georadius附近的人指定经纬度为中心返回该中心指定半径内的成员georadiusbymember附近的人等同georadius上述是指定经纬度这个是指定成员附近的人geohash地理位置坐标返回Redis GEO 的地理位置的坐标
m 表示单位为米[默认值] km 表示单位为千米 mi 表示单位为英里 ft 表示单位为英尺
geoadd 向key中添加指定的地理位置经度、纬度、位置名称 (添加位置) geoadd key longitude latitude member [longitude …] geoadd {key} {longitude} {latitude} {member} [longitude latitude member…] // 添加北京经纬度、上海经纬度的位置到名为mycity的key中
127.0.0.1:6379 geoadd mycity 116.40 39.9 beijing 121.47 31.23 shanghai
(integer) 2// 底层是zset存储方式可以直接用zrange查询索引区间的所有成员
127.0.0.1:6379 zrange mycity 0 -1
1) beijing
2) tianjingeopos 返回指定成员的经纬度参数 (查询位置) geopos key member1 member2… geopos {key} {member} [member…] // 底层是zset存储方式可以直接用zrange查询索引区间的所有成员
127.0.0.1:6379 zrange mycity 0 -1
1) beijing
2) shanghai// 查询上海、北京、成都的经度纬度
127.0.0.1:6379 geopos mycity beijing shanghai tianjin
1) 1) 116.399998962879180912) 39.90000009167092543
2) 1) 121.470001637935638432) 31.22999903975783553
3) (nil) # 不存在mycity中的城市位置则返回nilgeodist 返回指定2个成员之间的距离 (查询位置) geodist key member1 member2… [m|km|ft|mi 单位可选] geodist {key} {member1} {member2} [m|km|ft|mi ] // 指定单位的参数 unit 必须是以下单位的其中一个
// 返回上海到北京的直线距离单位为km千米
127.0.0.1:6379 geodist mycity beijing shanghai km
1067.3788 // 返回北京到天津的直线距离成都在mycity中不存在返回nil
127.0.0.1:6379 geodist mycity beijing tianjin
(nil)georadius 以给定的经纬度为中心返回指定半径内的成员 (查询附近的人) georadius key longitude latitude radius [m|km|ft|mi 单位可选] georadius {key} {longitude} {latitude} radius m|km|ft|mi # 返回经度120纬度30 的周边500千米内的成员
127.0.0.1:6379 georadius mycity 120 30 500 km
1) nanchang
2) hangzhou
3) shanghai
4) nanjing# 100千米内的成员
127.0.0.1:6379 georadius mycity 120 30 100 km
1) hangzhou# 200千米内的成员
127.0.0.1:6379 georadius mycity 120 30 200 km
1) hangzhou
2) shanghai# 200千米内的成员名称、12030与该成员位置的直线距离数、经纬度参数
127.0.0.1:6379 georadius mycity 120 30 200 km withdist withcoord
1) 1) hangzhou2) 30.8146 # 直线距离3) 1) 120.1600000262260437 2) 30.2400003229490224
2) 1) shanghai2) 196.25123) 1) 121.470001637935638432) 31.22999903975783553# 返回1个 200千米内的成员名称 count num 指定显示num个
127.0.0.1:6379 georadius mycity 120 30 200 km count 1
1) hangzhougeoradiusbymember 指定某成员为中心返回指定半径内的成员 (查询附近的人) georadiusbymember key longitude latitude radius [m|km|ft|mi] # 返回上海的周边300千米内的成员名称
127.0.0.1:6379 georadiusbymember mycity shanghai 300 km
1) hangzhou
2) shanghai
3) nanjing# 200千米内的成员名称
127.0.0.1:6379 georadiusbymember mycity shanghai 200 km
1) hangzhou
2) shanghai# 返回上海的周边200千米内的成员名称、经纬度参数
127.0.0.1:6379 georadiusbymember mycity shanghai 200 km withcoord
1) 1) hangzhou2) 1) 120.16000002622604372) 30.2400003229490224
2) 1) shanghai2) 1) 121.470001637935638432) 31.22999903975783553geohash 获取一个或多个地理位置的hash值 (返回坐标hash值) geohash key member1 member2… # 返回上海、北京、杭州的坐标hash
127.0.0.1:6379 geohash mycity shanghai beijing hangzhou
1) wtw3sj5zbj0
2) wx4fbxxfke0
3) wtmkn31bfb0Hyperloglog基数
hyperloglog 是用来做基数统计的其优点是输入的提及无论多么大hyperloglog使用的空间总是固定的12KB 利用12KB它可以计算2^64个不同元素的基数非常节省空间但缺点是估算的值可能存在误差 这个结构可以非常省内存的去统计各种计数比如注册 IP 数、每日访问 IP 数的页面实时UV、在线用户数共同好友数等。 Redis HyperLogLog 是一种基数算法可以用于估计一个集合中的元素数量。Redis HyperLog 的特点如 Redis HyperLogLog 是一种基数算法可以用于估计一个集合中的元素数量。 Redis HyperLogLog 的误差率很小通常在 0.81% 左右。 Redis HyperLogLog 的空间占用很小通常只需要几 KB 的空间。
# 添加指定元素到 HyperLogLog 中
# PFADD key [element [element ...]]
127.0.0.1:6379 PFADD mykey1 a b c d e f g h i j
(integer) 1# 返回给定 HyperLogLog 的基数估算值。
# PFCOUNT key [key ...]
127.0.0.1:6379 PFCOUNT mykey1
(integer) 10# 将多个 HyperLogLog 合并为一个 HyperLogLog
# PFMERGE destkey sourcekey [sourcekey ...]
127.0.0.1:6379 PFADD mykey2 i j z x c v b n m
(integer) 1
127.0.0.1:6379 PFCOUNT mykey2
(integer) 9
127.0.0.1:6379 PFMERGE mykey3 mykey1 mykey2
OK
127.0.0.1:6379 PFCOUNT mykey3
(integer) 15Bitmaps位存储
Redis提供的Bitmaps这个“数据结构”可以实现对位的操作。Bitmaps本身不是一种数据结构实际上就是字符串但是它可以对字符串的位进行操作。 Bitmap 即位图数据结构都是操作二进制位来进行记录只有0 和 1 两个状态。 比如统计用户信息活跃不活跃 登录未登录 打卡不打卡 两个状态的都可以使用 可以把Bitmaps想象成一个以位为单位数组数组中的每个单元只能存0或者1数组的下标在bitmaps中叫做偏移量。单个bitmaps的最大长度是512MB即2^32个比特位。
1.设置Bitmaps中某个偏移量的值(0或1)
setbit key offset value2.获取Bitmaps中某个偏移量的值
getbit key offset3.统计字符串从start字节到end字节比特值为1的数量
bitcount key [start end]4.对多个Bitmaps的and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在destkey中
bitop and(or/not/xor) destkey [key1 key2 ...]127.0.0.1:6379 SETBIT sign:Bob:202201 1 1 # 设置 这里的 1|0 是二进制
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 2 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 3 0
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 4 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 5 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 6 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 7 1
(integer) 0
127.0.0.1:6379 GETBIT sign:Bob:202201 2 # 获取某天状态
(integer) 1
127.0.0.1:6379 BITCOUNT sign:Bob:202201 # 统计 位 1 的数量
(integer) 6对指定key按位进行交、并、非、异或操作并把结果保存到destKey中
127.0.0.1:6379 SETBIT sign:Bob:202201 1 1 # 设置 这里的 1|0 是二进制
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 2 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 3 0
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 4 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 5 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 6 1
(integer) 0
127.0.0.1:6379 SETBIT sign:Bob:202201 7 1
(integer) 0
127.0.0.1:6379 GETBIT sign:Bob:202201 2 # 获取某天状态
(integer) 1
127.0.0.1:6379 BITCOUNT sign:Bob:202201 # 统计 位 1 的数量
(integer) 6事务
// 1. multi命令开启事务exec命令提交事务
127.0.0.1:6379 multi
OK
127.0.0.1:6379(TX) set k1 v1
QUEUED
127.0.0.1:6379(TX) set k2 v2
QUEUED
127.0.0.1:6379(TX) exec
1) OK
2) OK
// 2. 组队的过程中可以通过discard来放弃组队。127.0.0.1:6379 multi
OK127.0.0.1:6379(TX) set k3 v3
QUEUED127.0.0.1:6379(TX) set k4 v4
QUEUED127.0.0.1:6379(TX) discard
OK四、击穿
缓存已过期了请求直奔数据库。
出现原因
热点Key过期
解决方案
查DB后同步Redis、Canal同步
设置热点key永不过期但是非常占用空间对内存消耗也是极大。个人并不建议使用该方法应该根据具体业务逻辑来操作。加互斥锁通过synchronized双重检查机制 当发生reids穿透的时候这时海量请求发送到数据库。保证了只有一个线程能够进行持久层数据查询其它线程保持阻塞状态(可以让它们sleep几秒)。当这个进入数据库的线程查询出key对应的value时我们再将其同步至redis的缓存当中其它线程睡醒以后再重新去redis里边请求数据。使用Timetask做一个定时任务 使用Timetask做定时每隔一段时间对一些热点key进行数据库查询将查询出的结果更新至redis中。前条件是不会给数据库过大的压力。
五、雪崩
大量的热点Key过期Redis 宕机请求全部打到DB导致数据库极大压力飙升甚至宕机。
出现原因
大量Key同时失效Redis宕机
解决方案
过期时间添加随机值、接口限流
设置缓存时,随机初始化其失效时间将不同的热点key放置到不同的节点上去使用Timetask做一个定时任务在失效之前重新刷redis缓存时效设置成永不过期Redis高可用搭建Redis集群异地多活限流降级在缓存失效后通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存其他线程等待。数据预热我先把可能的数据先预先访问一遍这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key设置不同的过期时间让缓存失效的时间点尽量均匀 。
六、穿透
查询不存在的数据一般为恶意请求请求直奔数据库缓存系统形同虚设对数据库产生很大压力从而影响正常服务。
出现原因
特殊请求在查询一个不存在的数据即Redis不存在且数据库也不存在。
解决方案
布隆过滤器、设置缺省值
布隆过滤器可以理解成一个白名单或者黑名单它的作用就是判断一个元素是否存在于这个过滤器。 白名单 过滤器里有数据库中所有的合法的参数key请求经过布隆过滤器布隆过滤器判断这个请求的key在不在过滤器在就放行让请求进入redis不在就直接return空数据。 在数据写入数据库的同时将这个 ID 同步到到布隆过滤器中当请求的 id 不存在布隆过滤器中则说明该请求查询的数据一定没有在数据库中保存就不要去数据库查询了。DB即使空值也讲其在Redis设置一个缺省值比如None并设置一个过期时间再访问这个数据将会从Redis中访问保护了持久层的数据库 a. 很多多余的空值 b. 缓存与DB不一致请求Redis导致查询结果不正确不是真实DB数据拉黑其IP对请求的参数进行合法性校验在判断其不合法的前提下直接return跳出
七、集群同步
1. 主从复制
主从复制是高可用Redis的基础哨兵和cluster都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。
优势
读写分离如果只有一台服务器读和写操作都在一台服务器上进行这台服务器的压力就会很大。而使用主从复制可以达到读写分离效果写操作都在master主服务器进行写操作进行完成之后把内容复制到它的从服务器去读操作都在slave从服务器进行。容灾快速恢复如果主服务器中进行写操作之后复制到了从服务器从服务器一般有多台如果第一台从服务器在读的过程中突然挂掉就会切换到另外一台从服务器进行读操作此即为容灾快速恢复。
缺陷故障恢复无法自动化写操作无法负载均衡存储能力受到单机的限制。
主从复制模式就是部署多台redis节点其中只有一台节点是主节点master其他的节点都是从节点slave也叫备份节点replica。只有master节点提供数据的事务性操作增删改slave节点只提供读操作。所有slave节点的数据都是从master节点同步过来的。
2. 哨兵sentinel
哨兵模式即为反客为主的自动版能够后台监控主机是否故障如果故障了根据投票数自动将从库转换为主库。
缺陷故障恢复无法自动化写操作无法负载均衡存储能力受到单机的限制。
集群监控负责监控 Redis master 和 slave 进程是否正常工作消息通知如果某个 Redis 实例出现故障那么哨兵负责发送消息作为报警通知给管理员故障转移如果 master node 挂掉了会自动转移到 slave node 上配置中心如果故障转移发生了通知 client 客户端习新的 master 地址
3. 集群Cluster
通过集群Redis解决了写操作无法负载均衡以及存储能力受到单机限制的问题实现了较为完善的高可用方案
主节点负责读写请求和集群信息的维护从节点只进行主节点数据和状态信息的复制
数据分区
数据分区或称数据分片是集群最核心的功能分布式
集群将数据分散到多个节点一方面突破了 Redis 单机内存大小的限制存储容量大大增加另一方面每个主节点都可以对外提供读服务和写服务大大提高了集群的响应能力
Redis 单机内存大小受限问题例如如果单机内存太大bgsave 和 bgrewriteaof 的 fork 操作可能导致主进程阻塞主从环境下主机切换时可能导致从节点长时间无法提供服务全量复制阶段主节点的复制缓冲区可能溢出
高可用
集群支持主从复制模式和主节点的自动故障转移与哨兵类似当任意节点发送故障时集群仍然可以对外提供服务
数据分片
Redis 集群引入了哈希槽的概念有 16384 个哈希槽编号 0~16383
集群的每个节点负责一部分哈希槽每个 Key 通过 CRC16 校验后对 16384 取余来决定放置哪个哈希槽通过这个值去找到对应的插槽所对应的节点然后直接自动跳转到这个对应的节点上进行存取操作
八、持久化
Redis是一种内存型数据库一旦服务器进程退出数据库的数据就会丢失为了解决这个问题Redis供了两种持久化的方案将内存中的数据保存到磁盘中避免数据的丢失 两种持久化方式快照RDB文件和追加式文件AOF文件下面分别为大家介绍两种方式的原理。
RDB快照
Redis中的RDB持久化方式采用了写时复制技术copy on write和fork子进程。
RDB是Redis用来进行持久化的一种方式是把当前内存中的数据集快照写入磁盘也就是 Snapshot 快照数据库中所有键值对数据它可以手动执行也可以在redis.conf配置文件中配置定时执行恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,在用这个临时文件替换上次持久化好的文件.
整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效.
何时触发
自动触发
1. save save这里是用来配置触发 Redis的 RDB 持久化条件也就是什么时候将内存中的数据保存到硬盘。比如“save m n”。表示m秒内数据集存在n次修改时自动触发bgsave这个命令下面会介绍手动触发RDB持久化的命令
当然如果你只是用Redis的缓存功能不需要持久化那么你可以注释掉所有的 save 行来停用保存功能。可以直接一个空字符串来实现停用save “”
save 900 1 900s检查一次至少有1个key被修改就触发
save 300 10 300s检查一次至少有10个key被修改就触发
save 60 10000 60s检查一次至少有10000个key被修改2. stop-writes-on-bgsave-error
默认值为yes。当启用了RDB且最后一次后台保存数据失败Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上否则没有人会注意到灾难disaster发生了。如果Redis重启了那么又可以重新开始接收数据了
3. rdbcompression
默认值是yes。对于存储到磁盘中的快照可以设置是否进行压缩存储。如果是的话redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话可以设置为关闭此功能但是存储在磁盘上的快照会比较大。
4. rdbchecksum
默认值是yes。在存储快照后我们还可以让redis使用CRC64算法来进行数据校验但是这样做会增加大约10%的性能消耗如果希望获取到最大的性能提升可以关闭此功能。
5. dbfilename
设置快照的文件名默认是 dump.rdb
6. dir
设置快照文件的存放路径这个配置项一定是个目录而不能是文件名。默认是和当前配置文件保存在同一目录。
也就是说通过在配置文件中配置的 save 方式当实际操作满足该配置形式时就会进行 RDB 持久化将当前的内存快照保存在 dir 配置的目录中文件名由配置的 dbfilename 决定。
手动触发
1. save
该命令会阻塞当前Redis服务器执行save命令期间Redis不能处理其他命令直到RDB过程完成为止。
显然该命令对于内存比较大的实例会造成长时间阻塞这是致命的缺陷为了解决此问题Redis提供了第二种方式。
2. bgsave
执行该命令时Redis会在后台异步进行快照操作快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程RDB持久化过程由子进程负责完成后自动结束。阻塞只发生在fork阶段一般时间很短。
基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
ps:执行执行 flushall 命令也会产生dump.rdb文件但里面是空的无意义
a. shutdown正常关闭
任何组件在正常关闭的时候都会去完成应该完成的事。比如Mysql 中的Redolog持久化正常关闭的时候也会去持久化。
b. flushall指令触发
数据清空指令会触发RDB操作并且是触发一个空的RDB文件所以 如果在没有开启其他的持久化的时候flushall是可以删库跑路的在生产环境慎用。
恢复数据
将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可redis就会自动加载文件数据至内存了。Redis 服务器在载入 RDB 文件期间会一直处于阻塞状态直到载入工作完成为止。
获取 redis 的安装目录可以使用 config get dir 命令
停止 RDB 持久化
有些情况下我们只想利用Redis的缓存功能并不像使用 Redis 的持久化功能那么这时候我们最好停掉 RDB 持久化。可以通过上面讲的在配置文件 redis.conf 中可以注释掉所有的 save 行来停用保存功能或者直接一个空字符串来实现停用save “”
也可以通过命令
redis-cli config set save
优势
1.RDB是一个非常紧凑(compact)的文件它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。 2.生成RDB文件的时候redis主进程会fork()一个子进程来处理所有保存工作主进程不需要进行任何磁盘IO操作。 3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
劣势
如果你想保证数据的高可用性即最大限度的避免数据丢失那么RDB将不是一个很好的选择。因为数据完整性和一致性不高因为RDB可能在最后一次备份时宕机此前没有来得及写入磁盘的数据都将丢失可能会丢失最后一次快照后的修改fork的时候,内存中数据被克隆了一份,需要考虑内存的使用fork过程比较耗时,可能响应客户端的时间不能达到毫秒级经常fork子进程所以比较耗CPU对CPU不是很友好由于RDB是通过fork子进程来协助完成数据持久化工作的因此如果当数据集较大时可能会导致整个服务器停止服务几百毫秒甚至是1秒钟。DB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程属于重量级操作(内存中的数据被克隆了一份大致2倍的膨胀性需要考虑)频繁执行成本过高(影响性能)RDB文件使用特定二进制格式保存Redis版本演进过程中有多个格式的RDB版本存在老版本Redis服务无法兼容新版RDB格式的问题(版本不兼容)
AOF
以日志的形式来记录每个写的操作将Redis执行过的所有指令记录下来读操作不记录只许追加文件但不可以改写文件redis启动之初会读取该文件重新构建数据换言之redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
Always同步写回每个写命令执行完立马同步地将日志写回磁盘 Everysec每秒写回每个写命令执行完只是先把日志写到 AOF 文件的内存缓冲区每隔一秒把缓冲区中的内容写入磁盘 No操作系统控制的写回每个写命令执行完只是先把日志写到 AOF 文件的内存缓冲区由操作系统决定何时将缓冲区内容写回磁盘。
配置项写回时机优点缺点Always同步写回可靠性高数据基本不会丢失每个写命令都要落盘性能影响较大Everysec每秒写回性能适中宕机时丢失1秒内的数据No操作系统控制的写回性能好宕机时丢失数据较多
base表示基础AOF一般由子进程重写产生该文件最多只有一个。 incr表示增量AOF一般会在AOFRW开始执行时被创建该文件可有多个。 history表示历史AOF由base和incr变化而来每次AOFRW成功完成时本次AOFRW之前对应的base和incr都会变成historyhistory类型的AOF会被redis自动删除
优势
AOF相对RDB更加安全一般不会有数据的丢失或者很少官方推荐同时开启AOF和RDB。
如果系统是愿意牺牲一些性能换取更高的缓存一致性AOF 或者是愿意写操作频繁的时候不启用备份来换取更高的性能待手动运行save的时候再做备份RDB。 Redis允许同时开启AOF和RDB既保证了数据安全又使得进行备份等操作十分容易。此时重新启动Redis后Redis会使用AOF文件来恢复数据因为AOF方式的持久化可能丢失的数据更少。
更好的保护数据不丢失使用默认每秒写回策略也最多只会丢失一秒钟的写入性能高AOF仅是一个附加日志不会出现寻道问题也不会在断电时出现损坏问题并且多数问题redis-check-aof工具能轻松修复它可做紧急恢复例如最后一条命令是flushall只需要打开增量文件把flushall删除再重启服务数据就恢复到flushall之前了
劣势
AOF文件通常比相同数据集的等效RDB文件大AOF运行效率要慢于RDB每秒同步策略效率较好不同步效率和RDB相同
触发
AOF也有不同的触发方案这里简要描述以下三种触发方案
always每次发生数据修改就会立即记录到磁盘文件中这种方案的完整性好但是IO开销很大性能较差 everysec在每一秒中进行同步速度有所提升。但是如果在一秒内宕机的话可能失去这一秒内的数据 no默认配置即不使用 AOF 持久化方案。 可以在redis.config中进行配置appendonly no改换为yes再通过注释或解注释appendfsync配置需要的方案
RDB与AOF混合持久化
数据恢复顺序和加载流程 混合持久化中RDB持久化的必要性 在混合持久化情况下当redis重启的时候会优先载入AOF文件来恢复原始的数据因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。 RDB的数据不实时同时使用两者时服务器重启也只会找AOF文件。但是RDB更适合用于备份数据库(AOF在不断变化不好备份)留着rdb作为一个万一的手段。混合持久化结合了RDB和AOF的优点既能快速加载又能避免丢失过多的数据 RDB镜像做全量持久化AOF做增量持久化。 先使用RDB进行快照存储然后使用AOF持久化记录所有的写操作当重写策略满足或手动触发重写的时候将最新的数据存储为新的RDB记录。这样的话重启服务的时候会从RDB和AOF两部分恢复数据既保证了数据完整性又提高了恢复数据的性能。 简单来说混合持久化方式产生的文件一部分是RDB格式一部分是AOF格式。---- AOF包括了RDB头部AOF混写
应用场景做纯粹的高并发高性能缓存服务器时 关闭RDBsave “” 关闭AOFappendonly no 同时关闭RDBAOF但在RDBAOF都禁用的情况下仍然可以使用save/bgsave命令生成rdb文件仍可以使用bgrewriteaof命令生成aof文件