1、NoSQL
-
什么是NoSQL
- No Only SQL
- 非关系型的数据库
-
为什么需要NoSQL
- High performance - 高并发读写
- Huge Storage - 海量数据的高效率存储和访问
- High Scalability && High Availability - 高可扩展性和高可用性
-
NoSQL数据库的四大分类
- 键值(Key-Value)存储
- 列存储
- 文档数据库
- 图形数据库
-
NoSQL的特点
- 易扩展
- 大数据量,高性能
- 灵活的数据模型
- 高可用
Redis概述
高性能键值对数据库,支持的键值数据类型:
- 字符串类型
- 列表类型
- 有序的集合类型
- 散列类型
- 集合类型
Redis应用场景
- 缓存
- 任务队列
- 网站访问统计
- 数据过期处理
- 应用排行榜
- 分布式集群架构中的session分离
安装Redis
- redis-benchmark :性能测试的工具
- redis-check-aof : aof文件修复工具
- redis-check-dump : RDB文件检查工具
- redis-cli : 命令行客户端
- redis-sentinel :
- redis-server : Redis服务器启动命令
redis.conf:daemonize yes 后台启动
ps -ef | grep -i redis 查看redis进程
kill -9 redis_kid 关闭redis
或者 redis-cli shutdown
127.0.0.1:6379> set name imooc // 设置值
OK
127.0.0.1:6379> get name // 获取值
"imooc"
127.0.0.1:6379> keys * // 查看当前数据库所有key
1) "name"
127.0.0.1:6379> del name // 删除key
(integer) 1
127.0.0.1:6379> keys *
(empty list or set) // 已经删除了
Jedis入门
Jedis介绍
Jedis是Redis官方首选的Java客户端开发包
http://github.com/xetorthio/jedis
设置Linux防火墙:
CentOS 6.5
vim /etc/sysconfig/iptables
添加:-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
重启防火墙:service iptables restartCentOS 7.0+
firewall-cmd --add-port=6379/tcp
Redis数据结构
- 字符串(String)
- 字符串列表(list)
- 有序字符串集合(sorted set)
- 哈希(hash)
- 字符串集合(set)
key定义规范
- 不要太长
- 不要过短
- 统一的命名规范
存储String
- 在redis中以二进制方式进行操作,意味着该类型存入和获取的数据是相同的,做多可容纳512M
- 命令
- 赋值
- 取值
- 删除
- 数值增减
- 扩展命令
127.0.0.1:6379> set company immoc
OK
127.0.0.1:6379> get company
"immoc"
127.0.0.1:6379> getset company baidu // 先获取在设置
"immoc"
127.0.0.1:6379> get company
"baidu"
127.0.0.1:6379> del company // 删除
(integer) 1
127.0.0.1:6379> get company
(nil)
127.0.0.1:6379> incr num // 数值增加,指定的key的value递增1,如果可以未设置,则初始化0并且自增1,如果key存储字符串则抛出异常
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr company
(error) ERR value is not an integer or out of range
127.0.0.1:6379> decr num // 和incr相反
(integer) 1
127.0.0.1:6379> decr num2
(integer) -1
127.0.0.1:6379> incrby num 5 // 指定增加幅度
(integer) 6
127.0.0.1:6379> incrby num3 3
(integer) 3
127.0.0.1:6379> decrby num 3 // 与incrby相反
(integer) 3
127.0.0.1:6379> decrby num4 3
(integer) -3
127.0.0.1:6379> append num 5 // 追加字符串
(integer) 2
127.0.0.1:6379> get num
"35"
存储Hash
- String Key 和 String Value的map容器
- 每一个Hash可以存储42949672895个键值对
存储Hash的常用命令
- 赋值
- 取值
- 删除
- 增加数字
- 自学命令
127.0.0.1:6379> hset myhash username jack // 设置存储hash值,key 属性 属性值
(integer) 1
127.0.0.1:6379> hset myhash age 18
(integer) 1
127.0.0.1:6379> hmset myhash2 username rose age 21 // 设置多个属性属性值
OK
127.0.0.1:6379> hget myhash username // 获取指定key的指定属性值
"jack"
127.0.0.1:6379> hmget myhash username age // 获取指定key多个属性的多个值
1) "jack"
2) "18"
127.0.0.1:6379> hgetall myhash // 获取指定key的多有属性和属性值
1) "username"
2) "jack"
3) "age"
4) "18"
127.0.0.1:6379> hdel myhash2 username age // 删除指定key的多个属性
(integer) 2
127.0.0.1:6379> hdel myhash2 username // 删除不存在的指定key的属性
(integer) 0
127.0.0.1:6379> hmset myhash2 username rose age 21
OK
127.0.0.1:6379> del myhash2 // 一次性删除指定key的所有属性
(integer) 1
127.0.0.1:6379> hget myhash2 username
(nil)
127.0.0.1:6379> hincrby myhash age 5 // 给指定key的属性值增5
(integer) 23
127.0.0.1:6379> hget myhash age
"23"
127.0.0.1:6379> hexists myhash username // 判断指定key属性是否存在,存在为1
(integer) 1
127.0.0.1:6379> hlen myhash // 获取属性数量
(integer) 2
127.0.0.1:6379> hkeys myhash // 获取指定key所有属性
1) "username"
2) "age"
127.0.0.1:6379> hvals myhash // 获取指定key所有属性值
1) "jack"
2) "23"
存储list
按照插入顺序排序的字符串的链表,和数据结构中的普通链表一样。可以在头部(左侧)和尾部(右侧)去添加新的元素。在插入的时候,如果该键不存在,那么redis就会为这个键创建一个新的链表,与此相反,如果链表中的所有元素都被移除了,那么该键也会被从数据库中删除。从元素的插入和删除的效率的视角来看,链表的两头插入和删除元素是非常高效的操作。如果是在链表中间操作,那么效率就会比较低。
- ArrayList使用数组方式(根据索引去查询速度非常快,新增和删除元素需涉及位移操作,较慢)
- LinkedList使用双向链接方式(每个元素都记录了前后元素的指针,插入和删除只是改变前后元素的指针指向即可,速度较快)
- 双向链表中增加数据
- 双向链表删除数据
存储list常用命令:
- 两端添加
- 查看列表
- 两端弹出
- 获取列表元素个数
- 扩展命令
127.0.0.1:6379> lpush mylist a b c // 从左侧首次添加
(integer) 3
127.0.0.1:6379> lpush mylist 1 2 3 // 再次添加
(integer) 6
127.0.0.1:6379> rpush mylist2 a b c // 从右边插入
(integer) 3
127.0.0.1:6379> rpush mylist2 1 2 3 // 再次添加
(integer) 6
127.0.0.1:6379> lrange mylist 0 5 // 查看列表(从0到5)
1) "3"
2) "2"
3) "1"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> lrange mylist2 0 -1
1) "a"
2) "b"
3) "c"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> lrange mylist2 0 -2
1) "a"
2) "b"
3) "c"
4) "1"
5) "2"
127.0.0.1:6379> lrange mylist 0 -1
1) "3"
2) "2"
3) "1"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> lpop mylist // 头部弹出
"3"
127.0.0.1:6379> lrange mylist 0 -1
1) "2"
2) "1"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379> rpop mylist2 // 尾部弹出
"3"
127.0.0.1:6379> lrange mylist2 0 -1
1) "a"
2) "b"
3) "c"
4) "1"
5) "2"
127.0.0.1:6379> llen mylist // 获取列表中元素个数
(integer) 5
127.0.0.1:6379> llen mylist2
(integer) 5
127.0.0.1:6379> llen mylist3
(integer) 0
127.0.0.1:6379> lpushx mylist x // 仅当key存在时在头部插入一个值
(integer) 6
127.0.0.1:6379> lrange mylist 0 -1
1) "x"
2) "2"
3) "1"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> lpushx mylist3 x
(integer) 0
127.0.0.1:6379> rpushx mylist2 y // 仅当key存在时在尾部插入一个值
(integer) 6
127.0.0.1:6379> lpush mylist3 1 2 3
(integer) 3
127.0.0.1:6379> lpush mylist3 1 2 3
(integer) 6
127.0.0.1:6379> lpush mylist3 1 2 3
(integer) 9
127.0.0.1:6379> lrem mylist3 2 3 // 删除元素 key count value;删除count个为value的值;如果count>0,从头向尾删除
(integer) 2
127.0.0.1:6379> lrange mylist3 0 -1
1) "2"
2) "1"
3) "2"
4) "1"
5) "3"
6) "2"
7) "1"
127.0.0.1:6379> lrem mylist3 -2 1 // count<0,从尾向头遍历删除
(integer) 2
127.0.0.1:6379> lrange mylist3 0 -1
1) "2"
2) "1"
3) "2"
4) "3"
5) "2"
127.0.0.1:6379> lrem mylist3 0 2 // count=0,删除全部等于value的值。
(integer) 3
127.0.0.1:6379> lrange mylist3 0 -1
1) "1"
2) "3"
127.0.0.1:6379> lrange mylist 0 -1
1) "x"
2) "2"
3) "1"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> lset mylist 3 mmm // 设置链表中的某个index的角标的值,0代表第一个元素;-1代表最尾的一个数
OK
127.0.0.1:6379> lpush mylist4 a b c
(integer) 3
127.0.0.1:6379> lpush mylist4 a b c
(integer) 6
127.0.0.1:6379> lrange mylist4 0 -1
1) "c"
2) "b"
3) "a"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> linsert mylist4 before b 11 // 某个角标的前后插入值
(integer) 7
127.0.0.1:6379> lrange mylist4 0 -1
1) "c"
2) "11"
3) "b"
4) "a"
5) "c"
6) "b"
7) "a"
127.0.0.1:6379> linsert mylist4 after b 11
(integer) 8
127.0.0.1:6379> lrange mylist4 0 -1
1) "c"
2) "11"
3) "b"
4) "11"
5) "a"
6) "c"
7) "b"
8) "a"
127.0.0.1:6379> lpush mylist5 1 2 3
(integer) 3
127.0.0.1:6379> lpush mylist6 a b c
(integer) 3
127.0.0.1:6379> lrange mylist5 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> lrange mylist6 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> rpoplpush mylist5 mylist6 // 尾部元素弹出并压入到头部
"1"
127.0.0.1:6379> lrange mylist5 0 -1
1) "3"
2) "2"
127.0.0.1:6379> lrange mylist6 0 -1
1) "1"
2) "c"
3) "b"
4) "a"
rpoplpush的应用场景
redis链表多用于消息队列的一些服务,来完成多个程序之间的消息交互,加入一个应用程序正在执行lpush向链表中添加新的元素,即生产者;另外一个程序正在执行rpop从链表中取出元素,即消费者;与此同时消费者程序在取出元素后,立刻崩溃。由于该消息已经被取出,且没有被正常处理。则认为这个消息已经丢失,可能会导致业务数据的丢失,或者是业务状态的不一致。可以通过rpoplpush这个命令,消费者程序在主消息队列中,取出元素后,再将其插入到一个备份的队列中,直到消费者程序完成正常逻辑处理后,在将消息从备份队列中删除,这样就提供了一个守护线程。然后当发现备份队列中的消息过期后可以重新放到主消息的队列中,以便其他消费者可以继续处理。
存储Set
没有排序的字符串集合
- 和List类型不同的是,Set集合中不允许出现重复的元素(在服务器端完成多个set之间的聚合操作)
- Set可包含的最大元素数量是4294967295
存储set常用命令:
- 添加/删除元素
- 获得集合中的元素
- 集合中的差集运算
- 集合中的交集运算
- 集合中的并集运算
- 扩展命令
127.0.0.1:6379> sadd myset a b c // 添加元素
(integer) 3
127.0.0.1:6379> sadd myset a // 添加重复元素无效
(integer) 0
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> srem myset 1 2 // 删除元素
(integer) 2
127.0.0.1:6379> smembers myset // 查看set
1) "b"
2) "3"
3) "a"
4) "c"
127.0.0.1:6379> sismember myset a // 判断是否存在某一元素,1表示存在,0表示不存在
(integer) 1
127.0.0.1:6379> sismember myset x
(integer) 0
127.0.0.1:6379> sadd mya1 a b c
(integer) 3
127.0.0.1:6379> sadd myb1 a c 1 2
(integer) 4
127.0.0.1:6379> sdiff mya1 myb1 // 进行集合的差集运算,与key的顺序有关
1) "b"
127.0.0.1:6379> sadd mya2 a b c
(integer) 3
127.0.0.1:6379> sadd myb2 a c 1 2
(integer) 4
127.0.0.1:6379> sdiff mya1 myb1
1) "b"
127.0.0.1:6379> sadd mya2 a b c
(integer) 0
127.0.0.1:6379> sadd myb2 a c 1 2
(integer) 0
127.0.0.1:6379> sinter mya2 myb2 // 交集运算
1) "c"
2) "a"
127.0.0.1:6379> sadd mya3 a b c
(integer) 3
127.0.0.1:6379> sadd myb3 a c 1 2
(integer) 4
127.0.0.1:6379> sunion mya3 myb3 // 并集运算
1) "2"
2) "b"
3) "1"
4) "c"
5) "a"
127.0.0.1:6379> smembers myset // 获得set成员
1) "b"
2) "3"
3) "a"
4) "c"
127.0.0.1:6379> scard myset // 获得set成员数量
(integer) 4
127.0.0.1:6379> srandmember myset // 随机返回set中的成员
"3"
127.0.0.1:6379> srandmember myset
"a"
127.0.0.1:6379> sdiffstore my1 mya1 myb1 // 将两个集合先差的成员存储到某一个其他的集合中
(integer) 1
127.0.0.1:6379> smembers my1
1) "b"
127.0.0.1:6379> sinterstore my2 mya2 myb2 // 将两个集合交集的成员存储到某一个其他的集合中
(integer) 2
127.0.0.1:6379> smembers my2
1) "a"
2) "c"
127.0.0.1:6379> sunionstore my3 mya3 myb3 // 将两个集合交集的成员存储到某一个其他的集合中
(integer) 5
127.0.0.1:6379> smembers my3
1) "2"
2) "b"
3) "1"
4) "c"
5) "a"
set应用场景
可使用redis的set数据类型跟踪一些具有唯一性的一些数据,比如某一博客的唯一IP地址信息。还可以利用set服务器端聚合操作的方便高效的一些特性,可以用于维护数据对象之间的关联关系。
- 跟踪一些唯一性数据
- 用于维护数据对象之间的关联关系
存储Sorted-Set
- Sorted-Set和Set的区别(Sorted-Set中的每一个成员都会有一个分数与之关联,redis正是通过这个分数来为集合中的成员进行从小到大的一个排序,尽管Sorted-Set中的成员是惟一的,但是分数可以重复的,在Sorted-Set添加、删除和更新一个成员都是非常快速的操作。它的时间复杂度为集合中成员的个数的对数。)
- Sorted-Set中的成员在集合中的位置是有序的,访问位于集合中部的一些成员也是非常高效的。 (该特征是redis外其他类型数据库很难实现的,redis更高效)
- 游戏排名,微博热点话题。
存储Sorted-Set常用命令:
- 添加命令
- 获得元素
- 删除元素
- 范围查询
- 扩展命令
127.0.0.1:6379> zadd mysort 70 zs 80 ls 90 ww // 添加元素
(integer) 3
127.0.0.1:6379> zadd mysort 100 zs // 已经存在替换原有
(integer) 0
127.0.0.1:6379> zadd mysort 60 tom
(integer) 1
127.0.0.1:6379> zscore mysort zs // 获得元素
"100"
127.0.0.1:6379> zcard mysort // 获取成员数量
(integer) 4
127.0.0.1:6379> zrem mysort tom ww // 删除元素
(integer) 2
127.0.0.1:6379> zcart mysort
(error) ERR unknown command 'zcart'
127.0.0.1:6379> zcort mysort
(error) ERR unknown command 'zcort'
127.0.0.1:6379> zcard mysort
(integer) 2
127.0.0.1:6379> zadd mysort 85 jack 95 rose
(integer) 2
127.0.0.1:6379> zrange mysort 0 -1
1) "ls"
2) "jack"
3) "rose"
4) "zs"
127.0.0.1:6379> zrange mysort 0 -1 withscores // 显示全部元素及值
1) "ls"
2) "80"
3) "jack"
4) "85"
5) "rose"
6) "95"
7) "zs"
8) "100"
127.0.0.1:6379> zrevrange mysort 0 -1 withscores // 从大到小排名
1) "zs"
2) "100"
3) "rose"
4) "95"
5) "jack"
6) "85"
7) "ls"
8) "80"
127.0.0.1:6379> zremrangebyrank mysort 0 4 // 按照排名范围删除
(integer) 4
127.0.0.1:6379> zadd mysort 80 zs 90 ls 100 ws
(integer) 3
127.0.0.1:6379> zremrangebyscore mysort 80 100 // 按分数范围删除
(integer) 3
127.0.0.1:6379> zrange mysort 0 -1
(empty list or set)
127.0.0.1:6379> zadd mysort 70 zs 80 ls 90 ww
(integer) 3
127.0.0.1:6379> zrangebyscore mysort 0 100
1) "zs"
2) "ls"
3) "ww"
127.0.0.1:6379> zrangebyscore mysort 0 100 withscores limit 0 2
1) "zs"
2) "70"
3) "ls"
4) "80"
127.0.0.1:6379> zincrby mysort 3 ls
"83"
127.0.0.1:6379> zscore mysort ls // 增加3
"83"
127.0.0.1:6379> zcount mysort 80 90
(integer) 2
使用场景
- 大型游戏积分排行榜
- 构建索引数据
Keys的通用操作
127.0.0.1:6379> keys *
1) "mylist3"
2) "mylist"
3) "num"
4) "bum"
5) "my2"
6) "mylist5"
7) "myb3"
8) "num4"
9) "myhash"
10) "mysort"
11) "mylist6"
12) "mya1"
13) "my1"
14) "mya3"
15) "num2"
16) "myset"
17) "myb1"
18) "my3"
19) "myb2"
20) "mylist2"
21) "mylist4"
22) "mya2"
23) "num3"
24) "company"
25) "name"
127.0.0.1:6379> keys my?
1) "my2"
2) "my1"
3) "my3"
127.0.0.1:6379> del my1 my2 my3
(integer) 3
127.0.0.1:6379> exists my1 // 查看是否存在
(integer) 0
127.0.0.1:6379> exists mya1
(integer) 1
127.0.0.1:6379> get company
"baidu"
127.0.0.1:6379> rename company newcompany // 重命令
OK
127.0.0.1:6379> get company
(nil)
127.0.0.1:6379> get newcompany
"baidu"
127.0.0.1:6379> expire newcompany 100 // 设置过期时间
(integer) 1
127.0.0.1:6379> ttl newcompany // 该key所剩的超时时间
(integer) 76
127.0.0.1:6379> ttl newcompany
(integer) 49
127.0.0.1:6379> ttl mya1 // 未设置返回-1
(integer) -1
127.0.0.1:6379> type newcompany
string
127.0.0.1:6379> type mylist
list
127.0.0.1:6379> type myset
set
127.0.0.1:6379> type myhash
hash
127.0.0.1:6379> type mysort
zset
redis的特性
- 多数据库
- Redi事务
一个redis实例可以包含多个数据库,客户端可以指定连接某个redis实例的哪个数据库,客户端可以指定连接哪个数据库,一个redis实例最多可以连接提供16个数据库,下标从 0-15 ,客户端默认连接第0号数据库,也可以通过select选择连接哪个数据库。
127.0.0.1:6379> keys *
1) "mylist3"
2) "mylist"
3) "num"
4) "bum"
5) "mylist5"
6) "myb3"
7) "num4"
8) "myhash"
9) "mysort"
10) "mylist6"
11) "mya1"
12) "mya3"
13) "num2"
14) "myset"
15) "myb1"
16) "myb2"
17) "mylist2"
18) "mylist4"
19) "mya2"
20) "num3"
21) "name"
127.0.0.1:6379> get newcompany
(nil)
127.0.0.1:6379> move name 1 // 移动myset到1号数据库
(integer) 1
127.0.0.1:6379> keys *
1) "mylist3"
2) "mylist"
3) "num"
4) "bum"
5) "mylist5"
6) "myb3"
7) "num4"
8) "myhash"
9) "mysort"
10) "mylist6"
11) "mya1"
12) "mya3"
13) "num2"
14) "myset"
15) "myb1"
16) "myb2"
17) "mylist2"
18) "mylist4"
19) "mya2"
20) "num3"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "name"
事物机制:
- multi:相当于开启事务,后边的命令都会被存到命令的队列中
- exec:相当于关系型数据库的commit
- discard:相当于关系型数据库的rollback
客户端1:
127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> get num --> 转到客户端2
"1"
127.0.0.1:6379> get num
"2"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr num
QUEUED
127.0.0.1:6379> incr num --> 转到客户端2
QUEUED
127.0.0.1:6379> exec --> 转到客户端2
1) (integer) 3
2) (integer) 4
客户端2:
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num --> 转到客户端1
"2"
127.0.0.1:6379> get num --> 转到客户端1
"2"
127.0.0.1:6379> get num
"4"
127.0.0.1:6379> set user jack
QUEUED
127.0.0.1:6379> discard // 回滚
OK
127.0.0.1:6379> get user
(nil)
事务中所有命令都将被串行化顺序执行,事务执行期间redis不会为其他客户端提供任何服务,从而保证事务中的所有命令都被原子化执行,和关系型事务相比,在redis中,如果某个命令执行失败,后边的命令还会被执行。
Redis持久化
- RDB方式
- AOF方式
持久化使用的方式:
- RDB持久化:默认支持,在指定的时间间隔内将内存中的数据集快照写入到磁盘。
- AOF持久化:以日志的形式记录服务器所处理的每一个操作,在redis服务器启动之初,它会读取该文件来重新构建我们的数据库,保证启用后数据中的数据是完整的。
- 无持久化:通过配置来禁用redis持久化的功能
- 同时使用RDB和AOF
Redis的持久化的RDB的方式
优势:
- redis数据库将会只包含一个文件,对于文件备份而言是非常完美的。每个小时归档一次24小时的数据,每天归档一次最近30天的数据,可以通过这样的备份策略,出现灾难式的故障,可以非常容易恢复。可以对一个单独的RDB文件压缩后转移到其他的存储介质上。性能最大化,对于redis的服务进程而言,在开始持久化时,唯一需要做的只是分叉出一些进程,之后再由子进程完成持久化的操作,这样就可以极大地避免服务器进程执行IO的操作,相比AOF机制,如果数据集很大,RDB启动效率更高。
缺点:如果想保证数据的高可用性,最大限度避免数据的丢失,RDB并非一个最好的选择。因为系统一定在定时持久化之前出现一些宕机的情况,还没来得及往硬盘上写,数据则会丢失。 由于RDB通过fork分叉的方式子进程来协助完成数据持久化工作,因此如果当数据集非常大的时候,可能会导致整个服务器需要停止几百毫秒甚至是一秒钟。
配置:
save 900 1 // 每900秒至少有1个key发生变化,持久化一次
save 300 10 // 每300秒至少有10个key发生变化,往硬盘上写一次
save 60 10000 // 每60秒至少有10000个key发生变化,往硬盘上写一次
dbfilename dump.rdb // 数据的文件名
dir /usr/application/redis-4.0.9/data/redisData // 数据保存的位置
Redis的持久化的AOF的方式
优势:
1.带来更高的数据安全性。redis中有三种同步策略。每秒同步(异步完成,效率高,差的是一旦系统出现宕机,这一秒钟之内修改的数据会丢失)、每修改同步(同步持久化,每一次发生数据变化,都会被记录到磁盘当中,效率低,最安全)、不同步。
2.AOF文件是一个只进行追加(append模式)操作的日志文件,因此在写入过程中即使出现宕机现象也不影响之前已经存在的内容。
在redis下一次启动之前,redis-check-aof这个工具帮助我们解决数据一致性的问题。
3.如果日志过大,redis可以自动启动重写机制。redis以append这个模式不断地将修改的数据写入到老的磁盘文件中,同时redis还会创建一个新的文件用于记录此期间来产生的哪些修改命令被执行了,因此在进行重写切换的时候能更好的去保证数据的安全性。
4.AOF包含一个格式非常清晰,易于理解的日志文件用于记录所有的修改操作。可以通过这个文件完成数据重建。文件有序地保存了对数据库执行的所有写入操作
劣势:
1.对于相同数量的数据集而言,aof文件比rdb方式要大。
2.同步策略的不同,效率比rdb低。
配置
appendonly no // 默认情况下,aof模式未打开,使用时则改为yes
appendfilename "appendonly.aof" // 产生一个文件
// 同步策略设置
# appendfsync always // 每修改一次同步到磁盘
appendfsync everysec // 每秒修改一次同步到磁盘
# appendfsync no // 不同步