将“
操作
+
数据
”
以格式化指令的方式追加到操作日志文件的尾部,在
append
操作返回后
(
已经
写入到文件或者将要写入
)
,才进行实际的数据变更,
“
日志文件
”
保存了历史所有的操作过程;当
server
需要数据恢复时,可以直接
replay
此日志文件,即可还原所有的操作过程。
AOF
相对可靠,
AOF
文件内容是字符串,非常
容易阅读和解析。
优点:
可以保持更高的数据完整性,如果设置追加 fifile
的时间是
1s
,如果
redis
发生故障,最多会丢失
1s
的数
据;且如果日志写入不完整支持
redis-check-aof
来进行日志修复;
AOF
文件没被
rewrite
之前(文件过大时会对
命令进行合并重写),可以删除其中的某些命令(比如误操作的
flflushall
)。
缺点:
AOF
文件比
RDB
文件大,且恢复速度慢。
我们可以简单的认为 AOF
就是日志文件,此文件只会记录
“
变更操作
”(
例如:
set/del
等
)
,如果
server
中持续的大
量变更操作,将会导致
AOF
文件非常的庞大,意味着
server
失效后,数据恢复的过程将会很长;事实上,一条数据经过多次变更,将会产生多条
AOF
记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为
AOF持久化模式还伴生了
“AOF rewrite。
Redis主从复制
持久化保证了即使redis
服务重启也不会丢失数据,但是当
redis
服务器的硬盘损坏了可能会导致数据丢失,通
过
redis
的主从复制机制就可以避免这种单点故障(单台服务器的故障)。
主redis
中的数据和从上的数据保持实时同步
,
当主
redis
写入数据时通过主从复制机制复制到两个从服务上。
主从复制不会阻塞master
,在同步数据时,
master
可以继续处理
client
请求
.
主机master
配置
:
无需配置;
若出现宕机,则选择一个从机提升为主机继续服务。
复制原理
当从库和主库建立MS(master slaver)
关系后,会向主数据库发送
SYNC
命令;
主库接收到SYNC
命令后会开始在后台保存快照(
RDB
持久化过程),并将期间接收到的写命令缓存起来;
快照完成后,
主
Redis
会将快照文件和所有缓存的写命令发送给从
Redis
;
从Redis
接收到后,会载入快照文件并且执行收到的缓存命令;
主Redis
每当接收到写命令时就会将命令发送从
Redis
,保证数据的一致;【内部完成
,
所以
不支持客户端在从
机人为写数据
。】
Redis哨兵模式
哨兵的作用就是对Redis
系统的运行情况监控,它是一个独立进程
,
它的功能:
1. 监控主数据库和从数据库是否运行正常;
2. 主数据出现故障后自动将从数据库转化为主数据库;
如果主机宕,开启选举工作,选择一个从做主机。
总结:
主从集群:主机有写入权限。从机没有,只有可读。
意外宕机方案:
手动恢复:人为重启服务器,主机宕,把从机设置为主机。
自动恢复:使用哨兵监控。自动切换主从。
缓存
广义的缓存就是在第一次加载某些可能会复用数据的时候,在加载数据的同时,将数据放到一个指定的地点做保
存。再下次加载的时候,从这个指定地点去取数据。这里加缓存是有一个前提的,就是从这个地方取数据,比从数
据源取数据要快的多。
java狭义一些的缓存,主要是指三大类
1. 虚拟机缓存(
ehcache
,
JBoss Cache
)
2. 分布式缓存(
redis
,
memcache
)
3. 数据库缓存
正常来说,速度由上到下依次减慢
缓存雪崩
由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间(缓存正常从
Redis
中获取,如下图)所有原本应该访问缓存的请求都去查询数据库了,而对数据库
CPU
和内存造成巨大压力,
严重的会造成数据库宕机,造成系统的崩溃。
解决方案:
1.在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key
只允许一个线程查询数据
和写缓存,其他线程等待。虽然能够在一定的程度上缓解了数据库的压力但是与此同时又降低了系统的吞吐量。
2. 分析用户的行为,不同的key
,设置不同的过期时间,让缓存失效的时间点尽量均匀。
缓存穿透
缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
解决方案:
1.如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问
数据库,这种办法最简单粗暴。
2.把空结果,也给缓存起来,这样下次同样的请求就可以直接返回空了,既可以避免当查询的值为空时引起的缓存
穿透。同时也可以单独设置个缓存区域存储空值,对要查询的
key
进行预先校验,然后再放行给后面的正常缓存处
理逻辑。
缓存击穿
对于一些设置了过期时间的key
,如果这些
key
可能会在某些时间点被超高并发地访问,是一种非常
“
热点
”
的数据。
这个时候,需要考虑一个问题:缓存被
“
击穿
”
的问题,这个和缓存雪崩的区别在于这里针对某一
key
缓存,前者则是
很多
key
。
解决办法:
①使用锁,单机用synchronized,lock
等,分布式用分布式锁。
②缓存过期时间不设置,而是设置在key
对应的
value
里。如果检测到存的时间超过过期时间则异步更新缓存。
热点key:
某个key
访问非常频繁,当
key
失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃。