ctags简易用法
前言
在分布式系统中,缓存和数据库同时存在时,如果有写操作的时候,先操作数据库还是先操作缓存呢?先思考一下,可能会存在哪些问题,再往下看。下面我分几种方案阐述。
缓存维护方案一
假设有一写(线程A)一读(线程B)操作,先操作缓存,在操作数据库。,如下流程图所示:

1)线程A发起一个写操作,第一步del cache
2)线程A第二步写入新数据到DB
3)线程B发起一个读操作,cache miss,
4)线程B从DB获取最新数据
5)请求B同时set cache
这样看,没啥问题。我们再看第二个流程图,如下:

1)线程A发起一个写操作,第一步del cache
2)此时线程B发起一个读操作,cache miss
3)线程B继续读DB,读出来一个老数据
4)然后老数据入cache
5)线程A写入了最新的数据
OK,酱紫,就有问题了吧,老数据入到缓存了,每次读都是老数据啦,缓存与数据与数据库数据不一致。
上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。
缓存维护方案二
双写操作,先操作缓存,在操作数据库。

1)线程A发起一个写操作,第一步set cache
2)线程A第二步写入新数据到DB
3)线程B发起一个写操作,set cache,
4)线程B第二步写入新数据到DB
这样看,也没啥问题。,但是有时候可能事与愿违,我们再看第二个流程图,如下:

1)线程A发起一个写操作,第一步set cache
2)线程B发起一个写操作,第一步setcache
3)线程B写入数据库到DB
4)线程A写入数据库到DB
执行完后,缓存保存的是B操作后的数据,数据库是A操作后的数据,缓存和数据库数据不一致。
缓存维护方案三
一写(线程A)一读(线程B)操作,先操作数据库,再操作缓存。
1)线程A发起一个写操作,第一步write DB
2)线程A第二步del cache
3)线程B发起一个读操作,cache miss
4)线程B从DB获取最新数据
5)线程B同时set cache
这种方案没有明显的并发问题,但是有可能步骤二删除缓存失败,虽然概率比较小,优于方案一和方案二,平时工作中也是使用方案三。
综上对比,我们一般采用方案三,但是有没有完美全解决方案三的弊端的方法呢?
缓存维护方案四
这个是方案三的改进方案,都是先操作数据库再操作缓存,我们来看一下流程图:
通过数据库的binlog来异步淘汰key,以mysql为例 可以使用阿里的canal将binlog日志采集发送到MQ队列里面,然后通过ACK机制 确认处理 这条更新消息,删除缓存,保证数据缓存一致性。
但是呢还有个问题,如果是主从数据库呢?
缓存维护方案五
主从DB问题:因为主从DB同步存在同时延时时间如果删除缓存之后,数据同步到备库之前已经有请求过来时,会从备库中读到脏数据,如何解决呢?解决方案如下流程图:
缓存维护总结
综上所述,在分布式系统中,缓存和数据库同时存在时,如果有写操作的时候,先操作数据库,再操作缓存。如下:
(1)读取缓存中是否有相关数据
(2)如果缓存中有相关数据value,则返回
(3)如果缓存中没有相关数据,则从数据库读取相关数据放入缓存中key->value,再返回
(4)如果有更新数据,则先更新数据,再删除缓存
(5)为了保证第四步删除缓存成功,使用binlog异步删除
(6)如果是主从数据库,binglog取自于从库
(7)如果是一主多从,每个从库都要采集binlog,然后消费端收到最后一台binlog数据才删除缓存
ctags简易用法的更多相关文章
- (转载)php之call_user_func_array的简易用法
(转载)http://www.cnitblog.com/neatstudio/archive/2006/07/21/13990.html php之call_user_func_array的简易用法 今 ...
- VIM+ctags+cscope用法
使用vim + cscope/ctags,就能够实现Source Insight的功能,可以很方便地查看分析源代码. 关键词: vim, cscope, ctags, tags 1. 查看vi ...
- ctags高级用法
1.ctags -R 有个问题,成员变量没有包含在里面.所以自动完成对象的成员时没有提示.解决办法:$ctags -R --fields=+iaS --extra=+q *–fields=[+|-]f ...
- ctags简明用法
1.安装: sudo apt install ctags 2.生成tags文件: //进入目标目录 ctags -R . 3.在vim中设置tags的绝对目录,这样就可以在任何子目录使用了. :set ...
- Boost中timer的简易用法
boost::asio::deadline_timer timer_; timer_(io_service), timer_.expires_from_now(boost::posix_time::s ...
- Linux - gcc 的简易用法 (编译、参数与链结)
# 仅将原始码编译成为目标档,并不制作连结等功能: [root@www ~]# gcc -c hello.c # 会自动的产生 hello.o 这个文件,但是并不会产生 binary 运行档. # 在 ...
- Oracle游标的简易用法
create or replace procedure NW_DelYW(iOPERATION_ID number, sUserID varchar2) is sCurDJBH yw_operatio ...
- 使用VIM插件ctags来阅读C代码
说明 Ctags是vim下方便代码阅读的工具.尽管ctags也可以支持其它编辑器,但是它正式支持的只有vim.并且vim中已经默认安装ctags,它可以帮助程序员很容易地浏览源代码:ctags最先是用 ...
- Android ORMLite 框架的入门用法
大家在Android项目中或多或少的都会使用数据库,为了提高我们的开发效率,当然少不了数据库ORM框架了,尤其是某些数据库操作特别频繁的app:本篇博客将详细介绍ORMLite的简易用法. 下面开始介 ...
随机推荐
- [javase学习笔记]-7.2 构造函数与一般函数的差别
这一节我们简单学习一下构造函数与一般函数之间的差别所在. 那么它们有什么差别呢,结合上一节,我们能够总结出下面两点差别: 第一个差别: 构造函数:对象创建时,就会调用与之相应的构造函数,对对象进行初始 ...
- C#基础第九天-作业答案-储蓄账户(SavingAccount)和信用账户(CreditAccount)
class Bank { //Dictionary<long,Account> dictionary=new Dictionary<long,Account>(); DataT ...
- Feign请求中报错:Request header is too large 的解决方案。
现在我们项目中都已迁入spring boot和spring cloud. 服务间调用现在都改成feign的调用方式,但是上次在实际使用过程中出现过:Request header is too larg ...
- 集群扩容的常规解决:一致性hash算法
写这篇博客是因为之前面试的一个问题:如果memcached集群需要增加机器或者减少机器,那么其他机器上的数据怎么办? 最后了解到使用一致性hash算法可以解决,下面一起来学习下吧. 声明与致谢: 本文 ...
- php的opcode缓存
前言:由php的运行机制决定,其实php在运行阶段我们也是可以进行缓存的从而提高程序运行效率,这就是我们常说的opcode缓存.1.简述php的运行机制(因为本文是写opcode缓存的所以这里只是简要 ...
- java服务端技术
服务端框架:1.servlet2.netty 协议:1.http 1.02.http 1.1 数据库:mysql 对象关系映射(ORM)框架:mybatis 缓存:redis eclipse能运行,导 ...
- redis 指定IP访问
配置IPTABLES -A INPUT -s 10.100.0.5 -p tcp --dport 6379 -j ACCEPT -A INPUT -s 10.100.0.219 -p tcp --dp ...
- View:Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()的理解
Android系统手机屏幕的左上角为坐标系,同时y轴方向与笛卡尔坐标系的y轴方向想反.提供了 getLeft(), getTop(), getBottom(), getRight() 这些API来获取 ...
- 10-free-must-read-books-machine-learning-data-science
Spring. Rejuvenation. Rebirth. Everything’s blooming. And, of course, people want free ebooks. With ...
- matlab问题集总
每次更新一点,慢慢增加 nargin nargin是用来判断输入变量个数的函数,这样就可以针对不同的情况执行不同的功能.通常可以用他来设定一些默认值,如下面的函数. 例子,函数test1的功能是输出a ...