读完这篇文章,就基本搞定了Redis数据库( 四 )


 
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令 。
 
当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致 。
 
最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作 。
 Redis 事务
 
Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能 。
 
事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制 。
 
并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求 。
 
在传统的关系式数据库中,常常用 ACID 性质来检验事务功能的可靠性和安全性 。
 
在 Redis 中,事务总是具有原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),并且当 Redis 运行在某种特定的持久化模式下时,事务也具有持久性(Durability) 。
 
缓存雪崩和缓存穿透问题解决方案
 
缓存雪崩
 
简介:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉 。

读完这篇文章,就基本搞定了Redis数据库

文章插图
 
解决办法:
  • 事前:尽量保证整个 Redis 集群的高可用性,发现机器宕机尽快补上 。选择合适的内存淘汰策略 。
  • 事中:本地 Ehcache 缓存 + Hystrix 限流&降级,避免 MySQL 崩掉 。
  • 事后:利用 Redis 持久化机制保存的数据尽快恢复缓存 。
 
缓存穿透
 
简介:一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉 。
 
解决办法:有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中 。
 
一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力 。
 
另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟 。
 如何解决 Redis 的并发竞争 Key 问题
 
所谓 Redis 的并发竞争 Key 的问题也就是多个系统同时对一个 Key 进行操作,但是最后执行的顺序和我们期望的顺序不同,这样也就导致了结果的不同!
 
推荐一种方案:分布式锁(ZooKeeper 和 Redis 都可以实现分布式锁) 。(如果不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能)
 
基于 ZooKeeper 临时有序节点可以实现的分布式锁 。大致思想为:每个客户端对某个方法加锁时,在 ZooKeeper 上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点 。
 
判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个 。当释放锁的时候,只需将这个瞬时节点删除即可 。
 
同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题 。完成业务流程后,删除对应的子节点释放锁 。
 
在实践中,当然是以可靠性为主 。所以首推 ZooKeeper 。
 如何保证缓存与数据库双写时的数据一致性
 
你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?
 
一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶尔有不一致的情况 。
 
最好不要做这个方案,读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况 。
 
串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个请求 。
 
参考文章: