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的简易用法. 下面开始介 ...
随机推荐
- Debian本地镜像长时间不更新
一.执行apt-get update 使用一个长期未更新的本地源,得到错误的提示: Release file for ... is expired. Updates for this reposito ...
- oracle中exists和in的比较
exists 是Oracle sql中的一个函数.表示是否存在符合某种条件的记录.如 select * from A,B where A.id=B.id and exists (SELECT * FR ...
- python标准库介绍——29 zlib 模块详解
==zlib 模块== (可选) ``zlib`` 模块为 "zlib" 压缩提供支持. (这种压缩方法是 "deflate".) [Example 2-43 ...
- 将Android Studio默认布局ConstraintLayout切换成LinearLayout
将Android Studio默认布局ConstraintLayout切换成LinearLayout 大部分人初次使用google android 扁平化布局ConstraintLayout都 ...
- 用MATLAB做T检验(ttest)
t-检验: t-检验,又称student‘s t-test,可以用于比较两组数据是否来自同一分布(可以用于比较两组数据的区分度),假设了数据的正态性,并反应两组数据的方差在统计上是否有显著差异. ma ...
- nginx增加ssl支持 - 编译时参数详情列表
./configure \ --with-http_ssl_module \ make && make install nginx编译参数说明如下: --prefix=&l ...
- jquery 获取URL参数并转码的例子
通过jquery 获取URL参数并进行转码,个人觉得不错,因为有时不转码就会有乱码的问题.jquery 获取URL参数并转码,首先构造一个含有目标参数的正则表达式对象,匹配目标参数并返回参数值代码: ...
- spring cloud 路由Zuul的高可用
Zuul的高可用非常关键,因为外部请求到后端微服务的流量都会经过Zuul.故而在生产环境中,我们一般都需要部署高可用的Zuul以避免单点故障. 笔者分两种场景讨论Zuul的高可用. Zuul客户端也注 ...
- 生产机器禁止ROOT远程SSH登录
vim /etc/ssh/sshd_config PermitRootLogin no /etc/init.d/sshd restart
- schema的作用
1,如果schema中定义的字段类型和数据库中该字段存储值的类型不一致(可以不定义,但定义的时候类型必须一致),则该字段查找不到,mongoose不会返回该字段的数据 2,如果数据库中有字段a,而sc ...