0%

Nginx 配置限流:基于漏桶算法的流量控制策略

在高并发场景中,突发流量可能导致服务器过载、响应延迟甚至崩溃。Nginx 提供了基于漏桶算法的限流功能,通过limit_req_zonelimit_req指令控制请求速率,保护后端服务稳定。本文详细讲解 Nginx 限流的配置方法、核心参数及实战场景,帮助合理管控流量。

限流核心原理:漏桶算法

Nginx 限流基于漏桶算法(Leaky Bucket),其核心逻辑如下:

  • 想象一个 “漏桶”,请求如同水流注入桶中,桶底有一个固定速率的 “漏洞”;
  • 若请求注入速度超过漏洞的漏水速度,多余的水(请求)会溢出(被拒绝);
  • 通过控制漏洞的速率(rate)和桶的容量(burst),实现请求的匀速处理,避免瞬间压力。

基础配置:limit_req_zonelimit_req

Nginx 限流需两步配置:先在http块定义限流规则(limit_req_zone),再在location/server块应用规则(limit_req)。

定义限流区域(limit_req_zone

1
2
3
4
5
6
7
http {
# 定义限流规则
# $binary_remote_addr:以客户端IP的二进制形式作为key(节省内存)
# zone=mylimit:1m:创建名为mylimit的共享内存区域,大小1M(约可存储16000个IP状态)
# rate=1r/m:限制速率为每分钟1个请求(r/s表示每秒,r/m表示每分钟)
limit_req_zone $binary_remote_addr zone=mylimit:1m rate=1r/m;
}
阅读全文 »

Shell 位置参数变量:处理命令行传参的实用指南

在 Shell 脚本中,位置参数变量用于接收和处理命令行传入的参数,是实现脚本灵活性和复用性的关键。无论是简单的参数传递还是复杂的批量处理,掌握位置参数变量都能高效完成任务。以下是详细解析和示例。

基础位置参数变量

1. $n:按序号获取参数

  • $0:表示脚本本身的名称(包含路径时显示完整路径)。
  • $1~$9:表示第 1 到第 9 个参数。
  • ${10}及以上:10 个以上的参数需用大括号包裹(如${10}${11})。

示例params.sh 脚本

1
2
3
4
5
#!/bin/bash
echo "脚本名称:$0"
echo "第1个参数:$1"
echo "第2个参数:$2"
echo "第10个参数:${10}"

执行脚本:

1
sh params.sh a b c d e f g h i j k

输出:

1
2
3
4
脚本名称:params.sh
第1个参数:a
第2个参数:b
第10个参数:j

2. $#:获取参数总数

  • 表示命令行传入的参数总个数(不包含脚本名称$0)。
阅读全文 »

Bash 中的特殊符号:全面解析与实用指南

Bash shell 中有的特殊符号是实现复杂命令和脚本逻辑的基础,它们赋予了 Shell 强大的文本处理和流程控制能力。理解这些符号的含义和用法,能帮助你写出更简洁、高效的命令和脚本。

引号类符号:控制字符解析

单引号 ''

  • 作用强引用,单引号内的所有字符(包括特殊符号)都被视为普通字符,无特殊含义。
  • 适用场景:需要原样输出包含特殊符号(如 $!空格)的字符串。

示例

1
2
3
name="Alice"
echo 'Hello $name' # 输出:Hello $name($name 不解析为变量)
echo '当前目录:$(pwd)' # 输出:当前目录:$(pwd)(命令不执行)

双引号 ""

  • 作用:弱引用,双引号内大部分字符视为普通字符,但保留以下特殊符号的含义:
    • $:引用变量(如 $name
    • `:执行命令(如date``)
    • \:转义符(如 \" 表示输出双引号)
  • 适用场景:需要保留变量和命令执行结果,同时避免空格等字符被拆分。

示例

阅读全文 »

Redis 跳跃表(Skiplist)实现详解(基于 6.0.10 版本)

跳跃表(Skiplist)是一种高效的有序数据结构,通过在节点中维护多层指针,实现快速查找、插入和删除操作(平均时间复杂度 O (logN))。Redis 中,跳跃表是有序集合(ZSet)的底层实现之一(当 ZSet 元素数量多或元素较大时使用,替代 ziplist)。本文结合 Redis 源码中的结构体,详解跳跃表的设计与工作原理。

跳跃表的核心作用

ZSet 需要支持按分值(score)排序快速范围查询(如 ZRANGEZREVRANGE),跳跃表相比其他结构(如平衡树)的优势:

  • 实现简单:无需像红黑树那样维护复杂的旋转平衡逻辑。
  • 性能均衡:查找、插入、删除的平均时间复杂度均为 O (logN),且常数因子小。
  • 适合范围查询:通过层级指针可直接定位到范围起点,高效遍历区间元素。

跳跃表的结构体设计

Redis 中跳跃表由两个核心结构体组成:zskiplistNode(节点)和 zskiplist(表本身),定义如下(简化自源码):

跳跃表节点(zskiplistNode

1
2
3
4
5
6
7
8
9
typedef struct zskiplistNode {
sds ele; // 存储的元素(字符串,ZSet 中的 member)
double score; // 分值,用于排序(ZSet 中按 score 排序)
struct zskiplistNode *backward; // 后退指针(仅指向当前节点的前一个节点,用于反向遍历)
struct zskiplistLevel { // 层级数组(每个层级包含前进指针和跨度)
struct zskiplistNode *forward; // 前进指针(指向同一层级的下一个节点)
unsigned long span; // 跨度(当前节点到 forward 指向节点的"距离",用于计算排名)
} level[]; // 柔性数组(层级数量动态分配,每层独立维护指针)
} zskiplistNode;
关键字段解析:
  • ele:ZSet 中的成员(member),是一个字符串(sds 类型),具有唯一性(ZSet 不允许重复 member)。
  • score:成员对应的分值,ZSet 按 score 升序排序(相同 score 的节点按 ele 字典序排序)。
  • backward:后退指针,仅用于反向遍历(如 ZREVRANGE),指向当前节点的前一个节点(类似双向链表的 prev 指针),但仅在最底层有效。
  • level[]:层级数组,是跳跃表 “跳跃” 特性的核心:
    • 每个节点的层级数量是随机生成的(通常 1-64 层,Redis 中最大层级为 64)。
    • 层级越高,前进指针跨越的节点越多,查询时可快速 “跳过” 无关节点。

跳跃表本身(zskiplist

阅读全文 »

Redis intset(整数集合)实现详解(基于 6.0.10 版本)

intset(整数集合)是 Redis 中 Set 类型的底层实现之一,专门用于存储整数值元素(如 int16_t、int32_t、int64_t)。当 Set 中仅包含整数且元素数量较少时,Redis 会选择 intset 而非哈希表(hashtable),以节省内存空间。

intset 的核心设计目标

  • 内存高效:相比哈希表(需存储键值对和指针),intset 以紧凑数组形式存储整数,无冗余开销。
  • 类型灵活:支持不同长度的整数(16 位、32 位、64 位),并能自动升级编码以容纳更大的整数。
  • 有序性:元素在数组中按升序排列,支持快速查找(二分查找)。

intset 的结构体设计

intset 的结构体定义简洁高效,源码如下:

1
2
3
4
5
typedef struct intset {
uint32_t encoding; // 编码方式(决定元素的类型和长度)
uint32_t length; // 元素数量
int8_t contents[]; // 柔性数组,存储整数元素(实际类型由 encoding 决定)
} intset;

各字段详解:

阅读全文 »