memcached演练(2) 访问memcached服务

通过上节《memcached演练(1) 搭建memcached服务》,已经成功在linux虚拟机上安装了memcached服务,并设置了自启动。

STAT version 1.4.29
Mem:          1891

主要内容

  • 使用telnet命令行工具,操作memcached服务
  • 使用java spymemcached工具访问memcached服务
  • 监控插入不同数据量的数据,响应时间
  • 监控memcached主机繁忙&清闲对比情况
  • 调整memcached的内存指标,插入相同的数据量的数据,什么情况下性能最高

1.使用telnet命令行工具,操作memcached服务

1.1 验证set&add添加命令

[[email protected] ~]$ 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
#连接
[[email protected] ~]$ 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个键值
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命令

#某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

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 引入依赖

<dependency>
    <groupId>net.spy</groupId>
    <artifactId>spymemcached</artifactId>
    <version>2.11.5</version>
</dependency>

2.2 客户端工具类

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 测试对象

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;
    }
}
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输出结果

get emp_1
VALUE emp_1 1 345
srcom.nap.Employee
favoriteFoodstLjava/util/List;LnametLjava/lang/String;xpetLjava/util/Date;L

                                                        ?佚U

通过结果分析,通过客户端已经成功保存了。

3.监控插入不同数据量的数据,响应时间

存储单位转换器

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));
    }
}
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利用率

[[email protected] ~]# 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换页情况

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个数量级)

[[email protected] ~]# 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队列的长度

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集群效果

时间: 2024-08-23 23:11:12

memcached演练(2) 访问memcached服务的相关文章

memcached演练(1) 搭建memcached服务

memcached已经火了好多年了,现在网上关于memcached的资源相当多了,我就不浪费话语了.干脆写一个实战系列,坚持一切用实施说话. 环境介绍 Linux虚拟机 内核信息 [[email protected] ~]# uname -aLinux hadoop1 2.6.32-358.el6.i686 内存:1G 安装过程 1.准备编译环境,安装必须的gcc,make工具,如果没有安装yum,最好安装下.网上有很多共享的yum源. 2.下载最新版本的libevent # wget http

memcached演练(3) 使用memcached搭建tomcat集群

上篇文章,已经明确了tomcat集群的必要性,主要从高可用和高并发量考虑.一般使用tomcat集群搭建,都要使用前置设一个nginx或apache作个反向代理,将请求转发给后端tomcat.使用tomcat集群,必然会引来session数据共享问题.如何解决这个问题?可借助memcached实现. 主要内容 测试单台tomcat的吞吐率 搭建apache+mod_jk+2个tomcat集群环境 搭建apache+mod_jk+2个tomcat+memcached集群环境 对比2个环境的吞吐率情况

个人memcached演练内容聚集(共11)

memcached演练(1) 搭建memcached服务 memcached演练(2) 访问memcached服务 单台tomcat的session信息的2种持久化方式 memcached演练(3) 使用apache+搭建双节点tomcat集群 memcached演练(4) 使用apache+memcached-session-manager+tomcat集群 memcached演练(4) 使用apache+memcached-session-manager+tomcat集群(续) memcac

memcached演练(6) 高可用实例HA(伪集群方案 )

本系列文章<memcached的演练>,这是第6篇,前面文章,已经阐述了,memcached的安装,访问,session管理,存储管理.从本篇开始,就分开有几篇演练下memcached的高可用相关. memcached的安全,承载着后台数据库的巨大访问,意义重大. 简单介绍下HA的梗概,如果时间允许尽量都演练下个方案,然后横向比较下各方案的优缺点. 本篇主要内容 伪集群方案的测试 明确memcached的高可用方案 通过比较memcached和redis两种NOSQL的方案,很容易发现,mem

Memcached 未授权访问漏洞及加固

memcached是一套分布式的高速缓存系统.它以Key-Value(键值对)形式将数据存储在内存中,这些数据通常是应用读取频繁的.正因为内存中数据的读取远远大于硬盘,因此可以用来加速应用的访问. 漏洞成因: 由于memcached安全设计缺陷,客户端连接memcached服务器后 无需认证就 可读取.修改服务器缓存内容. 漏洞影响: 除memcached中数据可被直接读取泄漏和恶意修改外,由于memcached中的数据像正常网站用户访问提交变量一样会被后端代码处理,当处理代码存在缺陷时会再次导

memcached基于socket访问memcache缓存服务器

memcached基于socket访问memcache缓存服务器 操作memcache常用三种方法: 1.memcache基于php_memcache.dll扩展(php扩展) 2.memcached基于php_memcached.dll扩展(php扩展) 3.memcached基于socket访问(基于网络) memcached-client.php 调用很简单,调用方法如下: <?php header("content-type:text/html; charset=utf-8&quo

#Memcached系列#(6)使用Enyim.Caching访问Memcached的一个C#控制台程序

这篇文章主要是通过Enyim.Caching来完成访问Memcached. 这篇文章标为"原创",其实,是从多个地方整合过来的内容:但觉得"转载"也不合适,也并不是完全照搬别人的东西. 参考网址(不过,感觉它的配置写的乱糟糟的):http://www.cnblogs.com/luyinghuai/archive/2008/08/28/1278200.html (1)首先下载EnyimMemcached(文件名:EnyimMemcached-master.zip).

Nginx HttpMemcModule和直接访问memcached效率对比测试

测试环境: 测试客户机A: HP DL380G4,2个双核CPU,4G Ram,2块10k RPM SAS盘做raid 1,ext3 Nginx所在服务器B:DELL R710,E5620 * 2,32G Ram,6块盘15K RPM SAS盘做raid 1+0,xfs Memcached所在服务器C:DELL R710,E5620 * 2,32G Ram,6块盘15K RPM SAS盘做raid 5,ext4 Nginx设置:keepalive 8192 Php fpm设置:listen.ba

memcached完全剖析–1. memcached的基础

系列文章导航: memcached完全剖析–1. memcached的基础 memcached全面剖析–2. 理解memcached的内存存储 memcached全面剖析–3. memcached的删除机制和发展方向 memcached全面剖析–4. memcached的分布式算法 memcached全面剖析–5. memcached的应用和兼容程序 翻译一篇技术评论社的文章,是讲memcached的连载.fcicq同学说这个东西很有用,希望大家喜欢. 发表日:2008/7/2 作者:长野雅广(