招商银行面试问题20200416

招商银行面试:

如何保证MySQL和Redis的双写一致性?

只考虑以下三种更新策略:

先更新数据库,再更新缓存:

1 线程A更新了数据库

2 线程B更新了数据库

3 线程B更新了缓存

4 线程A更新了缓存

这本该请求A先更新缓存,B后更新才对,但是因为网络等原因,B却比A更早更新了缓存,这就导致出现了脏数据,故不考虑。

1 如果你是一个写数据场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据还没读到,缓存就被频繁的更新,浪费性能

2 如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存的,那么,每次写入数据库,都再次计算写入缓存的值,无疑是浪费性能的,显然,删除缓存更为合适。

先删除缓存,再更新数据库

该方案会导致不一致的原因是:同时有一个请求A进行更新操作,另一个请求B进行查询操作,那么会出现以下几种情景:

1、请求A进行写操作,删除缓存

2、请求B进行读操作,发现缓存不存在

3、请求B去数据库查询得到旧值

4、请求B将旧值写入缓存

5、请求A将新值写入数据库,这样的情况就会导致不一致的情形出现,而且,如果不采用给缓存设置过期时间,该数据永远都是脏数据

采用延时双删策略:1、先淘汰缓存2、再写数据库3、休眠1秒,再次淘汰缓存,可以将1秒内所造成的缓存脏数据再次删除。

针对上面的情形,应该自行评估自己的项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百ms即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

如果你用了mysql的读写分离架构怎么办?

还是两个请求,一个请求A进行更新操作,另一个请求B进行查询操作。

(1)请求A进行写操作,删除缓存

(2)请求A将数据写入数据库了,

(3)请求B查询缓存发现,缓存没有值

(4)请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值

(5)请求B将旧值写入缓存

(6)数据库完成主从同步,从库变为新值 上述情形,就是数据不一致的原因。还是使用双删延时策略。只是,睡眠时间修改为在主从同步的延时时间基础上,加几百ms。

采用这种同步淘汰策略,吞吐量会降低,那又该怎么办呢?
那可以将第二次删除作为异步,自己起一个线程,异步删除。这样,写的请求就不用沉睡一段时间后再返回,这样做就可以加大吞吐量。

第二次删除,如果删除失败怎么办?

这会出现下面的请求,一个A请求进行更新操作,另一个请求B进行查询操作,为了方便,假设是单库:

1)请求A进行写操作,删除缓存

(2)请求B查询发现缓存不存在

(3)请求B去数据库查询得到旧值

(4)请求B将旧值写入缓存

(5)请求A将新值写入数据库

(6)请求A试图去删除请求B写入对缓存值,结果失败了。 ok,这也就是说。如果第二次删除缓存失败,会再次出现缓存和数据库不一致的问题。 如何解决呢? 具体解决方案,且看第(3)种更新策略的解析。

先更新数据库,再删除缓存

1**、失效**:应用程序先从cache取数据,没有得到,从数据库中取数据,成功后,放到缓存中。

2**、命中**:应用程序从cache中取数据,取到后返回。

3**、更新**:先把数据存到数据库中,成功后,再让缓存失效。

更新数据路数据

缓存因为种种问题删除失败

将需要删除的key发送至消息队列

自己消费消息,获得需要删除的key

继续充实删除操作,直到成功,然而,该方案有一个缺点对业务线代码造成大量的侵入,于是有了方案二,在方案二中,启动一个订阅程序去订阅数据库的binlog,获得需要操作的数据,在应用程序中,另起一段程序,获得这个订阅程序传来的信息,进行删除缓存操作

更新数据库数据

数据库会将操作信息写入binlog日志中

订阅程序提取所需要的数据以及key

另起一段非业务代码,获得该信息

尝试删除缓存操作,发现删除失败

将这些信息发送至消息队列

重新从消息队列中获得该数据,重新操作

如何实现分布式事务?

CPA原则 CA PA的原则 分布式事务保证的可用性和分区性 最终一致性的原则。数据的一致性 。采用的是两阶段的数据提交的方式来保证数据的最终一致性。采用的Redis的锁和zookeeper的锁机制来实现分布式事务。

如何实现分布式锁?

Redis实现分布式的锁

zookeeper实现分布式锁的机制

zk和Redis分布式锁的优缺点?

Redis为什么快?

数据结构简单丰富

多路复用的NIO技术

单线程的线程安全技术

直接对内存的操作原理

redis的单线程模型原理是什么?

采用的是一主多从的模型来实现。

如何实现MySQL的读写分离?

主库用于写操作 其他的库用于读操作,这个数据的就需要保证的数据的一致性。通过利用的数据的异步的写入到读库中。

在读写分离的前提下,如何强行去读主节点?

如何实现单机服务限流?资源隔离是怎么做的?熔断是怎么做的?降级的逻辑是怎么写的?

什么是服务的雪崩?A-B –C –D 但是其中一个坏了导致大量的请求的A中。导致A不用,这样导致其他服务也不可以用。采用就的springcloud的的Hystrix来实现对服务的降级和熔断操作。

在启动类中加入注解:@EnableHystrix

在需要做熔断的类上添加一下注解。其中fallbackMethod属性表示:当方法发生错误时,会跳到我们自己定义的findBasicDataByTypeFallBack方法中进行处理。这样的话当服务发生错误时,就会去执行我们自己定义的方法,返回一个结果,不会导致整个服务不可用。

分布式服务的限流如何做呢?

一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如nginx的limit_conn模块,用来限制瞬时并发连接数)、限制时间窗口内的平均速率(如Guava的RateLimiter、nginx的limit_req模块,限制每秒的平均速率);其他还有如限制远程接口调用速率、限制MQ的消费速率。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。

限流算法:常见的限流算法有:令牌桶、漏桶。计数器也可以进行粗暴限流实现。

漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:

令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.

令牌桶的另外一个好处是可以方便的改变速度. 一旦需要提高速率,则按需提高放入桶中的令牌的速率. 一般会定时(比如100毫秒)往桶中增加一定数量的令牌, 有些变种算法则实时的计算应该增加的令牌的数量.

Tomcat的限流:

对于一个应用系统来说一定会有极限并发/请求数,即总有一个TPS/QPS阀值,如果超了阀值则系统就会不响应用户请求或响应的非常慢,因此我们最好进行过载保护,防止大量请求涌入击垮系统。如果你使用过Tomcat,其Connector其中一种配置有如下几个参数:

acceptCount:如果Tomcat的线程都忙于响应,新来的连接会进入队列排队,如果超出排队大小,则拒绝连接;

maxConnections:瞬时最大连接数,超出的会排队等待;

maxThreads:Tomcat能启动用来处理请求的最大线程数,如果请求处理量一直远远大于最大线程数则可能会僵死

详细的配置请参考官方文档。另外如MySQL(如max_connections)、Redis(如tcp-backlog)都会有类似的限制连接数的配置。

池化技术限流:

如果有的资源是稀缺资源(如数据库连接、线程),而且可能有多个系统都会去使用它,那么需要限制应用;可以使用池化技术来限制总资源数:连接池、线程池。比如分配给每个应用的数据库连接是100,那么本应用最多可以使用100个资源,超出了可以等待或者抛异常。

限流某个接口的总并发/请求数

如果接口可能会有突发访问情况,但又担心访问量太大造成崩溃,如抢购业务;这个时候就需要限制这个接口的总并发/请求数总请求数了;因为粒度比较细,可以为每个接口都设置相应的阀值。可以使用Java中的AtomicLong进行限流:

try {if(atomic.incrementAndGet() > 限流数) {//拒绝请求}
catch{//处理请求}} finally {atomic.decrementAndGet();}

分布式限流:

分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使使用redis+lua或者nginx+lua技术进行实现,通过这两种技术可以实现的高并发和高性能。

首先我们来使用redis+lua实现时间窗内某个接口的请求数限流,实现了该功能后可以改造为限流总并发/请求数和限制总资源数。

有人会纠结如果应用并发量非常大那么redis或者nginx是不是能抗得住;不过这个问题要从多方面考虑:你的流量是不是真的有这么大,是不是可以通过一致性哈希将分布式限流进行分片,是不是可以当并发量太大降级为应用级限流;对策非常多,可以根据实际情况调节;像在京东使用Redis+Lua来限流抢购流量,一般流量是没有问题的。

对于分布式限流目前遇到的场景是业务上的限流,而不是流量入口的限流;流量入口限流应该在接入层完成,而接入层笔者一般使用Nginx。

基于Redis功能的实现限流

简陋的设计思路:假设一个用户(用IP判断)每分钟访问某一个服务接口的次数不能超过10次,那么我们可以在Redis中创建一个键,并此时我们就设置键的过期时间为60秒,每一个用户对此服务接口的访问就把键值加1,在60秒内当键值增加到10的时候,就禁止访问服务接口。在某种场景中添加访问时间间隔还是很有必要的。

基于令牌桶算法的实现:

令牌桶算法最初来源于计算机网络。在网络传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送。令牌桶算法就实现了这个功能,可控制发送到网络上数据的数目,并允许突发数据的发送。

令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。大小固定的令牌桶可自行以恒定的速率源源不断地产生令牌。如果令牌不被消耗,或者被消耗的速度小于产生的速度,令牌就会不断地增多,直到把桶填满。后面再产生的令牌就会从桶中溢出。最后桶中可以保存的最大令牌数永远不会超过桶的大小。

传送到令牌桶的数据包需要消耗令牌。不同大小的数据包,消耗的令牌数量不一样。

令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;而如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。

https://img-blog.csdn.net/20160423213519927

kafka如何保证消息的不重复消费或不丢失?

kafka的消息发送机制分为同步和异步机制。可以通过producer.type属性进行配置。使用同步模式的时候,有三种状态来保证消息的安全生产。可以通过配置request.required.acks属性。三个属性分别如下:

0—表示不进行消息接收是否成功的确认;

1—表示当Leader接收成功时确认;

-1—表示Leader和Follower都接收成功时确认

当acks = 0的时候,不和Kafka集群进行消息接收确认,则当网络异常、缓冲区满了等情况时,消息可能丢失;当acks=1的时候,只保证leader写入成功。当leader partition挂了的时候,数据就有可能发生丢失。另外还有一种情况,使用异步模式的时候,当缓冲区满了,acks=0的时候,不需要进行消息接受是否成功的确认,所以会自动清空缓冲池里的消息。

同步模式下只需要将确认机制设置为-1,让消息写入leader和所有的副本,就可以保证消息安全生产。

异步模式下,则需要在配置文件中,将阻塞超时的时间设置为不限制。这样生产端会一直阻塞。可以保证数据不丢失。

我们需要设置block.on.buffer.full = true。 这样producer将一直等待缓冲区直至其变为可用。缓冲区满了就阻塞

acks=all。所有的follwoer都响应了消息就认为消息提交成功。

retries=MAX。无限重试。

max.in.flight.requests.per.connnection = 1限制客户端在单个连接上能够发送的未响应的请求的个数。设置为1表示kafka broker在响应请求之前client不能再向broker发送请求了。通过此举可以保证消息的顺序性。

消息的接受机制

kafka有个offset的概念,当每个消息被写进去后,都有一个offset,代表他的序号,然后consumer消费该数据之后,隔一段时间,会把自己消费过的消息的offset提交一下,代表已经消费过了。下次我要重启,就会继续从上次消费到的offset来继续消费。

但是当我们直接kill进程了,再重启。这会导致consumer有些消息处理了,但是没来得及提交offset。等重启之后,少数消息就会再次消费一次。其他MQ也会有这种重复消费的问题,那么针对这种问题,我们需要从业务角度,考虑它的幂等性。

消息的重复消费如何解决

重复消费的问题,一方面需要消息中间件来进行保证。另一方面需要自己的处理逻辑来保证消息的幂等性。极有可能代码消费了消息,但服务器突然宕机,未来得及提交offset。所以我们可以在代码保证消息消费的幂等性。至于方法可以通过redis的原子性来保证,也可以通过数据库的唯一id来保证。

如何保证Kafka的消息一定发送成功呢?sequenceNumber实现精准一次性,ISR中所有节点同步来保证消息不会丢失。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39023.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试常考:C#用两个线程交替打印1-100的五种方法

"C#用两个线程交替打印1-100的五种方法"是.NET工程师面试多线程常考的试题之一,主要考察对C#语法和对多线程的熟悉程度。本文将用5种方法实现这个面试题。 方法1:使用Mutex或lock 这种方法涉及使用Mutex或lock对象来同步两个线程。其中一个线…

ChatGPT为什么火?|掀起热潮的对话革命|小智ai

ChatGPT丨小智ai丨chatgpt丨人工智能丨OpenAI丨聊天机器人丨AI语音助手丨GPT-3.5丨开源AI平台|人工智能巨头OpenAI开发的聊天机器人引发全球关注 近期,人工智能领域迎来了一股前所未有的热潮,而其中的主角正是由OpenAI开发的聊天机器人ChatGPT。作为一项…

数据分析案例-股票数据分析

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

图形化跟踪个股RPS走势,挖掘出源源不断的牛股!股票量化分析工具QTYX-V2.5.7...

概述RPS选股策略 威廉欧奈尔把投资理念集中于他自创的CANSLIM选股系统,凭借着这个系统驰骋股票市场数十年,无论在牛市还是熊市,这个系统都是最稳定、表现最好的系统之一。 CANSLIM选股系统中有一个RPS指标(Relative Price Strengt…

【树莓派烹饪日记】#1 系统安装与环境配置

0 引言 这个系列用于记录入门树莓派期间踩的各种坑及解决办法。 只记录一些我觉得重要的地方,不一定很全面。 目前暂定的一个目标是拿树莓派接管小爱音箱并接入ChatGPT。 今天的计划是将一个新的树莓派主板 烧录并启动系统系统配置安装VPN安装conda环境 需要用到…

RWKV配上ChatGPTBox让我们在浏览器中感受AI带来的魅力

这次我们来讲讲RWKV搭配ChatGPTBox结合使用带来的功能体验,这两个项目都是同一个大神创建的,完全可以无缝搭配进行使用。 以下是我之前在本地部署了AI模型RWKV的教程,如果还没有本地部署过AI的童鞋可以查看我之前发布的教程,在自…

总结谷歌身份验证器 Google Authenticator 的详细使用方法

谷歌身份验证器Google Authenticator是谷歌推出的一款动态口令工具,解决大家各平台账户遭到恶意攻击的问题,一般在相关的服务平台登陆中除了用正常用户名和密码外,需要再输入一次谷歌认证器生成的动态口令才能验证成功,相当于输入…

快速接入Google两步认证Google Authenticator

(一)介绍 既然来看该文章就应该知道Google的两步认证是干什么的,这边再提供一次app的下载链接 (apkpure搜索谷歌身份验证器) 验证原理讲解: 在数据库中查找该登陆用户之前绑定的32位随机码(该码一般会存入数据库)调用API传入32位…

身份验证器 Authenticator 插件

1.插件支持浏览器 ChromeFirefoxEdge 2.关键特性 通过扫描二维码添加账号使用密码加密数据在浏览器之间同步数据备份数据到云服务或导出数据到文件智能过滤和搜索 官网地址: Authenticator Extension 官方说明文档:What is Authenticator Extension? | Authen…

前后端身份验证

1、web 开发模式 【】基于服务端渲染的传统 Web 开发模式 【】基于前后端分离的新型 Web 开发模式:依赖于 Ajax 技术的广泛应用。后端只负责提供 API 接口,前端使用 Ajax 调用接口的开发模式 2、身份认证 【】服务端渲染推荐使用 Session 认证机制 【】…

生信工作流框架搭建 | 04-nextflow与Slurm高性能计算

目录 生信工作流框架搭建 | 04-nextflow与Slurm高性能计算前情提要什么是HPC高性能计算什么是slurm nextflow配置注意事项下期预告 生信工作流框架搭建 | 04-nextflow与Slurm高性能计算 本篇为biodoge《生信工作流框架搭建》系列笔记的第5篇,该系列将持续更新。 前情…

评价基于GPT和Bert的方法并用于生信文本识别PPI

检测蛋白质-蛋白质相互作用(PPI)对于理解遗传机制、疾病发病机制和药物设计至关重要。然而,随着生物医学文献的快速增长,越来越需要自动和准确地提取PPI以促进科学知识发现。预训练语言模型,例如生成式预训练Transform…

Limma | 三个组的差异分析怎么分析做呢!?~

1写在前面 高考结束了,不知道各位考生考的怎么样,这种时候总是几家欢喜几家忧,但这也是实现阶级流动的最佳机会。🤔 回想自己高考过去10几年了,不能说学了医后悔吧,只能说后悔至极,苦不堪言啊&a…

生信分析案例 Python简明教程 | 视频13

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在:https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

生信分析案例 Python简明教程 | 视频12

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在:https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

生信分析案例 Python简明教程 | 视频11

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在:https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

12款好用的Visual Studio插件,最后一款良心推荐

工欲善其事,必先利其器,整理的一些我必装的12款Visual Studio插件,希望你们能get到。 效率工具前文传送门: adb常用命令总结 程序员你可以考虑安装的15款谷歌插件 推荐20套实战源码 99%的人不知道搜索引擎的6个技巧 12款好用的Visual Stu…

七年磨一剑!苹果王炸产品Vision Pro诞生,未来已来

这是第一款「不见却可透见」的苹果产品 等了整整七年!2023年6月5日,WWDC23大会上,苹果发布首款头显Vision Pro,Vision Pro 可以算是苹果公司自 2015 年 Apple Watch 首次亮相以来最大的硬件产品发布,或许它会彻底改变数…

chatgpt赋能python:人机对话Python——让交互更智能

人机对话Python——让交互更智能 随着科技的不断发展,人类与机器之间的交互方式也在不断改变。从最初的键盘输入和鼠标点击,到现在的语音识别和手势交互,我们与计算机之间的交互方式日益智能化和自然化。人机对话技术就是其中一种重要的交互…

紫砂典故之“蔓生石瓢”

紫砂典故之“蔓生石瓢”