走进缓存的世界(二) - 缓存设计
系列文章
- 走进缓存的世界(一) - 开篇
- 走进缓存的世界(二) - 缓存设计
- 走进缓存的世界(三) - Memcache
如何设计缓存
主要考虑三个问题:
- 缓存哪些数据
- 如何缓存
- 如何保证数据一致性
缓存哪些数据
系统优化时有一句话必须切记:“优化无止境”,所以如果缓存不是必须的,请果断去掉,要知道越是业务上复杂的系统,对Cache的使用反而越简单,因为对于一个复杂、多变、历史悠久的系统,在Cache方面做过度设计会让人深陷其中;缓存的数据越多,系统的维护成本就越高,所以找准需要缓存的点尤为重要。一般情况下,我们只会缓存给系统带来巨大瓶颈的IO操作,在普通应用里尤其指由top SQL或者慢 SQL所带来的DAO查询;找准需要优化的sql,你可以找DBA帮忙。
如何缓存
存储介质的选择: 你可以直接缓存在JVM内存里,也可以采用阿里云专门的缓存服务器,如tair、memcache等;
DB、文件其实也可以做缓存,他们一般缓存复杂计算的中间结果,一般很少用到;如果你的缓存是存放在jvm本地,那么通常是用map实现,如果缓存数据更新比较频繁且对数据正确性比较高,那么你需要考虑为其添加并发控制和失效策略。还有一点比较重要的就是,在集群环境下想要做到数据一致性比较困难,主动更新比较麻烦而且达不到其降低数据库IO操作的效果,所以本地缓存适用场景一般是在读访问非常高,而写操作极少,对数据一致性要求不是特别高的场景;如果采用专门的缓存服务器则避免了很多麻烦,阿里云的缓存系统tair,是我们经常使用的缓存中间件,它提供了很好的并发控制和失效机制,另外还提供了不同存储引擎可以供我们选择,如mdb,rdb,ldb;普通的缓存可以选择mdb和rdb,两者分别有memcache和redis的影子,其响应时间和高QPS的表现都非常好,但没有提供持久化,如果要确保数据不丢失可以采用ldb引擎存储,它提供了对数据持久化的支持,相反牺牲了一点点性能。
数据一致性
缓存意味着同样的数据可能有多份并存,如果你的代码没有考虑某种情况导致了两份数据不一致就会有问题发生。解决方法很简单,把你的业务逻辑、代码触发情况都考虑清楚,不要遗留没有触底的地方。
多处使用缓存会导致你的代码逻辑变得异常复杂,这也是为何说在非必要的时候,建议你不要用缓存的原因。
缓存一致性协议就是为了解决数据一致性问题而发明的。缓存一致性协议有多种,大多数计算机设备使用的都属于“窥探(snooping)”协议。
“窥探”的基本思想是,内存是共享资源,所有内存I/O传输都发生在一条共享的总线上,所有的处理器都能看到这条总线,所有处理器对内存的访问请求都要经过仲裁(arbitrate):同一个指令周期中,只有一个处理器可以读写内存中的被缓存的数据。窥探协议的思想是,缓存不仅仅在做内存传输的时候才和总线打交道,而是不停地在窥探总线上发生的数据交换,跟踪其他缓存在做什么。所以当一个缓存代表它所属的处理器去读写内存时,其他处理器都会得到通知,以此来使自己的缓存保持同步。只要某个处理器执行写操作,其他处理器马上就知道这块内存在它们自己的缓存中对应的段已经失效。
在直写模式下,这是很直接的,因为写操作一旦发生,它的效果马上会被“公布”出去。但是如果混着回写模式就有问题了。因为有可能在写指令执行过后很久,数据才会被真正回写到物理内存中。在这段时间内,其他处理器的缓存可能会去写同一块内存地址导致冲突。在回写模型中,简单把内存写操作的信息广播给其他处理器是不够的,我们需要做的是,在修改本地缓存之前,就要告知其他处理器。
搞懂了细节,就找到了处理回写模式这个问题的最简单方案。当处理器想写某个缓存段时,如果它没有独占权,它必须先发送一条“我要独占权”的请求给总线,这会通知其他处理器,把它们拥有的同一缓存段的拷贝失效(如果它们有的话)。只有在获得独占权后,处理器才能开始修改数据——并且此时,这个处理器知道,这个缓存段只有一份拷贝,在我自己的缓存里,这样一来就可以巧妙地避免了冲突。
走进缓存的世界(二) - 缓存设计相关推荐
- ARKit-带你走进全新的世界(二:动画与光线处理)
简介: 上篇回顾: ARKit初探篇(链接)中写到怎样开启一个AR项目,包括开发环境,建立项目,及基础代码实现,在git的demo添加了手势的处理,简单实现点击球体实现图片轮换 本篇介绍: 将虚拟世界 ...
- Mybatis 一级缓存,Mybatis 二级缓存,Mybatis 缓存失效
Mybatis 一级缓存,Mybatis 二级缓存,Mybatis 缓存失效 ================================ ©Copyright 蕃薯耀 2021-06-24 ht ...
- ARKit-带你走进全新的世界(四:平面检测)
简介: 上篇回顾: 上篇文章中我们简单写了一个AR尺子测量距离的demo,计算距离的公式--> A(x1,y1,z1),B(x2,y2,z2),则A,B之间的距离为d=√[(x1-x2)^2+( ...
- 走进缓存的世界(一) - 开篇
系列文章 走进缓存的世界(一) - 开篇 走进缓存的世界(二) - 缓存设计 走进缓存的世界(三) - Memcache 概述 对于程序员来说多多少少都懂一点算法,算法是什么?算法是"时间& ...
- Glide核心设计二:缓存管理
原文链接:Glide核心设计二:缓存管理 引言 Glide作为一个优秀的图片加载框架,缓存管理是必不可少的一部分,这篇文章主要通过各个角度.从整体设计到代码实现,深入的分析Glide的缓存管理模块,力 ...
- 分布式缓存,就该这样设计!
文章来源:https://sourl.cn/Sejspk 前 言 在高并发的分布式的系统中,缓存是必不可少的一部分.没有缓存对系统的加速和阻挡大量的请求直接落到系统的底层,系统是很难撑住高并发的 ...
- 【转】系统缓存全解析二:动态缓存(4)-第三方分布式缓存解决方案 Memcache(2)...
缓存系统MemCached的Java客户端优化历程(转载自http://code.google.com/p/memcache-client-forjava/.) Memcached是一种集中式Cach ...
- 缓存系列之二:CDN与其他层面缓存
缓存系列之二:CDN与其他层面缓存 一:内容分发网络(Content Delivery Network),通过将服务内容分发至全网加速节点,利用全球调度系统使用户能够就近获取,有效降低访问延迟,提升服 ...
- 据说是“缓存之王”? Caffeine高性能设计剖析
概要 Caffeine[1]是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是 Guava Cache 的优化加强版,有些文章把 Caffeine 称为" ...
- java disruptor压测_Java并发框架Disruptor实现原理与源码分析(二) 缓存行填充与CAS操作...
##缓存行填充 关于缓存行填充在我个人的印象里面第一次看到是在Java的java.util.concurrent包中,因为当时很好奇其用法背后的逻辑,所以查了很多资料才明白到底是怎么回事*(也许事实上 ...
最新文章
- R语言Kolmogorov-Smirnov假设检验(正态性检验):检验数据的正态性
- 老李分享:jvm垃圾回收
- CPU 到底是怎么认识代码的?涨姿势了!
- fenby C语言 P30
- Python将迁移到GitHub
- window.open() 方法
- golang ide 环境搭建_新手引导 — Golang后端开发环境搭建
- win10+android+手机驱动,win10系统电脑没有手机驱动的解决方法
- TBS 腾讯浏览服务(X5WebView) 集成指南
- 测试用例(功能用例)——资产申购、统计报表
- [ 读书笔记 ] 1 -《 程序员修炼之道 - 通向务实的最高境界 (第2版)》
- 全站仪和手机连接软件_测量员APP全站仪设站的的应用说明
- 【数据结构PTA 7-158-161】
- anchor free和anchor based的区别
- MySQL权限与安全管理之权限表与账户管理
- APP二维码下载 自动跳转
- 理解HTTP和TCP
- dlt变换matlab,直接线性变换(DLT)简易程序实现
- asp.net mvc 上传到服务器 图片不显示,asp.net MVC上传图片完整方法
- 如何设计存储海量数据的存储系统
热门文章
- 我是如何战胜懒惰的?
- m2e (maven eclipse) 在运行一些命令时出现了无法compile(Unable to locate the Javac Compiler in:)...
- 通用的分页存储过程(少量代码实现)
- Asp.net直接保存文件到客户端
- java 利用同步工具类控制线程
- git不能上传空目录和设备文件
- (十)unity4.6学习Ugui中文文档-------參考-UGUI Canvas Components
- spring2中jpa的配置和使用
- c语言秒表编程示例,求大神帮忙写一篇简单的C语言秒表程序, 谢谢。
- Java之美[从菜鸟到高手演变]之设计模式四