通过上节《memcached演练(1) 搭建memcached服务》,已经成功在linux虚拟机上安装了memcached服务,并设置了自启动。
1
2
|
STAT version 1.4.29
Mem: 1891
|
主要内容
-
使用telnet命令行工具,操作memcached服务
-
使用java spymemcached工具访问memcached服务
-
监控插入不同数据量的数据,响应时间
-
监控memcached主机繁忙&清闲对比情况
-
调整memcached的内存指标,插入相同的数据量的数据,什么情况下性能最高
1.使用telnet命令行工具,操作memcached服务
1.1 验证set&add添加命令
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
|
[hadoop@hadoop1 ~]$
ps
-ef |
grep
memcached
nobody 2047 1 1 07:27 ? 00:08:59
/usr/local/memcached/bin/memcached
-d -p 11211 -u nobody -m 64 -c 1024 -P
/var/run/memcached/memcached
.pid
hadoop 9037 6485 0 16:59 pts
/0
00:00:00
grep
memcached
#连接
[hadoop@hadoop1 ~]$ telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is
'^]'
.
#获取key1的值
get key1
VALUE key1 0 4
abcd
END
#调用set命令,为一个已存在的key赋值成功
set
key1 0 0 4
1234
STORED
get key1
VALUE key1 0 4
1234
END
#调用set命令,为一个已存在的key赋值失败
add key1 0 0 4
abcd
NOT_STORED
get key1
VALUE key1 0 4
1234
END
|
结论:add和set命令虽然都可以添加数据,但两者使用上存在区别,set可以为已存在的key赋值,而add命令不可以。
1.2 验证get&gets获取命令
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
#获取1个键值
get key1
VALUE key1 0 4
1234
END
#获取1个键值
get key2
VALUE key2 0 4
word
END
#同时获取2个键值
get key1 key2
VALUE key1 0 4
1234
VALUE key2 0 4
word
END
---------------------------------------------
gets key1
VALUE key1 0 4 7695009
1234
END
gets key2
VALUE key2 0 4 7695010
word
END
gets key1 key2
VALUE key1 0 4 7695009
1234
VALUE key2 0 4 7695010
word
END
#gets命令返回比get命令,多了1个"不知名数字"
#修改key1的值
set
key1 0 0 5
world
STORED
#确认变化
get key1
VALUE key1 0 5
world
END
#不知名数字从7695009变为7695011
gets key1
VALUE key1 0 5 7695011
world
END
#key2值没有变化,所以不知名数字也没有变
gets key2
VALUE key2 0 4 7695010
word
END
#再次修改key1的值
set
key1 0 0 3
old
STORED
#用增加了1
gets key1
VALUE key1 0 3 7695012
old
END
|
结论gets命令比get命令,多返回的数字,类似数据库中的“变更版本号似的”,而且这个版本号是在各键值之间共享。
1.3测试下incr &decr命令
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
49
50
51
|
#某key不存在情况
incr
seq
1
NOT_FOUND
set
seq
0 0 1
1
STORED
get
seq
1
VALUE
seq
0 1
1
END
incr
seq
1
2
...
get
seq
VALUE
seq
0 1
4
END
gets
seq
VALUE
seq
0 1 7695016
4
END
incr
seq
1
5
#调用incr 命令,增加变更版本号
gets
seq
VALUE
seq
0 1 7695017
5
END
incr
seq
10
15
decr
seq
1
14
#不允许为负数
decr
seq
-1
CLIENT_ERROR invalid numeric delta argument
decr
seq
10
4
#最小值为0
decr
seq
10
0
#有最大值限制
decr
seq
10000000000000000000000
CLIENT_ERROR invalid numeric delta argument
set
seq2 0 0 1
a
STORED
#如果键值非数字,会报错
incr seq2 1
CLIENT_ERROR cannot increment or decrement non-numeric value
|
通过实验验证:incr&decr命令,影响key的长度;最小值为0;增量可变化;必须作用在数字上;命令参数不允许为负数值。
1.4更新命令 append&preppend&replace
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
49
|
set
updkey 0 0 5
world
STORED
get updkey
VALUE updkey 0 5
world
END
#在后面添加字符
append updkey 0 0 5
hello
STORED
get updkey
VALUE updkey 0 10
worldhello
#在前面添加字符
prepend updkey 0 0 10
1234567890
STORED
gets updkey
VALUE updkey 0 20 7695030
1234567890worldhello
END
#更改有效时间为1
prepend updkey 0 1 1
#一段时间后,还存在(说明更新操作不会影响有效时间)
get updkey
VALUE updkey 0 22
1u1234567890worldhello
END
#什么都不添加
prepend updkey 0 0 0
STORED
#虽然没有变更值,但变更版本号也发生了变化
gets updkey
VALUE updkey 0 22 7695037
1u1234567890worldhello
#replace命令
replace updkey 0 10 1
m
STORED
get updkey
VALUE updkey 0 1
m
END
#replace命令变更了有效时间
gets updkey
END
|
结论:prepend 与append命令作用类似,一个在从前面添加字符,一个在后面追加字符。每一次行为,都会影响版本号;不会影响原来的有效时间;replace命令,不仅可以修改数据,而且可以变更有效时间。
还有其他一些指令,就不玩了。
2.使用java spymemcached工具访问memcached服务
2.1 引入依赖
1
2
3
4
5
|
<
dependency
>
<
groupId
>net.spy</
groupId
>
<
artifactId
>spymemcached</
artifactId
>
<
version
>2.11.5</
version
>
</
dependency
>
|
2.2 客户端工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.nap.memcachedexample.service;
import
net.spy.memcached.MemcachedClient;
import
java.io.IOException;
import
java.net.InetSocketAddress;
/**
* Created by Administrator on 2016/8/7.
*/
public
class
MemcachedUtil {
private
static
MemcachedClient cachedClient =
null
;
static
{
try
{
cachedClient =
new
MemcachedClient(
new
InetSocketAddress(
"192.168.163.146"
,
11211
));
}
catch
(IOException e) {
e.printStackTrace();
}
}
public
static
MemcachedClient getSpyMemcachedClient(){
return
cachedClient;
}
}
|
2.2 测试对象
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
Employee.java
package
com.nap;
import
org.apache.commons.lang.builder.ToStringBuilder;
import
java.io.Serializable;
import
java.util.*;
public
class
Employee
implements
Serializable{
private
long
empNo;
private
String name;
private
Date birthDate;
private
int
age;
private
double
salary;
private
List<String> favoriteFoods;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
Date getBirthDate() {
return
birthDate;
}
public
long
getEmpNo() {
return
empNo;
}
public
void
setEmpNo(
long
empNo) {
this
.empNo = empNo;
}
public
void
setBirthDate(Date birthDate) {
this
.birthDate = birthDate;
}
public
int
getAge() {
return
age;
}
public
void
setAge(
int
age) {
this
.age = age;
}
public
double
getSalary() {
return
salary;
}
public
void
setSalary(
double
salary) {
this
.salary = salary;
}
public
List<String> getFavoriteFoods() {
return
favoriteFoods;
}
public
void
setFavoriteFoods(List<String> favoriteFoods) {
this
.favoriteFoods = favoriteFoods;
}
public
String toString(){
return
ToStringBuilder.reflectionToString(
this
);
}
}
--------------------------------------------------------------------------------------
EmployeeFactory.java
package
com.nap;
import
com.nap.memcachedexample.service.MemcachedUtil;
import
net.spy.memcached.MemcachedClient;
import
net.spy.memcached.internal.OperationFuture;
import
org.apache.commons.lang.RandomStringUtils;
import
java.util.ArrayList;
import
java.util.Calendar;
import
java.util.List;
import
java.util.Random;
import
java.util.concurrent.ExecutionException;
public
class
EmployeeFactory {
static
MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient();
public
static
final
String EMPNOSEQ =
"empnoseq"
;
static
{
Object cacheSeq = mcc.get(
"empnoseq"
);
if
(cacheSeq==
null
){
OperationFuture<Boolean> seqFuture = mcc.set(EMPNOSEQ,
900
,
"0"
);
try
{
if
(seqFuture.get()){
System.out.println(
"set status: ok"
);
}
}
catch
(InterruptedException e) {
e.printStackTrace();
}
catch
(ExecutionException e) {
e.printStackTrace();
}
}
}
/**
* 构造测试对象(一个对象大约40B)
* @return
*/
public
static
Employee newEmployee(){
long
empNo = MemcachedUtil.getSpyMemcachedClient().incr(
"empnoseq"
,
1
);
Calendar cal = Calendar.getInstance();
Employee emp =
new
Employee();
emp.setEmpNo(empNo);
emp.setAge(
new
Random().nextInt(
80
));
emp.setName(RandomStringUtils.randomAlphabetic(
15
));
cal.set(Calendar.MONTH,
new
Random().nextInt(
30
));
cal.set(Calendar.DAY_OF_YEAR,
new
Random().nextInt(
366
));
emp.setBirthDate(cal.getTime());
emp.setSalary(
new
Random().nextFloat());
List<String> foods =
new
ArrayList<String>();
for
(
int
j=
0
;j<
new
Random().nextInt(
10
);j++){
foods.add(
"foods_"
+RandomStringUtils.randomAlphabetic(
10
));
}
emp.setFavoriteFoods(foods);
return
emp;
}
}
|
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
|
package
com.nap;
import
com.nap.memcachedexample.service.MemcachedUtil;
import
junit.framework.TestCase;
import
net.spy.memcached.MemcachedClient;
import
java.util.concurrent.ExecutionException;
public
class
SpyMemcachedClientTest
extends
TestCase
{
//测试set
public
void
testAddBean()
throws
ExecutionException, InterruptedException {
MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient();
Employee emp = EmployeeFactory.newEmployee();
System.out.println(emp);
String key =
"emp_"
+ emp.getEmpNo();
System.out.println(key);
mcc.set(key,
19000
, emp);
// Shutdowns the memcached client
mcc.shutdown();
}
//测试get
public
void
testGetBean()
throws
ExecutionException, InterruptedException {
MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient();
Object o = mcc.get(
"emp_1"
);
System.out.println(o);
// Shutdowns the memcached client
mcc.shutdown();
}
}
|
telnet输出结果
1
2
3
4
5
6
|
get emp_1
VALUE emp_1 1 345
srcom.nap.Employee
favoriteFoodstLjava
/util/List
;LnametLjava
/lang/String
;xpetLjava
/util/Date
;L
?佚U
|
通过结果分析,通过客户端已经成功保存了。
3.监控插入不同数据量的数据,响应时间
存储单位转换器
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
package
com.nap;
public
enum
SizeConverter {
/** 转换任意单位的大小, 返回结果会包含两位小数但不包含单位. */
Arbitrary {
@Override
public
String convert(
float
size) {
while
(size >
1024
) {
size /=
1024
;
}
return
String.format(FORMAT_F, size);
}
},
// -----------------------------------------------------------------------
// 有单位
/** 转换单位为B的大小, 返回结果会包含两位小数以及单位. 如: 1024B->1KB, (1024*1024)B->1MB */
B {
@Override
public
String convert(
float
B) {
return
converter(
0
, B);
}
},
/** 转换单位为B的大小, 返回结果会包含两位小数以及单位. */
KB {
@Override
public
String convert(
float
KB) {
return
converter(
1
, KB);
}
},
/** 转换单位为MB的大小, 返回结果会包含两位小数以及单位. */
MB {
@Override
public
String convert(
float
MB) {
return
converter(
2
, MB);
}
},
/** 转换单位为GB的大小, 返回结果会包含两位小数以及单位. */
GB {
@Override
public
String convert(
float
GB) {
return
converter(
3
, GB);
}
},
/** 转换单位为TB的大小, 返回结果会包含两位小数以及单位. */
TB {
@Override
public
String convert(
float
TB) {
return
converter(
4
, TB);
}
},
// -----------------------------------------------------------------------
// trim没单位
/** 转换任意单位的大小, 返回结果小数部分为0时将去除两位小数, 不包含单位. */
ArbitraryTrim {
@Override
public
String convert(
float
size) {
while
(size >
1024
) {
size /=
1024
;
}
int
sizeInt = (
int
) size;
boolean
isfloat = size - sizeInt >
0
.0F;
if
(isfloat) {
return
String.format(FORMAT_F, size);
}
return
String.format(FORMAT_D, sizeInt);
}
},
// -----------------------------------------------------------------------
// trim有单位
/** 转换单位为B的大小, 返回结果小数部分为0时将去除两位小数, 会包含单位. */
BTrim {
@Override
public
String convert(
float
B) {
return
trimConverter(
0
, B);
}
},
/** 转换单位为KB的大小, 返回结果小数部分为0时将去除两位小数, 会包含单位. */
KBTrim {
@Override
public
String convert(
float
KB) {
return
trimConverter(
1
, KB);
}
},
/** 转换单位为MB的大小, 返回结果小数部分为0时将去除两位小数, 会包含单位. */
MBTrim {
@Override
public
String convert(
float
MB) {
return
trimConverter(
2
, MB);
}
},
/** 转换单位为GB的大小, 返回结果小数部分为0时将去除两位小数, 会包含单位. */
GBTrim {
@Override
public
String convert(
float
GB) {
return
trimConverter(
3
, GB);
}
},
/** 转换单位为TB的大小, 返回结果小数部分为0时将去除两位小数, 会包含单位. */
TBTrim {
@Override
public
String convert(
float
TB) {
return
trimConverter(
4
, TB);
}
};
/***
* <p> 将指定的大小转换到1024范围内的大小. 注意该方法的最大单位为PB, 最小单位为B,
* 任何超出该范围的单位最终会显示为**. </p>
*
* @param size 要转换的大小, 注意是浮点数, 不要以整形的方式传入, 容易造成溢出.
* (如: 1024*1024*1024*1024*1024会溢出, 使结果为0, 因为它先将结果以int相乘后再转换为float;
* 而1024.0F*1024.0F*1024.0F*1024.0F*1024.0F就不会溢出)
* @return
*/
abstract
public
String convert(
float
size);
// -----------------------------------------------------------------------
// 单位转换
private
static
final
String[] UNITS =
new
String[] {
"B"
,
"KB"
,
"MB"
,
"GB"
,
"TB"
,
"PB"
,
"**"
};
private
static
final
int
LAST_IDX = UNITS.length-
1
;
private
static
final
String FORMAT_F =
"%1$-1.2f"
;
private
static
final
String FORMAT_F_UNIT =
"%1$-1.2f%2$s"
;
private
static
final
String FORMAT_D =
"%1$-1d"
;
private
static
final
String FORMAT_D_UNIT =
"%1$-1d%2$s"
;
// -----------------------------------------------------------------------
private
static
String converter(
int
unit,
float
size) {
int
unitIdx = unit;
while
(size >
1024
) {
unitIdx++;
size /=
1024
;
}
int
idx = unitIdx < LAST_IDX ? unitIdx : LAST_IDX;
return
String.format(FORMAT_F_UNIT, size, UNITS[idx]);
}
private
static
String trimConverter(
int
unit,
float
size) {
int
unitIdx = unit;
while
(size >
1024
) {
unitIdx++;
size /=
1024
;
}
int
sizeInt = (
int
) size;
boolean
isfloat = size - sizeInt >
0
.0F;
int
idx = unitIdx < LAST_IDX ? unitIdx : LAST_IDX;
if
(isfloat) {
return
String.format(FORMAT_F_UNIT, size, UNITS[idx]);
}
return
String.format(FORMAT_D_UNIT, sizeInt, UNITS[idx]);
}
// -----------------------------------------------------------------------
public
static
String convertBytes(
float
B,
boolean
trim) {
return
trim ? trimConvert(
0
, B,
true
) : convert(
0
, B,
true
);
}
public
static
String convertKB(
float
KB,
boolean
trim) {
return
trim ? trimConvert(
1
, KB,
true
) : convert(
1
, KB,
true
);
}
public
static
String convertMB(
float
MB,
boolean
trim) {
return
trim ? trimConvert(
2
, MB,
true
) : convert(
2
, MB,
true
);
}
/***
* <p> 存储大小单位间的转换. 注意该方法的最大单位为PB, 最小单位为B,
* 任何超出该范围的单位最终会显示为**. </p>
*
* @param unit 从哪个单位开始
* @param size 存储大小, 注意是float, 不要以整形的形式传入, 否则会溢出(如:1024*1024这种,
* 它是先将1024*1024作为int相乘再转换为float的, 如果值过大的话就会溢出了,
* 所以这么写1024.0F*1024.0F)
* @param withUnit 返回的结果字符串是否带有对应的单位
* @return
*/
private
static
String convert(
int
unit,
float
size,
boolean
withUnit) {
int
unitIdx = unit;
while
(size >
1024
) {
unitIdx++;
size /=
1024
;
}
if
(withUnit) {
int
idx = unitIdx < LAST_IDX ? unitIdx : LAST_IDX;
return
String.format(FORMAT_F_UNIT, size, UNITS[idx]);
}
return
String.format(FORMAT_F, size);
}
/***
* <p> 存储大小单位间的转换, 如果转换后小数部分为0, 则去除小数部分.
* 注意该方法的最大单位为PB, 最小单位为B, 任何超出该范围的单位最终会显示为**. </p>
*
* @param unit 从哪个单位开始
* @param size 存储大小, 注意是float, 不要以整形的形式传入, 否则会溢出(如:1024*1024这种,
* 它是先将1024*1024作为int相乘再转换为float的, 如果值过大的话就会溢出了,
* 所以这么写1024.0F*1024.0F)
* @param withUnit 返回的结果字符串是否带有对应的单位
* @return
*/
private
static
String trimConvert(
int
unit,
float
size,
boolean
withUnit) {
int
unitIdx = unit;
while
(size >
1024
) {
unitIdx++;
size /=
1024
;
}
int
sizeInt = (
int
) size;
boolean
isfloat = size - sizeInt >
0
.0F;
if
(withUnit) {
int
idx = unitIdx < LAST_IDX ? unitIdx : LAST_IDX;
if
(isfloat) {
return
String.format(FORMAT_F_UNIT, size, UNITS[idx]);
}
return
String.format(FORMAT_D_UNIT, sizeInt, UNITS[idx]);
}
if
(isfloat) {
return
String.format(FORMAT_F, size);
}
return
String.format(FORMAT_D, sizeInt);
}
public
static
void
main(String[] args) {
System.out.println(SizeConverter.BTrim.convert(1029000f));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class SpyMemcachedClientTest extends TestCase{
//
逻辑非常简单,仅仅批量插入数量数据,经过估算一个Employee 对象,一般为40B。
public void testBatchAddBean() throws ExecutionException, InterruptedException {
MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient();
long startTime=System.currentTimeMillis();
int size=10000000;
for
(int i=0;i<size;i++){
Employee emp = EmployeeFactory.newEmployee();
System.out.println(emp);
mcc.
set
(
"emp_"
+ emp.getEmpNo(), 19000, emp);
}
long endTime=System.currentTimeMillis();
System.out.println(
"保存对象"
+size+
"数据大小"
+SizeConverter.BTrim.convert(size*40.0f)+
";共耗时:"
+(endTime-startTime));
//
Shutdowns the memcached client
mcc.
shutdown
();
}
}
|
结论(memcached服务内存参数为64m,每次测试前最好执行下flush,降低换入换出影响)
数据量 |
数据大小 |
耗时(ms) |
1000 |
39.06KB | 1191 |
10000 | 390.63KB | 3155 |
20000 | 781.25KB |
5142 |
30000 |
1.14MB | 7057 |
40000 |
1.53MB |
8611 |
50000 | 1.91MB | 10611 |
100000 |
3.81MB | 19594 |
500000 | 19.07MB |
89549 |
通过分析得知,当数据量为10000-20000左右时,单位时间保存的数据最多。
(0.32 kb/ms,降至0.26kb/s)
4.监控memcached主机繁忙&清闲对比情况
由于仅仅考虑写入情况,暂时不需要考虑命中率其他情况。主要记录以下指标
(暂时不考虑内存使用情况,IO等待)
4.1CPU利用率
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
|
[root@hadoop1 ~]
# sar -u 2 100
Linux 2.6.32-358.el6.i686 (hadoop1) 08
/07/2016
_i686_ (1 CPU)
07:06:47 PM CPU %user %
nice
%system %iowait %steal %idle
07:06:49 PM all 0.50 0.00 0.50 0.00 0.00 98.99
07:06:51 PM all 0.00 0.00 0.51 0.00 0.00 99.49
07:06:53 PM all 0.00 0.00 0.50 0.00 0.00 99.50
07:06:55 PM all 0.00 0.00 0.50 0.50 0.00 99.00
---------------start-------------------------------
07:06:57 PM all 0.00 0.00 5.18 0.00 0.00 94.82
07:06:59 PM all 0.58 0.00 41.62 0.00 0.00 57.80
07:07:01 PM all 0.00 0.00 61.69 0.00 0.00 38.31
07:07:03 PM all 0.65 0.00 65.36 0.00 0.00 33.99
07:07:05 PM all 0.62 0.00 70.19 0.00 0.00 29.19
07:07:07 PM all 1.23 0.00 69.14 0.00 0.00 29.63
07:07:09 PM all 0.00 0.00 70.55 0.00 0.00 29.45
07:07:11 PM all 0.00 0.00 70.19 0.00 0.00 29.81
07:07:13 PM all 0.00 0.00 70.81 0.00 0.00 29.19
07:07:15 PM all 0.00 0.00 70.89 0.00 0.00 29.11
07:07:17 PM all 0.00 0.00 71.52 0.00 0.00 28.48
07:07:19 PM all 0.00 0.00 71.60 0.00 0.00 28.40
07:07:21 PM all 1.27 0.00 69.43 0.00 0.00 29.30
07:07:23 PM all 0.00 0.00 70.13 0.00 0.00 29.87
07:07:25 PM all 0.66 0.00 69.74 0.00 0.00 29.61
07:07:27 PM all 0.00 0.00 71.34 0.00 0.00 28.66
07:07:29 PM all 1.85 0.00 69.75 0.00 0.00 28.40
07:07:31 PM all 0.00 0.00 70.81 0.00 0.00 29.19
07:07:33 PM all 0.00 0.00 70.89 0.00 0.00 29.11
07:07:35 PM all 0.00 0.00 41.48 0.00 0.00 58.52
-------------------end-----------------------------------------
07:07:37 PM all 0.00 0.00 0.50 0.00 0.00 99.50
07:07:39 PM all 0.00 0.00 0.50 0.00 0.00 99.50
|
在核心级别(kernel)运行所使用 CPU 总时间的百分比突然提升了40%-70%。
相对来说,用户级别的CPU 总时间百分比变化不大。这一点有点出乎意料。
输出项说明:
CPU | all 表示统计信息为所有 CPU 的平均值。 |
%user | 显示在用户级别(application)运行使用 CPU 总时间的百分比。 |
%nice | 显示在用户级别,用于nice操作,所占用 CPU 总时间的百分比。 |
%system | 在核心级别(kernel)运行所使用 CPU 总时间的百分比。 |
%iowait | 显示用于等待I/O操作占用 CPU 总时间的百分比。 |
%steal | 管理程序(hypervisor)为另一个虚拟进程提供服务而等待虚拟 CPU 的百分比。 |
%idle | 显示 CPU 空闲时间占用 CPU 总时间的百分比。 |
4.2换页情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
sar -B
06:59:29 PM pgpgin
/s
pgpgout
/s
fault
/s
majflt
/s
pgfree
/s
pgscank
/s
pgscand
/s
pgsteal
/s
%vmeff
06:59:35 PM 0.00 0.00 15.50 0.00 53.00 0.00 0.00 0.00 0.00
06:59:37 PM 0.00 0.00 15.58 0.00 53.27 0.00 0.00 0.00 0.00
06:59:39 PM 0.00 0.00 15.58 0.00 53.27 0.00 0.00 0.00 0.00
-----start-----------
06:59:41 PM 0.00 0.00 16.76 0.00 61.62 0.00 0.00 0.00 0.00
06:59:43 PM 0.00 0.00 123.78 0.00 111.59 0.00 0.00 0.00 0.00
06:59:45 PM 0.00 0.00 20.25 0.00 92.64 0.00 0.00 0.00 0.00
06:59:47 PM 0.00 22.78 20.89 0.00 94.30 0.00 0.00 0.00 0.00
06:59:49 PM 0.00 0.00 24.84 0.00 105.73 0.00 0.00 0.00 0.00
06:59:51 PM 0.00 0.00 19.02 0.00 92.02 0.00 0.00 0.00 0.00
06:59:53 PM 0.00 0.00 19.50 0.00 93.08 0.00 0.00 0.00 0.00
06:59:55 PM 0.00 0.00 19.38 0.00 95.00 0.00 0.00 0.00 0.00
06:59:57 PM 0.00 0.00 128.12 0.00 123.75 0.00 0.00 0.00 0.00
|
由于缺少必要的查询操作,换页监控,感觉意义不大。
输出项说明:
pgpgin/s | 每秒钟从磁盘读入的系统页面的 KB 总数 |
pgpgout/s | 每秒钟向磁盘写出的系统页面的 KB 总数 |
fault/s | 系统每秒产生的页面失效(major + minor)数量 |
majflt/s | 系统每秒产生的页面失效(major)数量 |
4.3上下文切换次数(提高了2个数量级)
1
2
3
4
5
6
7
8
9
10
11
|
[root@hadoop1 ~]
# sar -w 2 100
Linux 2.6.32-358.el6.i686 (hadoop1) 08
/07/2016
_i686_ (1 CPU)
06:57:10 PM proc
/s
cswch
/s
06:57:12 PM 0.00 14627.04
06:57:14 PM 0.00 14884.81
06:57:16 PM 0.62 14411.11
06:57:18 PM 0.00 1530.41
06:57:20 PM 0.00 118.00
06:57:22 PM 0.00 121.61
06:57:24 PM 0.00 118.09
|
4.4队列的长度
1
2
3
4
5
6
7
8
9
|
sar -q
06:10:01 PM runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15
06:20:01 PM 0 230 0.00 0.00 0.00
06:30:01 PM 0 230 0.00 0.00 0.00
06:40:01 PM 0 230 0.00 0.00 0.00
06:50:01 PM 0 230 0.00 0.00 0.00
07:00:01 PM 0 232 0.00 0.00 0.00
07:10:01 PM 0 230 0.00 0.00 0.00
Average: 0 228 0.00 0.00 0.00
|
基本上没什么变化,可以说明瓶颈不再CPU上。
输出项说明:
runq-sz | 运行队列的长度(等待运行的进程数) |
plist-sz | 进程列表中进程(processes)和线程(threads)的数量 |
ldavg-1 | 最后1分钟的系统平均负载(System load average) |
ldavg-5 | 过去5分钟的系统平均负载 |
ldavg-15 | 过去15分钟的系统平均负载 |
5.调整memcached的内存指标,测试性能
数据量 |
数据量大小 |
64m 响应时间 (ms) |
128m 响应时间 (ms) |
512m响应时间 |
1000 | 39.06KB | 1191 |
761 |
753 |
10000 |
390.63KB | 3155 | 3116 | 3168 |
20000 |
781.25KB | 5142 |
4965 | 4978 |
30000 |
1.14MB |
7057 | 6893 | 6829 |
40000 |
1.53MB | 8611 |
8629 | 8725 |
50000 |
1.91MB | 10611 | 10660 |
10334 |
100000 | 3.81MB | 19594 |
19984 | 19760 |
结论:发现一个奇怪问题。数据量到了40000时,内存大的反而效率低(多次测试,结果不太稳定,这种情况经常发生)。
个人真有点摸不着头脑了,有清楚麻烦告知下。
我分别对比了换入换出指标,CPU利用率情况等,均没有发现能引起注意的地方。难道是网络问题?
本文由于缺少查询操作,所以未考虑命中率,在以后调优演练时补上。
---------------------------
The End
memcached 正常使用了。接下来,借助memcached实现tomcat集群效果
本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1835429,如需转载请自行联系原作者