Java进阶学习资料,java小程序开发面试题
引言
技术好就一定能写出优质的代码吗?不能,对于做开发的人来说,学到的技术知识是理论性的,只有把知识代入到真实的实战案例中才能快速将理论转变为技能。
一直在网上看到过很多关于类似的资料,要么就是版本比较老,要么就是讲的太干,没有阅读下去的兴趣,以至于在这方面的学习止步不前。
今天,我跟大家要分享的这份阿里《互联网实战案例》共有22大实战案例,每一章节都有对应的完整代码,同时在学习的过程中需要了解并运行代码,再也不用担心学不会了。
如何保证缓存和数据库一致性
说了这么多缓存的必要性,那么使用缓存是不是就是一个很简单的事情了呢,我之前也一直是这么觉得的,直到遇到了需要缓存与数据库保持强一致的场景,才知道让数据库数据和缓存数据保持一致性是一门很高深的学问。
从远古的硬件缓存,操作系统缓存开始,缓存就是一门独特的学问。这个问题也被业界探讨了非常久,争论至今。我翻阅了很多资料,发现其实这是一个权衡的问题。值得好好讲讲。
以下的讨论会引入几方观点,我会跟着观点来写代码验证所提到的问题。
不更新缓存,而是删除缓存
大部分观点认为,做缓存不应该是去更新缓存,而是应该删除缓存,然后由下个请求去去缓存,发现不存在后再读取数据库,写入缓存。
观点引用:《分布式之数据库和缓存双写一致性方案解析》孤独烟
原因一:线程安全角度
同时有请求A和请求B进行更新操作,那么会出现
(1)线程A更新了数据库
(2)线程B更新了数据库
(3)线程B更新了缓存
(4)线程A更新了缓存
这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此不考虑。
原因二:业务场景角度
有如下两点:
(1)如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。
(2)如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。显然,删除缓存更为适合。
其实如果业务非常简单,只是去数据库拿一个值,写入缓存,那么更新缓存也是可以的。但是,淘汰缓存操作简单,并且带来的副作用只是增加了一次cache miss,建议作为通用的处理方式。
先操作缓存,还是先操作数据库
那么问题就来了,我们是先删除缓存,然后再更新数据库,还是先更新数据库,再删缓存呢?
先来看看大佬们怎么说。
《【58沈剑架构系列】缓存架构设计细节二三事》58沈剑:
对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:如果出现不一致,谁先做对业务的影响较小,就谁先执行。
假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。
假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。
沈剑老师说的没有问题,不过没完全考虑好并发请求时的数据脏读问题,让我们再来看看孤独烟老师《分布式之数据库和缓存双写一致性方案解析》:
先删缓存,再更新数据库
该方案会导致请求数据不一致
同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:
(1)请求A进行写操作,删除缓存
(2)请求B查询发现缓存不存在
(3)请求B去数据库查询得到旧值
(4)请求B将旧值写入缓存
(5)请求A将新值写入数据库
上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。
所以先删缓存,再更新数据库并不是一劳永逸的解决方案,再看看先更新数据库,再删缓存这种方案怎么样?
先更新数据库,再删缓存这种情况不存在并发问题么?
不是的。假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生
(1)缓存刚好失效
(2)请求A查询数据库,得一个旧值
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存
ok,如果发生上述情况,确实是会发生脏数据。
然而,发生这种情况的概率又有多少呢?
发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。可是,大家想想,数据库的读操作的速度远快于写操作的(不然做读写分离干嘛,做读写分离的意义就是因为读操作比较快,耗资源少),因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。
先更新数据库,再删缓存依然会有问题,不过,问题出现的可能性会因为上面说的原因,变得比较低!
(补充说明:我用了“先更新数据库,再删缓存”且不设过期时间策略,会不会有问题呢?由于先缓存和更新数据库不是原子的,如果更新了数据库,程序歇逼,就没删缓存,由于没有过期策略,就永远脏数据了。)
所以,如果你想实现基础的缓存数据库双写一致的逻辑,那么在大多数情况下,在不想做过多设计,增加太大工作量的情况下,请先更新数据库,再删缓存!
我非要数据库和缓存数据强一致怎么办
那么,如果我非要保证绝对一致性怎么办,先给出结论:
没有办法做到绝对的一致性,这是由CAP理论决定的,缓存系统适用的场景就是非强一致性的场景,所以它属于CAP中的AP。
所以,我们得委曲求全,可以去做到BASE理论中说的最终一致性。
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性
大佬们给出了到达最终一致性的解决思路,主要是针对上面两种双写策略(先删缓存,再更新数据库/先更新数据库,再删缓存)导致的脏数据问题,进行相应的处理,来保证最终一致性。
缓存延时双删
问:先删除缓存,再更新数据库中避免脏数据?
答案:采用延时双删策略。
上文我们提到,在先删除缓存,再更新数据库的情况下,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。
那么延时双删怎么解决这个问题呢?
(1)先淘汰缓存
(2)再写数据库(这两步和原来一样)
(3)休眠1秒,再次淘汰缓存
这么做,可以将1秒内所造成的缓存脏数据,再次删除。
那么,这个1秒怎么确定的,具体该休眠多久呢?
针对上面的情形,读者应该自行评估自己的项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百ms即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。
如果你用了mysql的读写分离架构怎么办?
ok,在这种情况下,造成数据不一致的原因如下,还是两个请求,一个请求A进行更新操作,另一个请求B进行查询操作。
(1)请求A进行写操作,删除缓存
(2)请求A将数据写入数据库了,
(3)请求B查询缓存发现,缓存没有值
(4)请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值
(5)请求B将旧值写入缓存
(6)数据库完成主从同步,从库变为新值
上述情形,就是数据不一致的原因。还是使用双删延时策略。只是,睡眠时间修改为在主从同步的延时时间基础上,加几百ms。
采用这种同步淘汰策略,吞吐量降低怎么办?
ok,那就将第二次删除作为异步的。自己起一个线程,异步删除。这样,写的请求就不用沉睡一段时间后了,再返回。这么做,加大吞吐量。
所以在先删除缓存,再更新数据库的情况下,可以使用延时双删的策略,来保证脏数据只会存活一段时间,就会被准确的数据覆盖。
在先更新数据库,再删缓存的情况下,缓存出现脏数据的情况虽然可能性极小,但也会出现。我们依然可以用延时双删策略,在请求A对缓存写入了脏的旧值之后,再次删除缓存。来保证去掉脏缓存。
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
[外链图片转存中…(img-xY1UYqAC-1650364559462)]
[外链图片转存中…(img-7IE6rpQ4-1650364559464)]
[外链图片转存中…(img-Fj3BlDAA-1650364559465)]
Java进阶学习资料,java小程序开发面试题相关推荐
- 基于Java毕业设计学习自律养成小程序后台源码+系统+mysql+lw文档+部署软件
基于Java毕业设计学习自律养成小程序后台源码+系统+mysql+lw文档+部署软件 基于Java毕业设计学习自律养成小程序后台源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B ...
- Java进阶学习之Java架构师的学习路线
Java架构师,首先要是一个高级Java攻城狮,熟练使用各种框架,并知道它们实现的原理.Java架构师的作用就是要满足业务需求,用低的硬件网络成本和技术维护成本.Java架构师还要根据业务发展阶段,提 ...
- Java进阶学习资料!dockerjar内存
准备好套路 **①自我介绍:**千万不能筐瓢,一定要牢记,自然流畅地介绍自己的学习经历.工作经历.项目经历.个人优势等等: **②抽象概念:**当面试官问你是如何理解多线程的时候,你要知道从定义.来源 ...
- 计算机毕业设计Java学习自律养成小程序后台(源码+系统+mysql数据库+lw文档)
计算机毕业设计Java学习自律养成小程序后台(源码+系统+mysql数据库+lw文档) 计算机毕业设计Java学习自律养成小程序后台(源码+系统+mysql数据库+lw文档) 本源码技术栈: 项目架构 ...
- 微信小程序开发文档及文件上传示例(JAVA)
微信小程序开发文档及文档上传示例 一.什么是微信小程序 小程序是一种无需下载安装,即可使用的手机应用.只需要扫描二维码,或是搜一搜,就能立即使用. 与APP不同的是,小程序无需下载安装.无需卸载.用完 ...
- 基于JAVA学习自律养成小程序前台.mp4计算机毕业设计源码+系统+数据库+lw文档+部署
基于JAVA学习自律养成小程序前台.mp4计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA学习自律养成小程序前台.mp4计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈: ...
- Java进阶面试资料无偿分享!真香系列
8-22 投递简历 8-24 一面(大概1h50min) 0.currenthashmap怎么扩容的?fwn为什么固定hash -1,这样设计有什么好处?帮助扩容是发生在什么阶段?读线程和写线程都会帮 ...
- Java后台微信点餐小程序开发最新版笔记,Springboot+Mysql+Freemarker+Bootstrap+微信小程序实现扫码点餐小程序,包含语音提示,微信消息推送,网页管理后台
由于之前的Java后台微信点餐小程序有些知识点过时了,所以今天重新出一版,把里面过时的知识点更新下 前五章是部署笔记,后面是知识点的详细讲解,大家可以先看部署笔记,部署起来后,再跟着详细知识学习. 第 ...
- Java进阶学习-7 面向对象程序设计原则
title: Java进阶学习-7 面向对象程序设计原则 date: 2020-02-02 18:02:27 tags: 以一个城堡游戏为例子谈面向对象程序设计原则 Game.java package ...
最新文章
- #pragma pack 内存对齐
- 使用职责链模式来重构你的代码
- linux 目标文件格式,Linux工具 - NM目标文件格式分析
- 温州大学《机器学习》课程代码(二)(回归)
- JDK7新特性简单翻译介绍
- mysql增删改查脚本_脚本方式实现数据库增删改查
- 【Canal源码分析】Sink及Store工作过程
- 【转】使用Feature导入WebPart
- spring 多数据源- 原理
- WordPress开发暗黑系列流量主收益高清壁纸小程序-可二开-无授权
- c++编写手机小游戏代码_玩过自己开发的贪吃蛇吗?点这里,教你用Python写一个贪吃蛇小游戏!(附源代码)...
- java循环while之等差数列均值_java基础_while 循环语句的定义及用法
- python数据类型、if判断语句
- centOs安装 ruby环境
- (转载)硬盘安装XP64位系统
- 计算机英语写作,计算机英语8.4_电邮写作+.ppt
- 怎么看电脑的hdmi是输出还是输入_笔记本hdmi接口是输入还是输出
- jsp清真餐馆订餐系统
- 【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Table表格增删查改、Pagination分页、搜索框
- 投稿SCI 中文文献翻译后 中英文混排的解决办法
热门文章
- 港中文旷视提出PanopticFCN:用于全景分割的全卷积网络
- Python将word表格存入excel —— 格式化pg参数手册
- Excel技巧【标记多行数据连续一样的行】【第一个单元格公式适用于所有本列所有行】【按照逗号分列】【快速统计出各个项出现的次数】【冻结窗口】[表格分段选择数据][根据单元格内容引索其他单元格数据指针]
- Double S 曲线轨迹规划——不同速度加速度条件下综合
- 读《禅与摩托车维修艺术》
- 《觉醒》:头脑编程与全息宇宙 大卫·艾克
- android一键清理任务,Android 一键清理、内存清理功能实现
- 【OWASP Top 10】2021版
- webp怎么转png?图片webp格式怎么转换?
- linux中日志服务器的搭建