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的简易用法. 下面开始介 ...
随机推荐
- matlab入门笔记(六):编程基础之M文件
摘自<matlab从入门到精通>胡晓东 在Matlab中,用户可以在命令行中直接输入命令,从而以一种交互式的方式来编写程序.这种方式适用于命令行比较简单,输入比较方便,同时处理的问题较少的 ...
- 目标检测 的标注数据 .xml 转为 tfrecord 的格式用于 TensorFlow 训练
将目标检测 的标注数据 .xml 转为 tfrecord 的格式用于 TensorFlow 训练. import xml.etree.ElementTree as ET import numpy as ...
- 命令行运行python项目文件,报错:ModuleNotFoundError: No module named 'xxxx' 解决办法
在pycharm中写好了自动化测试脚本,并能在pycharm中正常运行,由于要考虑到无人值守时能自动执行,执行时就需要脱离pycharm,直接能用命令执行.但是直接用命令执行用例文件:python3 ...
- 清理kafka zookeeper
; ; /; rm -rf /app/zookeeper/logs/*; rm -rf /app/pet_kafka_emds2_cluster/kafka-logs/*; rm -rf /app/p ...
- 更新中国地区ip列表
鉴于高总的IPIP.net的数据库的准确性,推荐使用下列源: https://github.com/17mon/china_ip_list/blob/master/china_ip_list.txt ...
- Subclipse和TortoiseSVN版本不一致导致升到高版本的project后,低版本svn客户端无法使用。
- /etc/sudoers文件设置为允许用户在不输入该用户的密码的情况下使用所有命令
设置用户666在不输入该用户的密码的情况下使用所有命令: /etc/sudoers ALL=(ALL) NOPASSWD:ALL # ALL=(ALL) ALL #sudo su - 时是需要输入66 ...
- HTML5学习笔记(十):CSS常用操作
对齐 在 CSS 中,可以使用多种属性来水平对齐元素. 水平对齐 使用 margin 属性来水平对齐,可通过将左和右外边距设置为 "auto",来对齐块元素. 把左和右外边距设置为 ...
- blocking
package blockingtest; /** * Hello world! */public class Sync implements Runnable { int n; public sta ...
- 支付宝对账单下载Java沙箱调用
package code; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; impo ...