0%

内存方面的知识真是博大精深,把一些看到的零碎的知识点做个笔记总结下。

这些知识只是自己的理解,并不能保证正确,ULK和《深入理解Linux虚拟内存管理》这两本书看完以后还会来更新这篇的内容。


段式管理与页式管理

在操作系统理论中

阅读全文 »

内存管理有两篇文章讲的还是满清晰的:

操作系统学习笔记-储存管理

The Linux Kernel-Chapter 3 Memory Management

下面这本书是有不少中文翻译的,可以自行查找

本文主要是讨论伙伴算法的,讲伙伴算法的文章虽然多,但是没几篇讲的很清楚的。我也是结合了几篇文章看了好久才弄明白,特地记下来。

阅读全文 »

业务线上出错,返回给用户的结果不正确。

使用了ZINTERSTORE这个接口对多个集合做交并集返回预期外的空集。如下图:

error操作
error操作

这是因为twemproxy只是把指令转发给redis而已,而多个集合被哈希算法分片在不同的redis节点上,所以转发这个redis并没有这几个集合,会直接返回空集。

这并不是BUG,redis3.0也存在这个特性,当多个集合做交并集操作时,需要使用hash_tag特性。

阅读全文 »

由于twemproxy的多进程改造计划,所以对教科书一般的nginx的管理方式做了分析

nginx的-s指令可以对进程执行多个命令。

这些命令由主进程接受信号然后在循环中对状态进行判断,然后通过unix socket或者信号的方式传达给子进程。

从代码里面可以看到如下状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for()
{
if (delay) {}
sigsuspend();
ngx_time_update();
if (ngx_reap) {} //需要重启工作进程
if (!live && (ngx_terminate || ngx_quit)) {} //工作进程都结束,自己也设定了结束,那么退出
if (ngx_terminate) {} //强制退出状态
if (ngx_quit) {} //优雅退出状态
if (ngx_reconfigure) {} //配置热加载
if (ngx_restart) {} //重启(配置不变)
if (ngx_reopen) {} //重新打开日志
if (ngx_change_binary) {} //二进制文件改变
if (ngx_noaccept) {} //不再接受新连接
}
阅读全文 »

nginx的文件缓存分为两种,内存缓存和硬盘缓存。

内存缓存指文件句柄等信息进行缓存,减少使用open等的系统调用。

硬盘缓存指文件被缓存到硬盘上,一般是因为当作反向代理用才会有这种需求。

内存缓存是全模块都可以调用的,因为封装在core/ngx_open_file_cache.c中。

而硬盘缓存只有http模块可以调用,因为封装在http/ngx_http_file_cache.c中,最常见的就是upstream模块的cache了。

阅读全文 »

C的内存管理难已经成为了共识。记得我那时候写ydfs,第一次接触全异步编程这种模式,没有考虑到内存的统一管理,导致溢出泄漏问题层出不穷。最终搞定没BUG了,那代码的阅读质量也是让人不敢恭维。那么来看看nginx是怎么做的吧。

nginx的内存池分为池(pool)和块(block)两个概念

这是nginx使用到的内存结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct ngx_pool_large_s  ngx_pool_large_t;

struct ngx_pool_large_s {
ngx_pool_large_t *next;
void *alloc;
};

//块
typedef struct {
u_char *last;//块目前已分配内存的末尾
u_char *end;//块总共可分配内存的末尾
ngx_pool_t *next;//下个块的指针(注意这里虽然是池类型,\
//但是实际上的使用中池的一些数据结构并没有全部用到,基本上是当块来用的)
ngx_uint_t failed;//在该块上尝试分配内存的错误次数
} ngx_pool_data_t;

//池
struct ngx_pool_s {
ngx_pool_data_t d;//内存池的第一个块
size_t max;//池中块支持的最大大小,大于该大小将分配在large结构中
ngx_pool_t *current;//指向当前的块
ngx_chain_t *chain;//
ngx_pool_large_t *large;//大内存链表
ngx_pool_cleanup_t *cleanup;//清理数据的回调
ngx_log_t *log;//日志指针
};


typedef struct {
ngx_fd_t fd;
u_char *name;
ngx_log_t *log;
} ngx_pool_cleanup_file_t;

池中以链表的形式保存许多块以及large链表。这是从数据结构中能大致看出的东西。

阅读全文 »

Why

nginx把整个时间的系统调用都封装了一遍。

其中有两个原因

1 不谈其他平台,至少在linux上,很多时间相关的系统调用不是async-signal-safe或thread-safe的。

例如local_time_r虽然是thread-safe的但不是async-signal-safe的,当然local_time两个都不是。

阅读全文 »

现象一:

昨天DBA反应线上存在某个redis slave 状态为down,反复重启无效

观察slave日志:

1
1

发现出现多次全同步,并且报出connect lost同步失败。

阅读全文 »