pull/6/head
yuanguangxin 5 years ago
parent 4a3bd02374
commit cde96ead44

@ -259,13 +259,8 @@
<workItem from="1587193343846" duration="24885000" />
<workItem from="1587225096292" duration="132000" />
<workItem from="1588302756697" duration="3701000" />
</task>
<task id="LOCAL-00015" summary="add q1277">
<created>1581441609925</created>
<option name="number" value="00015" />
<option name="presentableId" value="LOCAL-00015" />
<option name="project" value="LOCAL" />
<updated>1581441609925</updated>
<workItem from="1588749661816" duration="451000" />
<workItem from="1589857792404" duration="221000" />
</task>
<task id="LOCAL-00016" summary="add q42">
<created>1581519773712</created>
@ -603,7 +598,14 @@
<option name="project" value="LOCAL" />
<updated>1588336234219</updated>
</task>
<option name="localTasksCounter" value="64" />
<task id="LOCAL-00064" summary="update">
<created>1588749779331</created>
<option name="number" value="00064" />
<option name="presentableId" value="LOCAL-00064" />
<option name="project" value="LOCAL" />
<updated>1588749779332</updated>
</task>
<option name="localTasksCounter" value="65" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -656,7 +658,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="update README.md" />
<MESSAGE value="add q73/q102/q118/q224" />
<MESSAGE value="add q736" />
<MESSAGE value="增加操作系统相关问题" />
@ -681,29 +682,22 @@
<MESSAGE value="add q61" />
<MESSAGE value="add q62" />
<MESSAGE value="增加问题" />
<option name="LAST_COMMIT_MESSAGE" value="增加问题" />
<MESSAGE value="update" />
<option name="LAST_COMMIT_MESSAGE" value="update" />
</component>
<component name="WindowStateProjectService">
<state x="320" y="115" key="#Inspections" timestamp="1581061018990">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="320" y="115" key="#Inspections/0.0.1440.900@0.0.1440.900" timestamp="1581061018990" />
<state x="320" y="115" key="#Project_Structure" timestamp="1580830129378">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="320" y="115" key="#Project_Structure/0.0.1440.900@0.0.1440.900" timestamp="1580830129378" />
<state x="458" y="204" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1587221348872">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="458" y="204" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1440.900@0.0.1440.900" timestamp="1587221348872" />
<state x="303" y="50" key="CommitChangelistDialog2" timestamp="1588336234072">
<state x="303" y="50" key="CommitChangelistDialog2" timestamp="1588749779133">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="303" y="50" key="CommitChangelistDialog2/0.0.1440.900@0.0.1440.900" timestamp="1588336234072" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog" timestamp="1588336167223">
<state x="303" y="50" key="CommitChangelistDialog2/0.0.1440.900@0.0.1440.900" timestamp="1588749779133" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog" timestamp="1588749770793">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.0.1440.900@0.0.1440.900" timestamp="1588336167223" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.0.1440.900@0.0.1440.900" timestamp="1588749770793" />
<state x="144" y="78" width="1152" height="720" key="DiffContextDialog/0.23.1440.793@0.23.1440.793" timestamp="1582714686712" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.23.1440.797@0.23.1440.797" timestamp="1588303139733" />
<state width="1398" height="204" key="GridCell.Tab.0.bottom" timestamp="1587225087588">
@ -730,22 +724,18 @@
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="204" key="GridCell.Tab.1.bottom/0.0.1440.900@0.0.1440.900" timestamp="1587225087590" />
<state width="1398" height="304" key="GridCell.Tab.1.bottom/0.23.1440.797@0.23.1440.797" timestamp="1580408030266" />
<state width="1398" height="204" key="GridCell.Tab.1.center" timestamp="1587225087589">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="204" key="GridCell.Tab.1.center/0.0.1440.900@0.0.1440.900" timestamp="1587225087589" />
<state width="1398" height="304" key="GridCell.Tab.1.center/0.23.1440.797@0.23.1440.797" timestamp="1580408030265" />
<state width="1398" height="204" key="GridCell.Tab.1.left" timestamp="1587225087588">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="204" key="GridCell.Tab.1.left/0.0.1440.900@0.0.1440.900" timestamp="1587225087588" />
<state width="1398" height="304" key="GridCell.Tab.1.left/0.23.1440.797@0.23.1440.797" timestamp="1580408030262" />
<state width="1398" height="204" key="GridCell.Tab.1.right" timestamp="1587225087589">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="204" key="GridCell.Tab.1.right/0.0.1440.900@0.0.1440.900" timestamp="1587225087589" />
<state width="1398" height="304" key="GridCell.Tab.1.right/0.23.1440.797@0.23.1440.797" timestamp="1580408030266" />
<state x="431" y="173" key="MultipleFileMergeDialog" timestamp="1588302773046">
<screen x="0" y="0" width="1440" height="900" />
</state>
@ -754,10 +744,10 @@
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="221" y="63" key="SettingsEditor/0.0.1440.900@0.0.1440.900" timestamp="1585223890241" />
<state x="320" y="190" key="Vcs.Push.Dialog.v2" timestamp="1588336235490">
<state x="320" y="190" key="Vcs.Push.Dialog.v2" timestamp="1588749781144">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="320" y="190" key="Vcs.Push.Dialog.v2/0.0.1440.900@0.0.1440.900" timestamp="1588336235490" />
<state x="320" y="190" key="Vcs.Push.Dialog.v2/0.0.1440.900@0.0.1440.900" timestamp="1588749781144" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.DirectoryHistoryDialog" timestamp="1581744794182">
<screen x="0" y="23" width="1440" height="797" />
</state>
@ -766,10 +756,10 @@
<screen x="0" y="23" width="1440" height="797" />
</state>
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.23.1440.797@0.23.1440.797" timestamp="1587219014962" />
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1588302762834">
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1589857794365">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.0.1440.900@0.0.1440.900" timestamp="1588302762834" />
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.0.1440.900@0.0.1440.900" timestamp="1589857794365" />
<state x="100" y="100" width="1240" height="700" key="dock-window-1" timestamp="1585037767258">
<screen x="0" y="23" width="1440" height="797" />
</state>

@ -2,7 +2,21 @@
## ZooKeeper
### CAP定理
一个分布式系统不可能同时满足以下三种,一致性C:Consistency,可用性A:Available,分区容错性P:Partition Tolerance.在此ZooKeeper保证的是CPZooKeeper不能保证每次服务请求的可用性在极端环境下ZooKeeper可能会丢弃一些请求消费者程序需要重新请求才能获得结果。另外在进行leader选举时集群都是不可用所以说ZooKeeper不能保证服务可用性。Base理论CA强一致性和最终一致性
一个分布式系统不可能同时满足以下三种,一致性C:Consistency,可用性A:Available,分区容错性P:Partition Tolerance.在此ZooKeeper保证的是CPZooKeeper不能保证每次服务请求的可用性在极端环境下ZooKeeper可能会丢弃一些请求消费者程序需要重新请求才能获得结果。另外在进行leader选举时集群都是不可用所以说ZooKeeper不能保证服务可用性。
### BASE理论
BASE理论是基本可用软状态最终一致性三个短语的缩写。BASE理论是对CAP中一致性和可用性CA权衡的结果其来源于对大规模互联网系统分布式实践的总结是基于CAP定理逐步演化而来的它大大降低了我们对系统的要求。
1. 基本可用基本可用是指分布式系统在出现不可预知故障的时候允许损失部分可用性。但是这绝不等价于系统不可用。比如正常情况下一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果但由于出现故障查询结果的响应时间增加了1~2秒。
2. 软状态:软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
3. 最终一致性:最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
### ZooKeeper特点
1. 顺序一致性:同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
2. 原子性:所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。
3. 单一系统映像:无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。
4. 可靠性:一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。
### ZAB协议
@ -31,7 +45,7 @@ ZAB协议包括两种基本的模式崩溃恢复和消息广播。当整个 Z
1. 纯内存操作
2. 单线程操作,避免了频繁的上下文切换
3. 合理高效的数据结构
4. 采用了非阻塞I/O多路复用机制
4. 采用了非阻塞I/O多路复用机制(有一个文件描述符同时监听多个文件描述符是否有数据到来)
### Redis 的数据结构及使用场景
@ -54,6 +68,10 @@ Redis 中数据过期策略采用定期删除+惰性删除策略
5. 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。
6. 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。
### Redis的set和setnx
Redis中setnx不支持设置过期时间做分布式锁时要想避免某一客户端中断导致死锁需设置lock过期时间在高并发时 setnx与 expire 不能实现原子操作如果要用得在程序代码上显示的加锁。使用SET代替SETNX 相当于SETNX+EXPIRE实现了原子性不必担心SETNX成功EXPIRE失败的问题。
### Redis的LRU具体实现
传统的LRU是使用栈的形式每次都将最新使用的移入栈顶但是用栈的形式会导致执行select *的时候大量非热点数据占领头部数据所以需要改进。Redis每次按key获取一个值的时候都会更新value中的lru字段为当前秒级别的时间戳。Redis初始的实现算法很简单随机从dict中取出五个key,淘汰一个lru字段值最小的。在3.0的时候又改进了一版算法首先第一次随机选取的key都会放入一个pool中(pool的大小为16),pool中的key是按lru大小顺序排列的。接下来每次随机选取的keylru值必须小于pool中最小的lru才会继续放入直到将pool放满。放满之后每次如果有新的key需要放入需要将pool中lru最大的一个key取出。淘汰的时候直接从pool中选取一个lru最小的值然后将其淘汰。
@ -131,7 +149,7 @@ Redis默认是快照RDB的持久化方式。对于主从同步来说主从刚
* 最上层的服务类似其他CS结构比如连接处理授权处理。
* 第二层是Mysql的服务层包括SQL的解析分析优化存储过程触发器视图等也在这一层实现。
* 最后一层是存储引擎的实现类似于Java接口的实现Mysql的执行器在执行SQL的时候只会关注API的调用完全屏蔽了不同引擎实现间的差异。比如Select语句先会判断当前用户是否拥有权限其次到缓存内存查询是否有相应的结果集如果没有再执行解析sql优化生成执行计划调用API执行。
* 最后一层是存储引擎的实现类似于Java接口的实现Mysql的执行器在执行SQL的时候只会关注API的调用完全屏蔽了不同引擎实现间的差异。比如Select语句先会判断当前用户是否拥有权限其次到缓存内存查询是否有相应的结果集如果没有再执行解析sql检查SQL 语句语法是否正确,再优化生成执行计划调用API执行。
### SQL执行顺序
@ -512,8 +530,12 @@ HashSet的value存的是一个static finial PRESENT = newObject()。而HashSet
### 阻塞非阻塞与同步异步的区别
1. 同步和异步关注的是消息通信机制,所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。
2. 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
1. 同步和异步关注的是消息通信机制,所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下"然后开始查啊查等查好了可能是5秒也可能是一天告诉你结果返回结果。而异步通信机制书店老板直接告诉你我查一下啊查好了打电话给你然后直接挂电话了不返回结果。然后查好了他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
2. 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。
### Java SPI
由于双亲委派模型损失了一丢丢灵活性。就比如java.sql.Driver这个东西。JDK只能提供一个规范接口而不能提供实现。提供实现的是实际的数据库提供商。提供商的库总不能放JDK目录里吧。Java从1.6搞出了SPI就是为了优雅的解决这类问题——JDK提供接口供应商提供服务。编程人员编码时面向接口编程然后JDK能够自动找到合适的实现。
## Spring
@ -523,15 +545,7 @@ HashSet的value存的是一个static finial PRESENT = newObject()。而HashSet
2. 第二级缓存早期提前暴露的对象缓存earlySingletonObjects。属性还没有值对象也没有被初始化
3. 第三级缓存singletonFactories单例对象工厂缓存。
### 创建Bean的整个过程
1. getBean方法肯定不陌生必经之路然后调用doGetBean进来以后首先会执行transformedBeanName找别名看你的Bean上面是否起了别名。然后进行很重要的一步getSingleton这段代码就是从你的单例缓存池中获取Bean的实例。那么你第一次进来肯定是没有的缓存里肯定是拿不到的。也就是一级缓存里是没有的。那么它怎么办呢他会尝试去二级缓存中去拿但是去二级缓存中拿并不是无条件的首先要判断isSingletonCurrentlyInCreation(beanName)他要看你这个对象是否正在创建当中如果不是直接就退出该方法如果是的话他就会去二级缓存earlySingletonObjects里面取如果没拿到它还接着判断allowEarlyReference这个东西是否为true。它的意思是说是否允许让你从单例工厂对象缓存中去拿对象。默认为true。好了此时如果进来那么就会通过singletonFactory.getObject()去单例工厂缓存中去拿。然后将缓存级别提升至二级缓存也就早期暴露的缓存。
2. getSingleton执行完以后会走dependsOn方法判断是否有dependsOn标记的循环引用有的话直接卡死抛出异常。比如说A依赖于BB依赖于A 通过dependsOn注解去指定。此时执行到这里就会抛出异常。这里所指并非是构造函数的循环依赖。
3. beforeSingletonCreation在这里方法里。就把你的对象标记为了早期暴露的对象。提前暴露对象用于创建Bean的实例。
4. 紧接着就走创建Bean的流程开始。在创建Bean之前执行了一下resolveBeforeInstantiation。它的意思是说代理AOPBean定义注册信息但是这里并不是实际去代理你的对象因为对象还没有被创建。只是代理了Bean定义信息还没有被实例化。把Bean定义信息放进缓存以便我想代理真正的目标对象的时候直接去缓存里去拿。
5. 接下来就真正的走创建Bean流程首先走进真正做事儿的方法doCreateBean然后找到createBeanInstance这个方法在这里面它将为你创建你的Bean实例信息Bean的实例。如果说创建成功了那么就把你的对象放入缓存中去将创建好的提前曝光的对象放入singletonFactories三级缓存中将对象从二级缓存中移除因为它已经不是提前暴露的对象了。但是。如果说在createBeanInstance这个方法中在创建Bean的时候它会去检测你的依赖关系会去检测你的构造器。然后如果说它在创建A对象的时候发现了构造器里依赖了B然后它又会重新走getBean的这个流程当在走到这里的时候又发现依赖了A此时就会抛出异常。为什么会抛出异常因为走getBean的时候他会去从你的单例缓存池中去拿因为你这里的Bean还没有被创建好。自然不会被放进缓存中所以它是在缓存中拿不到B对象的。反过来也是拿不到A对象的。造成了死循环故此直接抛异常。这就是为什么Spring IOC不能解决构造器循环依赖的原因。因为你还没来的急放入缓存你的对象是不存在的。所以不能创建。同理@Bean标注的循环依赖方法也是不能解决的跟这个同理。那么多例就更不能解决了。为什么因为在走createBeanInstance的时候会判断是否是单例的Bean定义信息mbd.isSingleton()如果是才会进来。所以多例的Bean压根就不会走进来而是走了另一段逻辑这里不做介绍。至此构造器循环依赖和@Bean的循环依赖还有多例Bean的循环依赖为什么不能解决已经解释清楚。然后如果说Bean创建成功了。那么会走后面的逻辑。
6. 将创建好的Bean放入缓存addSingletonFactory方法就是将你创建好的Bean放入三级缓存中。并且移除早期暴露的对象。
7. 通过populateBean给属性赋值我们知道创建好的对象并不是一个完整的对象里面的属性还没有被赋值。所以这个方法就是为创建好的Bean为它的属性赋值。并且调用了我们实现的的XXXAware接口进行回调初始化。然后调用我们实现的Bean的后置处理器给我们最后一次机会去修改Bean的属性。
三级缓存详解:[根据 Spring 源码写一个带有三级缓存的 IOC](https://zhuanlan.zhihu.com/p/144627581)
### Spring如何解决循环依赖问题
@ -549,23 +563,38 @@ Spring使用了三级缓存解决了循环依赖的问题。在populateBean()给
2. CGlib动态代理利用ASM开源的Java字节码编辑库操作字节码开源包将代理对象类的class文件加载进来通过修改其字节码生成子类来处理。
3. 区别JDK代理只能对实现接口的类生成代理CGlib是针对类实现代理对指定的类生成一个子类并覆盖其中的方法这种通过继承类的实现方式不能代理final修饰的类。
### @Transactional 在private上会生效么
@Transactional注解只能应用在public方法上。当标记在protected、private、package-visible方法上时不会产生错误但也不会表现出为它指定的事务配置。可以认为它作为一个普通的方法参与到一个public方法的事务中。
### Spring的的事务传播机制
1. REQUIRED默认支持使用当前事务如果当前事务不存在创建一个新事务。
1. REQUIRED默认,常用):支持使用当前事务,如果当前事务不存在,创建一个新事务。eg:方法B用REQUIRED修饰方法A调用方法B如果方法A当前没有事务方法B就新建一个事务若还有C则B和C在各自的事务中独立执行如果方法A有事务方法B就加入到这个事务中当成一个事务。
2. SUPPORTS支持使用当前事务如果当前事务不存在则不使用事务。
3. MANDATORY强制支持使用当前事务如果当前事务不存在则抛出Exception。
4. REQUIRES_NEW创建一个新事务如果当前事务存在把当前事务挂起。
4. REQUIRES_NEW(常用):创建一个新事务,如果当前事务存在,把当前事务挂起。eg:方法B用REQUIRES_NEW修饰方法A调用方法B不管方法A上有没有事务方法B都新建一个事务在该事务执行。
5. NOT_SUPPORTED无事务执行如果当前事务存在把当前事务挂起。
6. NEVER无事务执行如果当前有事务则抛出Exception。
7. NESTED嵌套事务如果当前事务存在那么在嵌套的事务中执行。如果当前事务不存在则表现跟REQUIRED一样。
### Spring中Bean的生命周期
1. 实例化 Instantiation
2. 属性赋值 Populate
3. 初始化 Initialization
4. 销毁 Destruction
### Spring的后置处理器
1. BeanPostProcessorBean的后置处理器主要在bean初始化前后工作。
2. InstantiationAwareBeanPostProcessor继承于BeanPostProcessor主要在实例化bean前后工作 AOP创建代理对象就是通过该接口实现。
1. BeanPostProcessorBean的后置处理器主要在bean初始化前后工作。before和after两个回调中间只处理了init-method
2. InstantiationAwareBeanPostProcessor继承于BeanPostProcessor主要在实例化bean前后工作TargetSource的AOP创建代理对象就是通过该接口实现
3. BeanFactoryPostProcessorBean工厂的后置处理器在bean定义(bean definitions)加载完成后bean尚未初始化前执行。
4. BeanDefinitionRegistryPostProcessor继承于BeanFactoryPostProcessor。其自定义的方法postProcessBeanDefinitionRegistry会在bean定义(bean definitions)将要加载bean尚未初始化前真执行即在BeanFactoryPostProcessor的postProcessBeanFactory方法前被调用。
### Spring MVC的工作流程源码层面
参考文章:[自己写个Spring MVC](https://zhuanlan.zhihu.com/p/139751932)
## 消息队列
### 为什么需要消息队列
@ -768,6 +797,13 @@ void quick_sort(int a[], int low, int high){
* 降级:服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。
* 限流:限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。
### 负载均衡算法:
1. 轮询
2. 加权轮询
3. 随机算法
4. 一致性Hash
### 常见的限流算法:
常见的限流算法有计数器、漏桶和令牌桶算法。漏桶算法在分布式环境中消息中间件或者Redis都是可选的方案。发放令牌的频率增加可以提升整体数据处理的速度而通过每次获取令牌的个数增加或者放慢令牌的发放速度和降低整体数据处理速度。而漏桶不行因为它的流出速率是固定的程序处理速度也是固定的。

Loading…
Cancel
Save