1.发布订阅模式(redis做消息中间件)
1.1简介
redis 可以做消息中间件(MQ =message queue),通常通过订阅发布模式来实现(消息订阅发布模式),还可以使用基本数据类型List实现(点到点模式,可以使用lpush,lpop 实现消息先进先出)。
1.2消息中间件好处
1.3redis实战
发布者publisher/生产者producer
消费者consumer/订阅者subscribe
数据库和作用域
订阅模式匹配
2.持久化RDB和AOF
2.1RDB(Redis DataBase)
2.1.1概念
指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)
2.1.2原理
:196
Save the DB on disk:
save <seconds> <changes>
save 900 1
save 300 10
save 60 10000
# after 900 sec (15 min) if at least 1 key changed 在900秒之内有至少1个key发生变化,执行保存
# after 300 sec (5 min) if at least 10 keys changed 在300秒之内有至少10个key发生变化,执行保存
# after 60 sec if at least 10000 keys changed 在60秒之内有至少10000个key发生变化,执行保存
81000*60=4860000条 60秒10000key变化很好满足的
2.1.2 优点
1,紧凑文件。RDB是一种表示某个即时点的Redis数据的紧凑文件。RDB文件适合用于备份。例如,你可能想要每小时归档最近24小时的RDB文件,每天保存近30天的RDB快照。这允许你很容易的恢复不同版本的数据集以容灾。
2,灾难恢复。RDB非常适合于灾难恢复,作为一个紧凑的单一文件,可以被传输到远程的数据中心,或者是Amazon 亚马逊 S3(可能得加密)。
3,RDB最大化了Redis的性能,因为Redis父进程持久化时唯一需要做的是启动(fork)一个子进程,由子进程完成所有剩余工作。父进程实例不需要执行像磁盘IO这样的操作。
4,RDB在重启保存了大数据集的实例时比AOF要快。(rbd备份数据 aof备份命令,恢复需要重新执行)
2.1.3 缺点
1,服务器宕机,丢失数据量大。当你需要在Redis停止工作(例如停电)时最小化数据丢失,RDB可能不太好。你可以配置不同的保存点(save point)来保存RDB文件(例如,至少5分钟和对数据集100次写之后,但是你可以有多个保存点)。然而,你通常每隔5分钟或更久创建一个RDB快照,所以一旦Redis因为任何原因没有正确关闭而停止工作,你就得做好最近几分钟数据丢失的准备了。
2,子进程备份可能影响主进程。RDB需要经常调用fork()子进程来持久化到磁盘。如果数据集很大的话,fork()比较耗时,结果就是,当数据集非常大并且CPU性能不够强大的话,Redis会停止服务客户端几毫秒甚至一秒。AOF也需要fork(),但是你可以调整多久频率重写日志而不会有损(trade-off)持久性(durability)。
2.2 AOF(Append Of File)
2.2.1 概念
AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
set a 1
lpush lista 11 22 33
zadd za aa bb cc 11 22 33
.....
2.2.2 原理
:699
默认情况下,Redis将数据集异步转储到磁盘上。此模式为在许多应用程序中都足够好,但Redis进程或断电可能会导致几分钟的写入丢失(取决于配置的保存点)。
仅附加文件是一种替代的持久化模式,它提供
更好的耐用性。
AOF和RDB持久性可以同时启用,没有问题。
如果启动时启用了AOF,Redis优先将加载AOF
三种aof持久化模式:
no: don't fsync, just let the OS flush the data when it wants. Faster. 从来不做AOF,除非手动执行flush,速度最快,最不安全
always: fsync after every write to the append only log. Slow, Safest. 总是,每次写命令都把写命令放入append.aof文件中,速度最慢,最安全。
everysec: fsync only one time every second. Compromise. 每秒中 写一次(多个命令)。不是最快的,也不是最慢的,不是最安全,也不是最不安全的。
2.2.3 优点
1,丢失数据少(最多丢1秒)。使用AOF Redis会更具有可持久性(durable):你可以有很多不同的fsync策略:没有fsync,每秒fsync,每次请求时fsync。使用默认的每秒fsync策略,写性能也仍然很不错(fsync是由后台线程完成的,主线程继续努力地执行写请求),即便你也就仅仅只损失一秒钟的写数据。
2,追加方式,快捷。AOF日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof工具也可以很轻易的修复。
3,重写防止文件过大,影响性能。当AOF文件变得很大时,Redis会自动在后台进行重写。重写是绝对安全的,因为Redis继续往旧的文件中追加,使用创建当前数据集所需的最小操作集合来创建一个全新的文件,一旦第二个文件创建完毕,Redis就会切换这两个文件,并开始往新文件追加。
4,AOF方便阅读。AOF文件里面包含一个接一个的操作,以易于理解和解析的格式存储。你也可以轻易的导出一个AOF文件。例如,即使你不小心错误地使用FLUSHALL命令清空一切,如果此时并没有执行重写,你仍然可以保存你的数据集,你只要停止服务器,删除最后一条命令,然后重启Redis就可以。
2.2.4 缺点
1,相同数据,AOF体积大。对同样的数据集,AOF文件通常要大于等价的RDB文件。
2,AOF可能比RDB慢,这取决于准确的fsync策略。通常fsync设置为每秒一次的话性能仍然很高,如果关闭fsync,即使在很高的负载下也和RDB一样的快。不过,即使在很大的写负载情况下,RDB还是能提供能好的最大延迟保证。
3,AOF对BUG免疫力没有RBD强。在过去,我们经历了一些针对特殊命令(例如,像BRPOPLPUSH这样的阻塞命令)的罕见bug,导致在数据加载时无法恢复到保存时的样子。这些bug很罕见,我们也在测试套件中进行了测试,自动随机创造复杂的数据集,然后加载它们以检查一切是否正常,但是,这类bug几乎不可能出现在RDB持久化中。为了说得更清楚一点:Redis AOF是通过递增地更新一个已经存在的状态,像MySQL或者MongoDB一样,而RDB快照是一次又一次地从头开始创造一切,概念上更健壮。但是,1)要注意Redis每次重写AOF时都是以当前数据集中的真实数据从头开始,相对于一直追加的AOF文件(或者一次重写读取老的AOF文件而不是读内存中的数据)对bug的免疫力更强。2)我们还没有收到一份用户在真实世界中检测到崩溃的报告。
3.redis事务
Redis使用MULTI, EXEC, DISCARD 和 WATCH 命令来实现事务功能。事务可以一次执行多个命令,并带有两个重要的保证:
隔离性:事务中的所有命令都被序列化并按顺序执行。Redis执行事务期间,不会被其它客户端发送的命令打断,事务中的所有命令都作为一个隔离操作顺序执行。
原子性:Redis事务是原子操作,或者执行所有命令或者都不执行。
4.实战问题
一般事务
127.0.0.1:6379> mset aa 11 bb 22 cc 33 dd 44
OK
127.0.0.1:6379> mget aa bb cc dd
1) "11"
2) "22"
3) "33"
4) "44"
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> incr aa #执行更新操作
QUEUED
127.0.0.1:6379> set bb 222
QUEUED
127.0.0.1:6379> decr cc
QUEUED
127.0.0.1:6379> incr dd
QUEUED
127.0.0.1:6379> exec #提交事务
1) (integer) 12
2) OK
3) (integer) 32
4) (integer) 45
127.0.0.1:6379> mget aa bb cc dd #一起修改了
1) "12"
2) "222"
3) "32"
4) "45"
127.0.0.1:6379> multi #开始事务
OK
127.0.0.1:6379> incr aa
QUEUED
127.0.0.1:6379> set bb 22
QUEUED
127.0.0.1:6379> decr cc
QUEUED
127.0.0.1:6379> incr dd
QUEUED
127.0.0.1:6379> discard #回顾事务
OK
127.0.0.1:6379> mget aa bb cc dd
1) "12"
2) "222"
3) "32"
4) "45"
特别事务
27.0.0.1:6379> set ee 'ee'
OK
127.0.0.1:6379> get ee
"ee"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr aa
QUEUED
127.0.0.1:6379> set bb 22
QUEUED
127.0.0.1:6379> incr ee
QUEUED
127.0.0.1:6379> decr cc
QUEUED
127.0.0.1:6379> incr dd
QUEUED
127.0.0.1:6379> exec
1) (integer) 13
2) OK
3) (error) ERR value is not an integer or out of range
4) (integer) 31
5) (integer) 46
127.0.0.1:6379> mget aa bb cc dd #出错依然会提交事务
1) "13"
2) "22"
3) "31"
4) "46"
解释原因
如果你了解关系数据库,那么Redis事务处理机制看起来有点奇怪。Redis事务中的命令允许失败,但是Redis会继续执行其它的命令而不是回滚所有命令。这么做的原因有两点:
Redis 命令只在两种情况失败:
语法错误的时候才失败(在命令输入的时候不检查语法)。
要执行的key数据类型不匹配:这种错误实际上是编程错误,这应该在开发阶段被测试出来,而不是生产上。
因为不需要回滚,所以Redis内部实现简单并高效。
乐观锁
WATCH 用于为 Redis 事务提供检查和设置 (CAS=Check And Set) 行为。使用watch监控一个或者多个key,如果想改变key的值时,要先判断别人是否更改,如果有别人改,我就不改,如果别人没改,我就改。
127.0.0.1:6379> watch aa bb cc dd
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr aa
QUEUED
127.0.0.1:6379> incr bb
QUEUED
127.0.0.1:6379> incr cc
QUEUED
127.0.0.1:6379> incr dd
QUEUED
127.0.0.1:6379> exec
1) (integer) 14
2) (integer) 23
3) (integer) 32
4) (integer) 47
127.0.0.1:6379> mget aa bb cc dd
1) "14"
2) "23"
3) "32"
4) "47"
127.0.0.1:6379> watch aa bb cc dd
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr aa
QUEUED
127.0.0.1:6379> incr bb
QUEUED
127.0.0.1:6379> incr cc
QUEUED
127.0.0.1:6379> incr dd
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> mget aa bb cc dd
1) "14"
2) "23"
3) "3333"
4) "47"
使用watch看着4个key,如果没有别的线程改,我就修改,如果有别的线程修改,我就不改
标签:AOF,127.0,0.1,redis,Redis,6379,QUEUED
From: https://www.cnblogs.com/xiaomubupi/p/18641681