Linux下安装Memcached和Java应用

Memcache 介绍

Memcache 是一个自由和开放源代码、高性能、分配的内存对象缓存系统。简单来说,Memcache 是一个高性能的分布式内存对象的 key-value 缓存系统,用于加速动态 Web 应用程序,减轻数据库负载,现在也有很多人将它作为内存式数据库在使用。

它可以应对任意多个连接,使用非阻塞的网络 IO,由于它的工作机制是在内存中开辟一块空间,然后建立一个 Hash 表,Memcached 自动管理这些 Hash 表。

Memcache 由国外社区网站 LiveJournal 开发团队开发,设计理念就是小而强大,它简单的设计促进了快速部署、易于开发并解决面对大规模的数据缓存的许多难题,而所开放的 API 使得 Memcache 能用于 Java、C/C++/C#、Perl、Python、PHP、Ruby 等大部分流行的程序语言。

Memcache 和 Memcached 的区别:Memcache 是这个项目的名称,而 Memcached 是服务器端的主程序名称。

Memcache 特点
协议简单

Memcache 的服务端客户端通信使用简单的文本协议,通过 Telnet 即可在 Memcached 上存取数据。

基于 Libevent 的事件处理

Libevent 是一套跨平台的事件处理接口的封装,能够兼容包括这些操作系统:Windows/Linux/BSD/Solaris 等操作系统的的事件处理,包装的接口包括:poll、select(Windows)、epoll(Linux)、kqueue(BSD)/dev/pool(Solaris)。

Memcache 使用 Libevent 来进行网络并发连接的处理,能够保持在很大并发情况下,仍旧能够保持快速的响应能力。

内置内存存储方式

Memcache 中保存的数据都存储在 Memcache 内置的内存存储空间中。由于数据仅存在于内存中,因此重启 Memcache、重启操作系统会导致数据全部丢失。Memcache LRU(Least Recently Used)算法自动删除不使用的缓存,不过这个功能是可以配置的,Memcache 启动时通过“-M”参数可以禁止 LRU。不过,Memcache 本身是为缓存而设计的,建议开启 LRU。

不适应场景

缓存对象不能大于 1 MB
key 的长度大于 250 字符
Memcache 未提供任何安全策略
不支持持久化

linux下安装Memcached
  • 环境
    由于memcached和libevent是由C编写的,所以首先确保你的系统安装了gcc,如果
    没有安装,使用yum安装即可
    命令:
    yum -y install gcc
    yum -y install gcc-c++

  • 手动安装(1)

      然后下载 libevent 
      然后上传centos,进行给予权限,然后解压 
      # tar xzvf libevent-2.0.21-stable.tar.gz ##解压 
      # cd libevent-2.0.21-stable 
      # ./configure --prefix=/usr 
      # make 
      # make install 
      安装完后可以查看下/usr/lib是否有libevent等文件(ls -al /usr/lib | grep libevent) 
      
      然后下载 memcached 
      # tar xzvf memcached-1.4.15.tar.gz 
      # cd memcached-1.4.15 
      # ./configure --with-libevent=/usr 
      # make 
      # make install 
    
  • yum安装方式(2)
    1.查找memcached
    yum search memcached
    2.安装memcached
    yum -y install memcached
    3.验证安装memcached
    memcached -h
    4.修改memcached配置文件
    (1) 加入服务
    chkconfig --level 2345 memcached on
    热后可以使用 service memcached restart/start/stop
    (2)可修改参数
    vi /etc/sysconfig/memcached

memcached命令参数解释:
-p 监听的端口
-l <ip_addr> 连接的IP地址, 默认是本机
-d start 启动memcached 服务
-d restart 重起memcached 服务
-d stop|shutdown 关闭正在运行的memcached 服务
-d install 安装memcached 服务
-d uninstall 卸载memcached 服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助

(3) 查看服务
ps -ef | grep memcached

(4) 或者命令启动
/usr/bin/memcached -b -p 11211 -m 150 -u root >> /tmp/memcached.log &

Idea中boot集成使用memcached

  1. 映入memcachedx jar包

     <dependency>
     	    <groupId>com.googlecode.xmemcached</groupId>
     	    <artifactId>xmemcached</artifactId>
     	    <version>2.4.5</version>
     </dependency>
    

2.添加配置文件:

	# 单个 Memcached 配置,用集群时可以拼接多个地址:"host1:port1 host2:port2 …"。
	memcached.servers=192.168.25.130:11211
	# 连接池
	memcached.poolSize=10
	#操作超时时间
	memcached.opTimeout=6000 

3.创建 XMemcachedProperties 类,读配置信息

@Component
@ConfigurationProperties(prefix = "memcached")
public class XMemcachedProperties {
    private String servers;
    private int poolSize;
    private long opTimeout;
    xxxx
    xxxx
    ....
    }

4.创建memcached操作客户端类

@Configuration
public class MemcachedBuilder {
    protected static Logger logger =  LoggerFactory.getLogger(MemcachedBuilder.class);
    @Resource
    private XMemcachedProperties xMemcachedProperties;

    @Bean
    public  MemcachedClient getMemcachedClient() {
        MemcachedClient memcachedClient = null;
        try {
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(xMemcachedProperties.getServers()));
            // 设置集群权重
            // MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(memcacheConfig.getServers()),new int[]{3,2,1});
            // 开启/关闭failure模式
            builder.setFailureMode(false);
            // 多 Memcached 时启用 一致性哈希 算法
            builder.setSessionLocator(new KetamaMemcachedSessionLocator());
            // 多 Memcached 时启用 选举散列 算法
            // builder.setSessionLocator(new ElectionMemcachedSessionLocator());
            builder.setConnectionPoolSize(xMemcachedProperties.getPoolSize());
            //操作超时时间
            builder.setOpTimeout(xMemcachedProperties.getOpTimeout());
            // 进行数据压缩,大于1KB时进行压缩
            builder.getTranscoder().setCompressionThreshold(1024);
            // 使用序列化传输编码
            builder.setTranscoder(new SerializingTranscoder());
            // use binary protocol
            builder.setCommandFactory(new BinaryCommandFactory());
            memcachedClient = builder.build();
        } catch (IOException e) {
            logger.error("inint MemcachedClient failed ",e);
        }
        return memcachedClient;
    }
}

5.测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class MemcachedTests {

	@Autowired
	private MemcachedClient memcachedClient;

	/**
	 *  set 方法,它有三个参数,
	 *  第一个是存储的 key 名称,
	 *  第二个是 expire 时间(单位秒),超过这个时间,memcached 将这个数据替换出去,0 表示永久存储(默认是一个月),
	 *  第三个参数就是实际存储的数据,可以是任意的 Java 可序列化类型。
	 * @throws Exception
	 */
	@Test
	public void testGetSet() throws Exception {
		memcachedClient.set("hello", 0, "Hello,xmemcached");
		String value = memcachedClient.get("hello");
		System.out.println("hello=" + value);
		memcachedClient.delete("hello");
		value = memcachedClient.get("hello");
		System.out.println("hello=" + value);
	}

	/**
	 * 如果 add 的 key 已经存在,则不会更新数据(过期的 key 会更新),之前的值将仍然保持相同
	 * replace 命令,用于替换已存在的 key(键)的 value(数据值)。如果 key 不存在,则替换失败
	 * append 命令,用于向已存在 key(键)的 value(数据值)后面追加数据。
	 * prepend 命令,用于向已存在 key(键)的 value(数据值)前面追加数据。
	 * deleteWithNoReply 方法,这个方法删除数据并且告诉 Memcached,
	 * 			不用返回应答,因此这个方法不会等待应答直接返回,比较适合于批量处理。
	 * @throws Exception
	 */
	@Test
	public void testMore() throws Exception {
		if (!memcachedClient.set("hello", 0, "world")) {
			System.err.println("set error");
		}
		if (!memcachedClient.add("hello", 0, "dennis")) {
			System.err.println("Add error,key is existed");
		}
		if (!memcachedClient.replace("hello", 0, "dennis")) {
			System.err.println("replace error");
		}
		memcachedClient.append("hello", " good");
		memcachedClient.prepend("hello", "hello ");
		String name = memcachedClient.get("hello", new StringTranscoder());
		System.out.println(name);
		memcachedClient.deleteWithNoReply("hello");
	}

	/**
	 * Incr 和 Decr 类似数据的增和减,两个操作类似 Java 中的原子类如 AtomicIntger
	 * @throws Exception
	 */
	@Test
	public void testIncrDecr() throws Exception {
		memcachedClient.delete("Incr");
		memcachedClient.delete("Decr");
		System.out.println(memcachedClient.incr("Incr", 6, 12));
		System.out.println(memcachedClient.incr("Incr", 3));
		System.out.println(memcachedClient.incr("Incr", 2));
		System.out.println(memcachedClient.decr("Decr", 1, 6));
		System.out.println(memcachedClient.decr("Decr", 2));
	}

	/**
	 * memcachedClient.getCounter("counter",10),第一个参数为计数器的 key,第二参数当 key 不存在时的默认值;
	 * counter.incrementAndGet(),执行一次给计数器加 1;
	 * counter.decrementAndGet(),执行一次给计数器减 1。
	 * @throws Exception
	 */
	@Test
	public void testCounter() throws Exception {
		Counter counter=memcachedClient.getCounter("counter1",10);
		System.out.println("counter="+counter.get());
		long c1 =counter.incrementAndGet();
		System.out.println("counter="+c1);
		long c2 =counter.decrementAndGet();
		System.out.println("counter="+c2);
		long c3 =counter.addAndGet(-6);
		System.out.println("counter="+c3);
	}


	@Test
	public void testTouch() throws Exception {
		memcachedClient.set("Touch", 2, "Touch Value");
		Thread.sleep(1000);
		//memcached 不支持
	//	memcachedClient.touch("Touch",6);
		Thread.sleep(2000);
		String value =memcachedClient.get("Touch",3000);
		System.out.println("Touch=" + value);
	}

	/**
	 * Memcached 是通过 CAS 协议实现原子更新,所谓原子更新就是 Compare and Set
	 * @throws Exception
	 */
	@Test
	public void testCas() throws Exception {
		memcachedClient.set("cas", 0, 100);
		GetsResponse<Integer> result = memcachedClient.gets("cas");
		System.out.println("result value "+result.getValue());

		long cas = result.getCas();
		//尝试将a的值更新为2
		if (!memcachedClient.cas("cas", 0, 200, cas)) {
			System.err.println("cas error");
		}
		System.out.println("cas value "+memcachedClient.get("cas"));

		memcachedClient.cas("cas", 0, new CASOperation<Integer>() {
			public int getMaxTries() {
				return 1;
			}

			public Integer getNewValue(long currentCAS, Integer currentValue) {
				return 300;
			}
		});
		System.out.println("cas value "+memcachedClient.get("cas"));

	}

	@Test
	public void testStat() throws Exception {
		Map<InetSocketAddress,Map<String,String>> result=memcachedClient.getStats();
		System.out.println("Stats=" + result.toString());
		Map<InetSocketAddress,Map<String,String>> items=memcachedClient.getStatsByItem("items");
		System.out.println("items=" + items.toString());
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值