Redis 持久化的策略

Posted 宇宙唯心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 持久化的策略相关的知识,希望对你有一定的参考价值。

一 概述

redis是一种高级的key-value数据库,它跟memcached类似,不过数据可以持久化,而且支持的数据类型也很丰富。

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能,所以redis也可以被看成是一个数据结构服务器

 

1 String(字符串)

string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。

string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

string类型是Redis最基本的数据类型,一个键最大能存储512MB。

实例

redis 127.0.0.1:6379> SET name "runoob"
OK
redis 127.0.0.1:6379> GET name
"runoob"

在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 name,对应的值为 runoob

注意:一个键最大能存储512MB。

 

2 Hash(哈希)

Redis hash 是一个键值(key=>value)对集合。

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

实例

redis> HMSET myhash field1 "Hello" field2 "World"
"OK"
redis> HGET myhash field1
"Hello"
redis> HGET myhash field2
"World"

以上实例中 hash 数据类型存储了包含用户脚本信息的用户对象。 实例中我们使用了 Redis HMSET, HGETALL 命令,user:1 为键值。

每个 hash 可以存储 232 -1 键值对(40多亿)。

 

3 List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

实例

redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

 

4 Set(集合)

Redis的Set是string类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

sadd 命令

添加一个string元素到,key对应的set集合中,成功返回1,如果元素已经在集合中返回0,key对应的set不存在返回错误。

sadd key member

实例

redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob

1) "rabitmq"
2) "mongodb"
3) "redis"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。

 

5 zset(sorted set:有序集合)

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

 

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zset的成员是唯一的,但分数(score)却可以重复。

zadd 命令

添加元素到集合,元素在集合中存在则更新对应score

zadd key score member 

实例

redis 127.0.0.1:6379> zadd runoob 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> ZRANGEBYSCORE runoob 0 1000

1) "redis"
2) "mongodb"
3) "rabitmq" 

二 持久化的方式和原理

redis的所有数据都是保存在内存中的,

(1) 半持久化模式: 不定期地通过异步方式保存到磁盘上

(2) 全持久化模式: 把每一次数据变化都写入到一个append only file(aof)里面

 

1 半持久化模式 filesnapshotting

(1)行为:

默认redis会以快照的形式将数据持久化到磁盘,生成一个二进制文件,比如叫dump.rdb,配置文件中的格式是 save N M。表示在N秒之内,redis至少发生M次修改则redis抓快照到磁盘。当然也可以手动执行save或bgsave(异步)做快照

(2)原理实现:

redis需要持久化时,fork一个子京城,子进程将数据写到磁盘上一个临时文件rdb文件中,当子进程完成写临时文件后,将原来的rdb替换掉,copy-on-write方式

 

2 全持久化模式 AOF

(1)行为

filesnapshotting的半持久化方法在redis异常死掉时,会造成数据的丢失(取决于save的时机和频率)。而AOF可以做到数据不丢失,相应地性能就会差一些。在配置文件中开启(默认是no),appendonlyyes开启AOF后,redis每执行一个修改数据的命令,都会把它添加到AOF文件中,当redis重启时,将会读取AOF文件进行"回放"以恢复到redis关闭前的最后时刻

随着修改数据的执行AOF文件会越来越大,其中很多内容反复记录某一个key的变化情况,因此redis有一个特性对此进行了优化: 不影响client端操作的同时,后台重建AOF文件,在任何时候执行BGREWRITEAOF命令,都会把当前内存中最短序列的命令写到磁盘,这些命令完全可以构建当前的数据而没有多余的变化情况(如状态变化,计数器变化等),缩小了AOF文件的大小。

AOF文件刷新的方式,有三种,需要配置参数appendfsync:

a) appendfsync always每提交一个修改命令都调用fsync刷新到AOF文件,非常非常慢,但也非常安全;

b) appendfsync everysec每秒钟都调用fsync刷新到AOF文件,很快,但可能会丢失一秒以内的数据;

c) appendfsync no依靠OS进行刷新,redis不主动刷新AOF,这样最快,但安全性就差。默认并推荐每秒刷新,这样在速度和安全上都做到了兼顾。

 

(2)原理实现:

同样用到了copy-on-write,首先redis会fork一个子进程;子进程将最新的AOF写入一个临时文件;父进程增量的把内存中的最新执行的修改写入(这时仍写入旧的AOF,rewrite如果失败也是安全的);当子进程完成rewrite临时文件后,父进程会收到一个信号,并把之前内存中增量的修改写入临时文件末尾;这时redis将旧AOF文件重命名,临时文件重命名,开始向新的AOF中写入。

 

三 最后

最后,为以防万一(机器坏掉或磁盘坏掉),记得定期把使用 filesnapshotting 或 Append-only 生成的*rdb *.aof文件备份到远程机器上。我是用crontab每半小时SCP一次。我没有使用redis的主从功能 ,因为半小时备份一次应该是可以了,而且我觉得有如果做主从有点浪费机器。这个最终还是看应用来定了。

 

以上是关于Redis 持久化的策略的主要内容,如果未能解决你的问题,请参考以下文章

Redis持久化策略

Redis的持久化策略

Redis持久化策略(看这篇,你肯定会有所获)

Redis篇:持久化淘汰策略,缓存失效策略

Redis篇:持久化淘汰策略,缓存失效策略

关于redis的持久化策略