开发者社区> 技术小阿哥> 正文

memcached演练(5) 内存管理

简介:
+关注继续查看

memcached 是高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态 Web 应用的速度、提高可扩展性。很显然,弄清楚它的内存存储,很有必要。还是那句话,不需要兜书包了,把自己整理的相关memcached内存管理方面的框架图分享一下。

wKioL1ev3LqxbhLQAASqGDiEGmU670.png


个人喜欢把内存管理,分为3个学习单元。

  1. 如何分配内存?

  2. 如何回收内存?

  3. 如何监控内存?

当然,本文的主要演练重点也有了。

  1. 内存如何分配

  2. 内存如何回收

  3. 认识监控参数

  4. 验证一些边界数据

1.如何分配内存?

  1.1 默认启动内存分配情况

wKiom1ev4-yC9LhFAAF9Caoi5bs161.png

这段输出日志,可以分成2部分阅读。第一部分是slab内存分配信息;第二个:启用监听情况。

有3点没太搞清楚。

  1. 为什么每次启动都是2个"send buffer....",而且都是28,32。

  2. 每个server listening前面的26-35的数字编号是何含义?为什么不从0开始。

  3. 括号里面的udp,是说明监听UDP类型协议吗?监听TCP协议监听呢呢?

有对这一块比较清楚的麻烦指导下,但还好不清楚这几点不影响大局。

1.2 自定义启动规则

接下来,通过修改下启动参数,看下输出的日志。对比学习下。

wKiom1ev7S7TyCcvAADpi2GMIvQ734.png

通过对比,我们很容易理解一些基本概念。chunk size,增长因子。

值得一提的的有一个指标。

1
2
3
4
5
6
7
8
## -t 4时,监控curr_connections
## 4*2+2=10
[root@hadoop1 hadoop]# echo stats | nc 127.0.0.1 11211 |grep connection
STAT curr_connections 10
## -t 2时,监控curr_connections
## 2*2+2=6
[root@hadoop1 hadoop]# echo stats | nc 127.0.0.1 11211 |grep connection
STAT curr_connections 6

3. 监控保存数据前后slab信息

保存数据之前监控slabs信息如下

1
2
3
[root@hadoop1 hadoop]# echo stats slabs | nc 127.0.0.1 11211
STAT active_slabs 0
STAT total_malloced 0

保存数据之后监控slabs信息如下

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
set key 1 1 1
1
STORED
set key2 1 0 1
1
STORED
set key2 1 0 1
1
STORED
set key3 1 0 1
3
STORED
 
[root@hadoop1 hadoop]# echo stats slabs | nc 127.0.0.1 11211
STAT 1:chunk_size 80
STAT 1:chunks_per_page 13107
STAT 1:total_pages 1
STAT 1:total_chunks 13107
STAT 1:used_chunks 2
STAT 1:free_chunks 13105
STAT 1:free_chunks_end 0
STAT 1:mem_requested 108
STAT 1:get_hits 0
STAT 1:cmd_set 4
STAT 1:delete_hits 0
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 0
STAT 1:cas_badval 0
STAT 1:touch_hits 0
STAT active_slabs 1
STAT total_malloced 1048560
END

通过分析日志,可以很清楚的知道,发起的操作记录。

共发起了4个set或add操作.使用了2个大小为80的chunk。

值得一提下,保存的数据都非常小,却占用了160字节。好心疼浪费的存储空间啊。

通过监控total_malloced指标,还验证了,memcached采用预分配,分组管理方式。

当真正有数据保存时,才真正分配内存空间。而且,只有slab class被使用了之后,才能通过stat slabs监控到。

2.内存如何回收

内存回收不太方便验证,LRU算法使用情况,我们可以从侧面验证下。

我的演练思路:批量添加等大小的数据。然后dump出想要数据,确认下最小的KEY。

虽然简单粗暴,但大体可以说明LRU算法吧。

2.1 准备批量添加数据代码

使用的是《memcached演练(2) 访问memcached服务 》提到的spymemcached

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void test111() throws ExecutionException, InterruptedException {
    final MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient();
   final Lock lock = new ReentrantLock();
    final String value="abcdef.....";
    //不停的set值
  Thread t1=  new Thread(new Runnable() {
        @Override
        public void run() {
            for(int i=0;i<10000000;i++){
            //    System.out.println("i="+i);
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String key = "lrutestkey_"+StringUtils.leftPad(""+i,10,"0");;
                mcc.set(key, 19000, value);
            }
        }
    },"setting data");
          t1.start();
    t1.join();
    mcc.shutdown();
}

简单dump了几次,片段如下

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 13512
Dumping bucket 10 - 13512 total items
add lrutestkey_0000000000 0 1471172545 512
add lrutestkey_0000000001 0 1471172545 512
add lrutestkey_0000000002 0 1471172545 512
...
 
add lrutestkey_0000002688 0 1471172763 512
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 7530
Dumping bucket 10 - 7530 total items
add lrutestkey_0000002665 0 1471172762 512
add lrutestkey_0000002670 0 1471172762 512
...
 
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 7530
Dumping bucket 10 - 7530 total items
add lrutestkey_0000005142 0 1471172787 512
add lrutestkey_0000005143 0 1471172787 512
add lrutestkey_0000005144 0 1471172787 512
...
 
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 7530
Dumping bucket 10 - 7530 total items
add lrutestkey_0000016755 0 1471172903 512
add lrutestkey_0000016760 0 1471172903 512
...
 
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 7530
Dumping bucket 10 - 7530 total items
add lrutestkey_0000035102 0 1471173087 512
add lrutestkey_0000035103 0 1471173087 512
add lrutestkey_0000035110 0 1471173087 512
...

对比这5个片段,dump出最小的键值是越来越大,这说明,随着数据的增加,因为越小的KEY,数据越老,所以优先会被踢出。基本可以说明LRU算法逻辑。

还有一点,要说吗,踢出数据的过程,是按时间点进行的,不是时刻进行的。

3.监控slab参数

3,1 插入了100条数据,监控结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@hadoop1 scripts]# echo stats slabs | nc 127.0.0.1 11211
STAT 10:chunk_size 696
STAT 10:chunks_per_page 1506
STAT 10:total_pages 1
STAT 10:total_chunks 1506
STAT 10:used_chunks 100
STAT 10:free_chunks 1406
STAT 10:free_chunks_end 0
STAT 10:mem_requested 58400
STAT 10:get_hits 0
STAT 10:cmd_set 100
STAT 10:delete_hits 0
STAT 10:incr_hits 0
STAT 10:decr_hits 0
STAT 10:cas_hits 0
STAT 10:cas_badval 0
STAT 10:touch_hits 0
STAT active_slabs 1
STAT total_malloced 1048176
END

3.2 调用memcached-tool dump数据

1
2
3
4
5
6
7
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 100
Dumping bucket 10 - 100 total items
add lrutestkey_0000000000 0 1471173457 512
...

3.3 stats slabs监控结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[hadoop@hadoop1 ~]$ echo stats slabs  | nc 127.0.0.1 11211
STAT 10:chunk_size 696
STAT 10:chunks_per_page 1506
STAT 10:total_pages 1
STAT 10:total_chunks 1506
STAT 10:used_chunks 100
STAT 10:free_chunks 1406
STAT 10:free_chunks_end 0
STAT 10:mem_requested 58400
STAT 10:get_hits 100
STAT 10:cmd_set 100
STAT 10:delete_hits 0
STAT 10:incr_hits 0
STAT 10:decr_hits 0
STAT 10:cas_hits 0
STAT 10:cas_badval 0
STAT 10:touch_hits 0
STAT active_slabs 1
STAT total_malloced 1048176
END

结果

memcached-tool 引起了get_hits 的从原来的0变成100;由于,批量添加的100条数据值均是512字节长度。 加上item的长度32,等于544. 再加上key的长度21, 一共是563.

所以会放到slab class  10() chunk size 696 ),而不是放到slab class   9(chunk size       552)。

3.4 memcached-tool监控

3.4.1准备测试数据

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
public void test111() throws ExecutionException, InterruptedException {
    final MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient();
   final Lock lock = new ReentrantLock();
  Thread t1=  new Thread(new Runnable() {
        @Override
        public void run() {
            for(int i=0;i<1000;i++){
            //    System.out.println("i="+i);
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String key = "lrutestkey_"+StringUtils.leftPad(""+i,10,"0");
                int size =new Random().nextInt(1000);
                String value = RandomStringUtils.randomAlphanumeric(size);
                mcc.set(key, 19000, value);
                System.out.println(key+"-->"+value);
            }
        }
    },"setting data");
          t1.start();
    t1.join();
    mcc.shutdown();
}

3.4.2 运行memcached-tool命令

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
[hadoop@hadoop1 scripts]$ ./memcached-tool localhost:11211
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      80B        23s       1      10     yes        0        0    0
  2     104B        23s       1      26     yes        0        0    0
  3     136B        24s       1      30     yes        0        0    0
  4     176B        22s       1      37     yes        0        0    0
  5     224B        24s       1      47     yes        0        0    0
  6     280B        24s       1      50     yes        0        0    0
  7     352B        24s       1      72     yes        0        0    0
  8     440B        24s       1      93     yes        0        0    0
  9     552B        24s       1      91     yes        0        0    0
 10     696B        24s       1     142     yes        0        0    0
 11     872B        24s       1     174     yes        0        0    0
 12     1.1K        24s       1     228     yes        0        0    0
[hadoop@hadoop1 scripts]$ ./memcached-tool localhost:11211 display
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      80B       361s       1      10     yes        0        0    0
  2     104B       361s       1      26     yes        0        0    0
  3     136B       362s       1      30     yes        0        0    0
  4     176B       360s       1      37     yes        0        0    0
  5     224B       362s       1      47     yes        0        0    0
  6     280B       362s       1      50     yes        0        0    0
  7     352B       362s       1      72     yes        0        0    0
  8     440B       362s       1      93     yes        0        0    0
  9     552B       362s       1      91     yes        0        0    0
 10     696B       362s       1     142     yes        0        0    0
 11     872B       362s       1     174     yes        0        0    0
 12     1.1K       362s       1     228     yes        0        0    0

可以很清楚数据分布情况,把所有的Count列值求和,正好是1000.

当然用 echo stats slabs  | nc 127.0.0.1 11211 |grep used_chunks命令也可以,片段如下

1
2
3
4
5
6
7
8
9
10
11
12
13
[hadoop@hadoop1 scripts]$ echo stats slabs  | nc 127.0.0.1 11211 |grep used_chunks
STAT 1:used_chunks 10
STAT 2:used_chunks 26
STAT 3:used_chunks 30
STAT 4:used_chunks 37
STAT 5:used_chunks 47
STAT 6:used_chunks 50
STAT 7:used_chunks 72
STAT 8:used_chunks 93
STAT 9:used_chunks 91
STAT 10:used_chunks 142
STAT 11:used_chunks 174
STAT 12:used_chunks 228

 ./memcached-tool localhost:11211 stats 与  echo stats   | nc 127.0.0.1 11211 |sort命令类似

wKiom1ewUhnjTo0AAADmXOX0Slw465.png

每个指标的含义,网上资料有很多了,而且通过名称也能猜出个所以然了。


4.验证一些边界数据

1. 如果key超过250,报错信息

java.lang.IllegalArgumentException: Key is too long (maxlen = 250)

2. 可以往memcached存储该对象。new byte[100*1024*1024]。明显超过1M了,搞不太清楚。




本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1837779,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何为正在运行的ABAP程序创建内存镜像memory snapshot
如何为正在运行的ABAP程序创建内存镜像memory snapshot
40 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
10019 0
Java内存溢出OutOfMemoryError的产生与排查
在java的虚拟机异常中,有两个异常是大家比较关心的,一个是StackOverflowError,另一个是OutOfMemoryError。今天我们就来看看OutOfMemoryError是怎么产生的,以及如何去排查这个异常。
406 0
通俗易懂,C#如何安全、高效地玩转任何种类的内存之Memory<T>(三)
通俗易懂,C#如何安全、高效地玩转任何种类的内存之Memory<T>
2511 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
25240 0
IOS 内存警告 Memory warning level
内存警告   我们都知道在移动设备上很多资源都是比较紧缺的,尤其时内存,通常都比较小,iPhone4也才只有512MB。而且IOS4.0以后还支持了多任务,这个问题就更加突出了。因此我们在平时设计程序的时候要注意管理好内存,减少不必要的开销,谨防泄露。
849 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
18999 0
(总结)关于Linux的缓存内存 Cache Memory详解
PS:前天有童鞋问我,为啥我的Linux系统没运行多少程序,显示的可用内存这么少?其实Linux与Win的内存管理不同,会尽量缓存内存以提高读写性能,通常叫做Cache Memory。 有时候你会发现没有什么程序在运行,但是使用top或free命令看到可用内存free项会很少,此时查看系统的 /...
1197 0
1.cocos2dx内存管理和CCArray,CCMenuItem
1 C++内存管理 A 栈上的空间 自生自灭,不用管理 B 堆上的空间 手动new,手动delete,否则产生内存泄漏 2 内存管理的难处 管理原则,谁申请谁释放 3 内存的智
1136 0
13692
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载