赞
踩
127.0.0.1:6379> info memory # Memory #redis分配的内存总量,包括虚拟内存(字节) used_memory:727400 used_memory_human:710.35K #占操作系统的内存,不包括虚拟内存(字节) used_memory_rss:686368 used_memory_rss_human:670.28K used_memory_peak:727400 used_memory_peak_human:710.35K used_memory_peak_perc:100.01% used_memory_overhead:715334 used_memory_startup:665048 used_memory_dataset:12066 used_memory_dataset_perc:19.35% allocator_allocated:39539472 allocator_active:310378496 allocator_resident:314572800 total_system_memory:0 total_system_memory_human:0B used_memory_lua:37888 used_memory_lua_human:37.00K used_memory_scripts:0 used_memory_scripts_human:0B number_of_cached_scripts:0 maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction allocator_frag_ratio:7.85 allocator_frag_bytes:270839024 allocator_rss_ratio:1.01 allocator_rss_bytes:4194304 rss_overhead_ratio:0.00 rss_overhead_bytes:-313886432 #内存碎片比例,如果小于0说明使用了虚拟内存 mem_fragmentation_ratio:1.00 mem_fragmentation_bytes:0 mem_not_counted_for_evict:0 mem_replication_backlog:0 mem_clients_slaves:0 mem_clients_normal:49950 mem_aof_buffer:0 #redis使用的内存分配器 mem_allocator:jemalloc-5.2.1 active_defrag_running:0 lazyfree_pending_objects:0
作为数据库,数据是最主要的部分,这部分占用内存会统计在used_memory中。
redis使用键值对存储数据,其中的值(对象)包括5种类型,字符串、哈希、列表、集合、有序集合。这5种类型树对外提供的,实际上,在redis内部每种类型都有2种或更多的编码方式实现。
redis主进程本身需要占用一定内存,如代码、常量池等等,这部分内存大约有几M。
这部分内存不是由jemalloc分配,因此不会统计在used_memory中。
除了主进程外,redis创建的子线程也会占用内存,如redis执行AOF、RDB重写时创建的子进程,这部分内存不属于redis进程,不会统计在used_memory和used_memory_rss中。
缓冲内存包括客户端缓冲区、复制区积压缓冲区、AOF缓冲区等;其中客户端缓冲区存储在客户端连接的输入输出缓冲;复制积压缓冲区用于部分复制功能;AOF缓冲区用于在进行AOF重写时,保存最近的写入命令。
这部分内存由jemalloc分配,因此会统计在used_memory。
内存碎片是redis在分配、回收物理内存过程中产生的。例如,如果对数据的更改频繁,而且数据之间的大小相差很大,可能导致redis释放的空间在物理内存中并没有释放。但redis由无法有效利用,这就形成了内存碎片,内存碎片不会统计在used_memory中。
内存碎片的产生与对数据进行的操作、数据的特点等有关,此外,与使用的内存分配器有关:如果内存分配器设计合理,可以尽可能的减少内存碎片的产生。如果redis服务器中的内存碎片已经很大,可以通过安全重启的方式减少内存碎片,因为重启之后redis重新从备份文件中读取数据,在内存中进行重排,为每个数据重新选择合适的内存单元,减少内存碎片。
redis没有直接使用C字符串(以空字符串’\0’结尾的字符数组)作为默认的字符串表示,而是使用了SDS,SDS是简单动态字符串(Simple Dynamic String)的缩写。
SDS定义:
struct sdshdr{
//记录buf数组中已使用字节的数量
//等于 SDS 保存字符串的长度
int len;
//记录 buf 数组中未使用字节的数量
int free;
//字节数组,用于保存字符串,以'\0'结尾
char buf[];
}
buf数组的长度=free+len+1
好处:
SDS在C字符串上加入了len和free字段
获取字符串长度:SDS是O(1),C字符串是O(n)
缓冲区溢出:使用C字符串的API时,如果字符串长度增加而忘记重新分配内存,很容易造成缓冲区的溢出。而SDS由于记录了长度,相应的API在可能造成缓冲区溢出时会自动重新分配内存,杜绝了缓冲区溢出。
修改字符串时内存重新分配:对于C字符串,如果要修改字符串,必须要重新分配内存(先释放再申请),如果没有重新分配,字符串长度增大时会造成缓冲区溢出,字符串长度减少时,会造成内存泄漏。
SDS由于可以记录len和free,因此解除了字符串长度和空间数组长度之间的关联,可以在此基础上进行优化。
空间预分配策略(即分配内存时比实际需要的多)使得字符串长度增大时重新分配内存的概率大大减
小;惰性空间释放策略使得字符串长度减小时重新分配内存的概率大大减小。
存取二进制数据:SDS 可以,C 字符串不
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。