先操作数据库还是先操作缓存-并发环境下的数据操作顺序 (先操作数据库还是先删缓存)
问题提出
在分布式系统中,缓存和数据库同时存在时,如果有写操作的时候,先操作数据库还是先操作缓存呢?
先思考一下,可能会存在哪些问题,再往下看。
缓存维护方案
方案一:先操作缓存,再操作数据库
流程图如下:
分析:这种方案看似没有问题,但存在并发问题。当线程A写操作时,线程B可能同时发起读操作,此时缓存中没有数据,线程B会从数据库中获取最新数据。但是,线程A随后将新数据写入数据库,导致缓存与数据库数据不一致。
方案二:双写操作,先操作缓存,再操作数据库
流程图如下:
分析:这种方案可以解决并发问题,但仍然存在数据不一致的问题。如果线程A和线程B同时发起写操作,线程B可能在写入数据库之前先将数据写入缓存。这样,缓存中保存的是线程B操作后的数据,而数据库中保存的是线程A操作后的数据。
方案三:先操作数据库,再操作缓存
流程图如下:
分析:这种方案没有明显的并发问题,但有可能删除缓存失败。虽然这种可能性很小,但优于方案一和方案二,平时工作中也是使用方案三。
方案四:先操作数据库,再操作缓存,使用binlog异步淘汰key
流程图如下:
分析:这种方案是方案三的改进方案,通过数据库的binlog来异步淘汰key。这样可以保证数据缓存一致性。但是,如果存在主从数据库,则需要考虑主从同步延迟的问题。
方案五:先操作数据库,再操作缓存,主从数据库问题解决
流程图如下:
分析:这种方案解决了主从数据库问题。但如果是一主多从,每个从库都要采集binlog,然后消费端收到最后一台binlog数据才删除缓存。
缓存维护总结
在分布式系统中,缓存和数据库同时存在时,如果有写操作的时候,一般采用先操作数据库,再操作缓存的策略。具体流程如下:
- 读取缓存中是否有相关数据。
- 如果缓存中有相关数据value,则返回。
- 如果缓存中没有相关数据,则从数据库读取相关数据放入缓存中key->value,再返回。
- 如果有更新数据,则先更新数据,再删除缓存。
- 为了保证第四步删除缓存成功,使用binlog异步删除。
- 如果是主从数据库,binglog取自于从库。
- 如果是一主多从,每个从库都要采集binlog,然后消费端收到最后一台binlog数据才删除缓存。
如何处理大量数据并发操作
一.处理方法:缓存:文件缓存,数据库缓存数据库:sql优化,表的横向和纵向划分代码:优化代码结构二、高并发架构:1、HTML静态化 大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。 但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录 入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。 同 时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论 坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分 内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。 2、图片服务器分离 对于Web服务器来说,不管 是 Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服 务器,甚至很多台图片服务器。 这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器 上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗 和执行效率。 3、数据库集群和库表散列 大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。 在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。 上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最 有效的解决方案。 我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能 进行更小的,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。 sohu的论坛就是采用了这样的架 构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统 随时增加一台低成本的数据库进来补充系统性能。 4、缓存 缓存一词搞技术的都接触过,很多地方用到缓存。 网站架构和网站开发中的缓存也是非常重要。 这里先讲述最基本的两种缓存。 架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。 网 站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大 型社区使用了这样的架构。 另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多 了,不是很熟悉,相信也肯定有。 5、镜像 镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网 络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实 时更新。 6、负载均衡
如何保证缓存与数据库的双写一致性
一、涉及到的操作缓存:读、写、更新、删除,这些操作可能失败数据库:读、写、更新、删除,这些操作可能失败二、正常流程1. 读数据,先读缓存,命中返回数据;未命中读数据库,返回数据,写缓存;读数据不存在不一致问题2. 写数据库,对缓存不做处理3. 更新数据库数据,如果数据不在缓存中,不作处理;如果数据在缓存中,删除而不是更新缓存a. 有些缓存中的数据,是经过处理后的数据,如果更新会消耗计算资源b. 如果频繁更新,却没有读取,就会浪费计算时间和内存空间4. 删除数据库数据,如果数据不在缓存中,不作处理;如果数据在缓存中,删除缓存三、初级的数据不一致问题更新数据库数据的时候,如果更新数据库数据成功,删除缓存数据失败,则数据不一致四、解决方法:更新数据库数据时,先删除缓存,可以保证一致性a. 如果删除缓存失败,则更新失败b. 如果删除缓存成功,但是更新数据库失败,则缓存中没有数据,数据库是旧数据五、复杂的数据不一致的问题在删除缓存后,更新数据库还未成功,此时有请求读取数据库旧数据,并把旧数据写入了缓存,然后更新数据库成功六、解决方法设置缓存过期时间,保证最终数据一致性如何保证缓存与数据库的双写一致性标签:成功更新删除读取nbsp数据而不是内存设置
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。