-
事务
-
ACID原子性、一致性、隔离性和持久性。
-
redis事务中任意命令执行失败,其余命令依然执行。它不保证事务的原子性,也不支持回滚。事务中的多条命令一次性发给服务器,服务器在执行事务的过程中不会执行其它客户端的命令请求。它做到了隔离性,原子性无法保证。
-
redis数据持久化
-
rdb 全量持久化
rdb 通过save或bgsave触发,然后父进程执行fork操作创建子进程(创建过程会阻塞);子进程创建 rdb文件,根据父进程内存(这个内存需要拷贝)生成临时快照文件;完成后对原有文件进行原子替换(定时一次性将所有数据进行快照生成一份副本存储在硬盘中)。
优点:是一个紧凑压缩二进制文件,redis加载rdb恢复数据远快于aof方式。
缺点:每次生成rdb开销大,非实时持久化。 -
aof 增量持久化
aof 开启后,redis每执行一个修改数据的命令,都会把这个命令添加到aof文件中。查询不会写日志操作,修改和删除会写入日志操作。
优点:
1、实时持久化。
2、可以设置不同的策略,如fsync 1s一次,这样最多丢失1s的数据,默认是1s一次,这种配置下,redis性能依然保持比较好。
3、aof文件是一个只进行追加操作的日志文件(append only log),因为对aof文件的写入不需要进行seek。redis可以在aof文件体积变得过大时,自动地在后台对aof进行重写,重写后的aof文件包含了恢复当前数据集所需的最小命令集合。整个重写操作绝对安全,因为在redis创建aof文件的过程中,会继续将命令追加到现在的aof文件里面,即使重写过程中发生停机,现有的aof文件也不会丢失。而一旦新的aof文件创建完毕,redis就会从旧的aof文件切换到新的aof,并开始对新aof文件进行追加操作。
缺点:
1、由于aof文件体积逐渐变大,需要定期执行重写操作来降低文件体积,加载慢。
2、对于相同的数据集,aof文件体积比rdb要大。
3、根据所使用的fsync策略,aof的速度可能会低于rdb。关闭fsync策略可以让aof的速度和rdb一样快。 -
redis单线程为什么快
-
单线程避免线程竞争,使用内存减少磁盘io,多路复用模型,用了缓冲区概念。
-
虚拟内存
当key很小,value很大时,使用vm的效果会比较好,因为节约的内存比较大。
当key不小时,可以考虑使用一些方法,将很大的key变成很大的value,比如可以考虑将key,value组合成一个新的value。vm-max-threads可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成长时间的延迟,但对数据完整性有很好的保证。 -
热点数据回收
将db中的常用数据缓存至redis,6种回收策略
-
1 volatile-lur:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。
-
2 volatile-ttl:从已设置过期时间的数据集(server.db[i[].expires)中挑选将要过期的数据淘汰。
-
3 volatile-random:从已设置过期时间的数据集(server.db[i].expires)任选选择数据淘汰。
-
4 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰。
-
5 allkeys-ttl:从数据集中(server.db[i].dict)中任意选择数据淘汰。
-
6 no-enviction(驱逐):禁止驱逐数据。永不回收。
volatile表示从过期的数据集中,allkeys表示从所有的数据集中。
使用策略规则:
1、如果数据呈现幂等分布,就是一部分数据访问频率高,一部分访问频率低,则使用allkeys-lru。
2、如果数据呈现平均分布,也就是所有数据的访问频率相同,则使用allkeys-random。
ttl和random好理解,lru使用最近最少使用的策略,设计上会对key按失效时间排序,然后取最先失效的key进行淘汰。 -
锁
参考
redis是单进程,单线程,它利用队列技术将并发访问变为串行访问,消除了传统数据库进行串行控制的开销。 -
解决并发竞争
redis采用队列模式,将并发访问变为串行访问。它本身没有锁的概念。redis对于多个客户端连接并不存在竞争,但是jedis客户端进行并发访问时会造成连接超时、数据转换错误、阻塞、客户端关闭等问题。这都会造成客户端混乱。
解决并发竞争
1.客户端角度,对连接进行池化,同时对客户端读写redis操作采用内部锁synchronized。
2.服务器角度,利用setnx实现锁。 -
事务cas(check-and-set)
redis执行事务过程中,不会为其它客户端的请求提供任何服务。这样可以保证事务中的所有命令被原子的执行。
redis事务中如果某一条命令执行失败,其后的命令仍然会被继续执行。
multi exec discard watch
如果中途机器崩溃,要看exec执行的时间点是在崩溃前或是在写入的过程中,断电前崩溃的话,会执行完事务。如果是在写入的过程中,也许会有部分的数据写入,部分的丢失。
redis重启时会进行一些必要的一致性检测。redis-check-aof
工具,可以帮我们定位到数据不一致的错误,并将已写入的部分数据进行回滚。 -
watch命令和基于cas的乐观锁
redis事务中,watch命令可提供cas(check-and-set)功能。
假如我们通过watch命令在事务执行之前监控了多个keys,倘若在watch之后有任何key的值发生了变化,exec命令执行的事务都将被放弃,同时返回null mlti-bulk应答来通知调用者事务执行失败。
watch mykey
val = get meykey
val = val+1
multi
set mykey $val
exec
这段代码在获取mykey之前,进行监控,此后将set命令包围在事务中,这样就可以保证每个连接在执行exec之前,如果当前获取的mykey的值被其它连接的客户端修改,那么当前连接的exec命令将执行失败。这样调用者在判断返回值后就可以获悉val是否被重新设置成功。 -
缓存失效策略和主键失效机制
redis中,有生存期的key被称为volatile。在创建缓存时,要为给定的key设置生存期,当key过期时,生存期为0,可能会被删除。
-
1.影响生存时间的操作
del、set、getset来删除或覆盖原有数据。修改之后,生存时间会与之前不同。
比如对一个key进行incr,列表lpush或哈希表执行hset命令,这类操作不会修改key的生存时间。如果rename一个key,改名后的key的生存时间和之前相同。
rename命令的另一种可能是,尝试将一个带生存时间的key改名成另一个带生存时间的another_key,这时旧的another_key(以及它生存时间)会被删除,然后旧的key会改名为another_key,因此新的another_key的生存时间也和原来的key一样。使用persist命令可以在不删除key的情况下,移除key的生存时间,让key生新成为一个persistent key -
2.如何更新生存时间
expire命令 时间复杂度o(1)
expire ttl命令搭配使用,ttl可以查看key的当前生存时间,设置成功返回1;当key不存在或不可设置生存时间时返回0。
最大缓存配置 server.maxmemory,如果为0,表示没有指定,如果有新数据添加超最大内存,会导致redis崩溃。所以一定要设置,当数据集上升到一定大小的时值,会实行数据淘汰策略。
可视化工具有redis client以及redis desktop manager可以用下看看。
redis 总结
最新推荐文章于 2022-08-15 15:28:38 发布