读写同步-读优先-读写分离-Redis缓存使用的三种模式 (读写训练)
在互联网应用中,缓存技术是提高系统性能和稳定性的重要手段之一。作为一种高性能的缓存数据库,Redis被广泛应用于各种互联网应用中。本文将介绍Redis缓存使用的三种模式,包括CacheAside(旁路缓存)、Read/WriteThrough(读写穿透)和WriteBehindCaching(异步缓存写入),以及它们的适用场景和优缺点。
一、CacheAside(旁路缓存)
1.1 概念介绍
CacheAside是一种常见的缓存模式,也是最简单的一种缓存模式。在CacheAside模式中,应用程序首先从缓存中读取数据,如果缓存中不存在,则从数据库中读取数据,并将数据写入缓存中。在更新数据时,应用程序首先更新数据库中的数据,然后删除缓存中的数据。当下一次请求到来时,应用程序会从数据库中读取最新的数据,并将其写入缓存中。CacheAside模式的优点是简单易用,缓存和数据库之间的数据一致性较好。但是,由于应用程序需要手动维护缓存和数据库之间的数据一致性,因此在高并发场景下,容易出现缓存和数据库之间的数据不一致的情况。
1.2 适用场景
适用于读多写少的场景,数据一致性要求不高的场景。二、Read/WriteThrough(读写穿透)
2.1 概念介绍
Read/WriteThrough是一种将缓存和数据库完全解耦的缓存模式。在Read/WriteThrough模式中,应用程序不直接访问缓存和数据库,而是通过一个中间层来访问缓存和数据库。当应用程序需要读取数据时,中间层首先从缓存中读取数据,如果缓存中不存在,则从数据库中读取数据,并将数据写入缓存中。当应用程序需要更新数据时,中间层会将更新操作发送到数据库中,并更新缓存中的数据。Read/WriteThrough模式的优点是完全解耦缓存和数据库,可以有效地提高系统的并发能力和可扩展性。但是,由于中间层需要处理缓存和数据库之间的数据一致性,因此实现起来较为复杂。
2.2 适用场景
适用于读多写多的场景,数据一致性要求较高的场景。三、WriteBehindCaching(异步缓存写入)
3.1 概念介绍
WriteBehindCaching是一种将缓存和数据库异步写入的缓存模式。在WriteBehindCaching模式中,应用程序首先将更新操作写入缓存中,然后异步地将更新操作写入数据库中。当下一次请求到来时,应用程序会从缓存中读取数据,并将其写入数据库中。WriteBehindCaching模式的优点是可以有效地提高系统的写入性能,减少数据库的压力。但是,由于缓存和数据库之间存在一定的时间差,因此在数据一致性方面需要进行一定的权衡。
3.2 适用场景
适用于写多读少的场景,数据一致性要求不高的场景。四、总结
在使用Redis缓存时,应根据具体的业务场景和需求选择合适的缓存模式。CacheAside模式简单易用,适用于读多写少的场景;Read/WriteThrough模式完全解耦缓存和数据库,适用于读多写多的场景;WriteBehindCaching模式可以提高写入性能,适用于写多读少的场景。在实际应用中,可以根据具体的业务需求和性能要求,选择合适的缓存模式,以提高系统的性能和稳定性。
redis是怎么实现的
第一:Redis 是什么?
Redis是基于内存、可持久化的日志型、Key-Value数据库 高性能存储系统,并提供多种语言的API.
第二:出现背景
Redis早期的主从架构原理分析,早期如何实现读写分离的?
基于主从复制架构,实现读写分离,redis slave node节点只读,默认开启配置:slave-read-only yes。开启了只读的节点redis slave node,会拒绝所有写操作,这样可以强制搭建成读写分离的架构。
(1)redis采用异步方式复制数据到slave节点。
(2)一个master node是可以配置多个slave node的。
(3)slave node也可以连接其他的slave node。
(4)slave node做复制的时候,是不会block master node的正常工作的。
(5)slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了。
(6)slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量。
如果采用了主从架构,那么建议必须开启master node的持久化!不建议用slave node作为master node的数据热备,因为那样的话,如果你关掉master的持久化,可能在master宕机重启的时候数据是空的,然后可能一经过复制,salve node数据也丢了。
(1)当启动一个slave node的时候,它会发送一个 PSYNC 命令给master node。
(2)如果这是slave node 重新连接 master node,那么master node仅仅会 复制给slave部分缺少的数据 ,否则如果是slave node 第一次连接 master node,那么会触发一次 full resynchronization ,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令 缓存在内存中 。RDB文件生成完毕之后,master会先将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中 缓存的写命令 发送给slave,slave也会同步这些数据。
(3)slave node如果跟master node有网络故障,断开了连接,会自动重连。master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node。
从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制。master node会在内存中建一个 backlog ,master和slave都会保存一个 replica offset 还有一个 master id(run id) ,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制,但是如果没有找到对应的offset,那么就会执行一次full resynchronization全量同步。
master在内存中直接创建rdb,然后发送给slave,不会在自己本地落地磁盘了。
repl-diskless-sync no 改为开启就可以了
repl-diskless-sync-delay,等待一定时长再开始复制,因为要等更多slave重新连接过来,用一分数据提供服务。
slave node不会过期key,只会等待master过期key。如果master过期了一个key,或者通过LRU淘汰了一个key,那么会模拟一条del命令发送给slave。
(1)slave node启动,仅仅保存master node的信息,包括master node的host和ip,但是复制流程没开始。master host和ip是从哪儿来的?里面的slaveof配置的。
(2)slave node内部有个定时任务,每秒检查是否有新的master node要连接和复制,如果发现,就跟master node建立socket网络连接。
(3)slave node发送ping命令给master node。
(4)口令认证,如果master设置了requirepass(master上启用安全认证配置,requirepass自己取名 ),那么salve node必须发送masterauth的口令过去进行认证(masterauth自己取名 )
(5)master node第一次执行全量复制,将所有数据发给slave node。
(6)master node后续持续将写命令,增量异步复制给slave node。
指的就是第一次slave连接msater的时候,执行的全量复制,这个过程里面的一些细节的机制
(1)master和slave都会维护一个offset
master会在自身不断累加offset,slave也会在自身不断累加offset。slave每秒都会上报自己的offset给master,同时master也会保存每个slave的offset。这个倒不是说特定就用在全量复制的,主要是master和slave都要知道各自的数据的offset,才能知道互相之间的数据不一致的情况。
(2)backlog
master node有一个backlog,默认是1MB大小,master node给slave node复制数据时,也会将数据在backlog中同步写一份。backlog主要是用来做全量复制中断后的增量复制的。
(3)master run id
info server命令,可以看到master run id。如果根据host+ip定位master node,是不靠谱的,如果master node重启或者数据出现了变化,那么slave node应该根据不同的run id区分,run id不同就做全量复制。如果需要不更改run id重启redis,可以使用redis-cli debug reload命令。
从节点使用psync从master node进行复制psync runid offset。master node会根据自身的情况返回响应信息,可能是FULLRESYNC runid offset触发全量复制,可能是继续触发增量复制。
(1)master执行bgsave,在本地生成一份rdb快照文件。
(2)master node将rdb快照文件发送给salve node,如果rdb复制时间超过60秒(repl-timeout),那么slave node就会认为复制失败,可以适当调节大这个参数。
(3)对于千兆网卡的机器,一般每秒传输100MB,6G文件,很可能超过60s。
(4)master node在生成rdb时,会将所有新的写命令缓存在内存中,在salve node保存了rdb之后,再将新的写命令复制给salve node。
(5)client-output-buffer-limit slave 256MB 64MB 60,如果在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,或复制时间超过60秒,那么停止复制,复制失败。
(6)slave node接收到rdb之后,然后重新加载rdb到自己的内存中,同时基于旧的数据版本对外提供服务,写入后,清空自己的旧数据,用新的对外提供读服务。
(7)如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF。在这个过程中,rdb生成、rdb通过网络拷贝、slave旧数据的清理、slave node aof rewrite,很耗费时间的。
(1)如果全量复制过程中,master-slave网络连接断掉,那么salve重新连接master时,会触发增量复制。
(2)master直接从自己的backlog中获取部分丢失的数据,发送给slave node,默认backlog就是1MB。
(3)master就是根据slave发送的psync中的offset来从backlog中获取数据的。
下节讲解哨兵架构,在讲之前,你能否处理下面两个问题呢?
1、异步复制导致的数据丢失
哨兵可以解决主从架构下,因master宕机后不能接收写请求而进行选举salve为新的master,达到高可用的效果。
因为master -> slave的复制是异步的,所以可能有部分数据还没复制到slave,master就宕机了,此时这些部分数据就丢失了,此时应该怎么处理?
2、脑裂导致的数据丢失
脑裂,也就是说,某个master所在机器突然脱离了正常的网络,跟其他slave机器不能连接,但是实际上master还运行着。
此时哨兵可能就会认为master宕机了,然后开启选举,将其他slave切换成了master这个时候,集群里就会有两个master,也就是所谓的脑裂。
此时虽然某个slave被切换成了master,但是可能client还没来得及切换到新的master,还继续写向旧master的数据可能也丢失了,因此旧master再次恢复的时候,会被作为一个slave挂到新的master上去,自己的数据会清空,重新从新的master复制数据,导致数据丢失,怎么处理脑裂导致的数据丢失呢?
先考虑一下,我们下节进行讲解。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。