0%

限流

大众的限流方案有三种,一种是计数器,一种是漏桶算法,一种是令牌算法

计数器

分为固定窗口和滑动窗口

固定窗口计数器

固定窗口比较简单粗暴,如果假定某个接口1s最多接收100个请求,维护一个固定单位时间的计数器,检测到单位时间过去则重置计数器为0

其不能应对突发的流量,如1s中前100ms处理了99个请求,最后900ms就只能处理一个了

滑动窗口计数器

滑动窗口是对固定窗口的改进

  • 将单位时间分为多个区间,每个区间都有一个计数器,有一个请求落在该区间内,则该区间的计数器就会加一
  • 每过一段时间,时间窗口就会滑动一格,抛弃最老的一个区间,并纳入一个新的区间
  • 计算整个时间窗口内的请求总数时会累加所有时间片段内的计数器

漏桶算法

漏桶算法是利用一个缓存区,当请求进入系统时,无论请求的速率如何,都先在缓存区内保存,然后以固定的流速流出缓存区进行处理,使用队列实现

  • 将每个请求放入固定大小的队列进行存储
  • 队列以固定速率向外流出请求,如果队列为空则停止流出
  • 如果队列满了则多余的请求就被直接拒绝

限制的是流量的流出速率,对于流量均衡的可以使用该方式

无法应对突发的大流量

令牌桶算法

令牌桶算法是一种反向的漏桶算法,桶中存放的不再是请求,而是令牌,只有拿到令牌后,才能对请求进行处理,如果没有令牌,就需要等待可用的令牌,为了限制流速,该算法每单位时间产生一定量的令牌存入桶中

限制的是流量的平均流入速率,可以应对突发流量

Nginx的限流模块就是采用令牌桶算法的实现

  • 每秒有r个令牌放入桶中
  • 桶的容量不变,如果桶满了则不进行存储令牌
  • 如果请求来了,没有令牌会被限流

请求地址过长

有一次在进行表单提交的时候,由于参数过多,导致请求无法提交,使用的是nginx和resin,我一开始以为resin没有限制请求地址长度,只改了nginx

1
2
3
# http块内
client_header_buffer_size 100k;
large_client_header_buffers 4 100k;

结果改了之后还是不行,一开始还以为是nginx的配置没生效呢,结果看到nginx的access日志中已经有了该请求了,就去看了一下resin的日志,发现resin报错了URL or HTTP headers are too long

1
<cluster id="app" url-length-max="20480" header-size-max="20480">

elasticsearch简介

elasticsearch是基于Lucene的开源搜索引擎,虽然Lucene性能很好且功能齐全,但是非常复杂,所以elasticsearch使用Lucene作为核心来实现所有索引和搜索的功能,目的是通过简单地restful api来隐藏Lucene的复杂性

基本概念

文档

数据存储基本单元,文档信息能被索引,并且采用json格式传递

类型

同一个索引可被定义为多个类型,类型属于索引的逻辑分类(在6.x每个索引下只能创建一个type,在7.x直接不允许创建type,只有一个默认type)

阅读全文 »

事务的实现

MySQL在进行事务处理的时候采用了日志先行的方式来保证事务可快速和持久运行,在写数据之前,先写日志,开始事务时,会记录该事务的一个LSN日志序列号;当执行事务时,会往Innodb_log_buffer日志缓冲区中插入事务日志(redo log);当事务提交时,会将日志缓冲区里的事务刷入磁盘,由innodb_flush_log_at_trx_commit参数进行控制何时刷入磁盘

  • 0 延迟写 事务提交时不会将redo log buffer中日志写入到os buffer中,而是每秒写入os buffer并调用fsync()写入到redo log file中,如果系统崩溃,将丢失1秒的数据,性能最好,但是安全性最差
  • 1 实时写,实时刷 事务每次提交都会将redo log buffer中的日志写入到os buffer并调用fsync()刷到redo log file中,虽然不会丢失数据,但是每次都写入磁盘,IO性能较差
  • 2 实时写,延迟刷 每次提交将redo log buffer中的日志写入os buffer,但是每秒调用一次fsync()将os buffer中的日志写入到redo log file中
阅读全文 »