nginx–基础–19–共享内存
1、nginx的进程间的通讯方式
2、共享内存
- 如果需要做数据的同步 只能通过共享内存
- 所有worker进程协同工作的关键:共享内存
2.1、定义
- 我们打开了一块内存,比如说10M,一整块0到10M之间,多个worker进程之间可以同时的访问它,包括读取和写入。
2.2、共享内存会引入两个问题
01、同时操作一块内存,一定会存在竞争关系
- 因为多个worker进程同时操作一块内存,一定会存在竞争关系,所以我们需要加锁,nginx所使用的锁是自旋锁.
02、怎么管理内存
- 因为一整块共享内存是往往是给许多对象同时使用的,如果我们在模块中手动控制内存,且分配给到不同的对象,这是非常繁琐的,所以这个时候我们使用了Slab内存管理器。
3、Nginx哪些模块使用了共享内存?
3.1、用共享内存主要使用两种数据结构
01、rbtree:红黑树
-
我们想做限速和流控等等场景时,我们是不能容忍在内存当中做的,否则一个worker进程对某一个用户触发了流控,而其它worker进程还不知道,所以我们只能在共享内存中做。
-
红黑树特点
- 插入删除非常的快,当然也可以做遍历,这是共享内存使用红黑树的主要原因。
-
所以如下的模块都有一个特点;需要做快速地插入和删除;
02、单链表
- 只需要把这些共享的元素串联起来就可以了
3.2、案例
01、lua_shared_dict dogs 10m
- 分配一块共享内存,叫做dogs,大小10m
02、/set 请求
- 从dogs共享内存中取出空间(A)
- 设置 key=jim,value=8
- 向客户端返回"STORED"
03、/get 请求
- 从dogs共享内存中取出空间(A)
- 把Jim的值8取出来,返回给用户
04、解释
- 在这一段代码中,我们同时使用了红黑树和单链表
- lua_shared_dict dogs 10m 使用红黑树来保存每一个key-value,比如其中一个节点是(Jim,8)
- 为什么还需要一个链表?
- 当达到10m的最大值时,lua_shared_dict 采用了lru淘汰最早不使用的节点,这时lua_shared_dict同时满足了红黑树和链表。
4、共享内存工具:Slab管理器
4.1、架构
4.2、Bestfit结构
- 把整块的共享内存分为很多页面,每个页面切分为很多slot。
- slot的大小是2的n次方。比如32字节,64字节,128字节
- 内存分配是匹配最小的slot。
- 现在有一个51字节需要分配的内存,他会选择64字节的slot
- 所以上图中slot就是指向不同大小的块
4.2.1、特点
- 会有内存的浪费的,最多浪费2倍内存。
- 比如:51字节用64字节的slot,浪费13字节。
4.2.2、好处
- 适合小对象:如果我们要分配的对象的内存非常小,比如小于一个页面的大小,就非常合适
- 避免碎片:
- 每分配一块内存,就会找这个页面未使用的slot,继续使用就可以。
- 当一个页面使用满以后,我再拿一个空白的页面继续给此类slot大小的内存继续使用就可以
- 避免初始化:
- 分配在某段内存上的数据结构它是固定的,且完成了初始化,当我重复使用的话,避免了初始化
4.3、数据的监控和统计
- 安装openresty,使用slab_stat模块
4.3.1、安装LuaJIT
wget -c http://luajit.org/download/LuaJIT-2.0.4.tar.gz
tar xzvf LuaJIT-2.0.4.tar.gz
cd LuaJIT-2.0.4
make install PREFIX=/usr/local/luajit
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0
echo "/usr/local/luajit/lib" >> /etc/ld.so.conf
4.3.2、安装nginx
http://tengine.taobao.org/download_cn.html
下载
wget http://tengine.taobao.org/download/tengine-2.3.2.tar.gz
解压
tar -zxvf tengine-2.3.2.tar.gz
编译且添加ngx_slab_stat模块
./configure --prefix=/usr/local/tengine --add-module=/home/packages/tengine-2.3.2/modules/ngx_slab_stat --add-module=/home/packages/tengine-2.3.2/modules/ngx_http_lua_module
make
make install
验证模块是否安装成功
[root@zhoufei sbin]# ./nginx -V
修改配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
lua_shared_dict dogs 10m;
server {
listen 7000;
server_name localhost;
location = /slab_stat {
slab_stat;
}
location /set {
content_by_lua_block{
local dogs=ngx.shared.dogs
dogs:set("Jim",8)
ngx.say("STORED");
}
}
location /get {
content_by_lua_block{
local dogs=ngx.shared.dogs
ngx.say(dogs:get("Jim"))
}
}
}
}
测试
http://60.205.188.229:7000/slab_stat