高性能的分布式内存对象缓存系统--Memcached详解

Posted 嗨码歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高性能的分布式内存对象缓存系统--Memcached详解相关的知识,希望对你有一定的参考价值。

高性能的分布式内存对象缓存系统--Memcached详解

15

Memcached 是什么? 

Memcached能够做什么?

为什么需要Memcached?

学习新知识,亘古不变的三原则。

     1.Memcached简单概述

高性能的分布式内存对象缓存系统--Memcached详解

                2、Memcached的操作高性能的分布式内存对象缓存系统--Memcached详解

            3、Memcached的注意事项高性能的分布式内存对象缓存系统--Memcached详解


    纯享文字版

一、Memcached 是什么?

Memcached 是一个基于内存的 key-value非关系型数据库

1、通过 Key 存值

2、通过 Key 取值

Memcached是一个能够通过 API 访问的共享服务

二、Memcached做什么?

缓存

1数据存储:提高查询性能,缓解数据库压力;

2用户认证token和 session 存储,分布式情况下可以将用户认证的 token 和 session 存入 Memcached 中达到共用;

3API 调用和结果计算:比如在电商网站中的秒杀和抢购这种高并发情况下,可以讲商品的库存写入 Memcached, 然后调用 Memcached 的 decr 命令进行减法运算,decr 是原子操作,因此线程安全。


三、为什么需要 Memcached

提高系统性能:Memcached 是内存数据库,性能非常高

降低应用成本Memcached 是免费开源的,而且构建非常简单

四、Memcached客户端操作

1、客户端

Java客户端

1. Memcached Client for Java

2. Spymemcached

3. XMemcached

 Python客户端

1. pymemcache

2. python-memcached

2、使用方式

读取数据

先判断Memcached是否存在value

a) 存在:直接获取使用

b) 不存在:先从数据库中获取,然后再写入Memcached

写入数据

1. 更新数据:高并发情况下,使用 CAS 进行更新

2. 添加数据:可以采用任务队列,从后台写入

3、Xmemcached 操作

a) Maven导入依赖包:

 

<dependency>
    <
groupId>com.googlecode.xmemcachedgroupId>
    <
artifactId>xmemcachedartifactId>
    <
version>2.4.5version>
dependency>


b) API 介绍

public static void main(String[] args) throws Exception {
    XMemcachedClient client =
            
new XMemcachedClient("192.168.2.110"11211);

    
// 设置 key-value, set(key, expireTime-单位秒, value, timeout-单位毫秒)
    // key存在就会覆盖
    boolean isSuccess = client.set("key"3600"value"1000);

    
// key存在会返回 false
    isSuccess = client.add("key"3600"value"1000);

    
// key存在会覆盖,不存在false
    isSuccess = client.replace("key"3600"value"1000);

    
// 获取值,超时时间1
    String value = client.get("key"1000);

    
// 删除值
    boolean isDeleted = client.delete("key");

}

4、pymemcache客户端

a) 安装模块pip install pymemcache

b) API 介绍

from pymemcache.client.base import Client
c = Client(
server=('192.168.2.110', 11211))

# keyvalue 为字符串,expire单位秒,
# noreply: True直接返回提高性能,默认情况下改属性在“set”, “add”, “replace”, “append”,
# “prepend”, “delete”操作时是开启的,“cas”, “incr”, “decr”操作时关闭的
is_success = c.set(key="key", value="value", expire=3600, noreply=True)

is_success = c.add(
key="key", value="value", expire=3600)

is_success = c.replace(
key="key", value="value", expire=3600)

is_success = c.delete(
key="key")

5、原子操作

Memcached 对单个命令是原子操作:

如果针对同一个Item发送一个set命令和一个get命令,这两个命令之间是不会有影响的。即使是在多线程环境下,所有的命令也都是原子性的,但是我们要注意单个命令是原子性的,但是命令和命令之间的序列不是原子性的。例如使用get命令获取一个Item,然后通过set命令修改该Item,这个时候Memcached是无法保证该Item的值或其他属性不会被其他的进程修改的。同理,在并发环境下,当前线程也可能会修改其他进程setItem

怎样解决?

         第一步:通过gets命令查询某个Item的话,Memcached会返回一个该Item的当前值的唯一标示。

        第二步:通过cas命令更新的值和唯一标示一起发送到Memcached。如果当前Item的唯一标示和cas提供的唯一标示一样,那么写操作就成功;如果其他线程修改了Item,那么该唯一标示就改变了,那么写操作就失败。

Java 代码:
// 先获取值
GetsResponse response = client.gets("key");
long cas = response.getCas();
// 执行 cas 操作
client.cas("key", 3600, "value", 1000, cas);


Python 代码:

value, cas = c.gets("key")
c.cas(
key="key", value="new_value", cas=cas, timeout=3600, noreply=False)


五、Memcached 注意事项

Memcached的不稳定性可能会导致数据丢失:

 

以下情况,Memcached 的数据会丢失:

数据过期

服务器内存满了

Memcached 服务器宕机

Memcached 内部基于LRU(最近最少使用)的淘汰算法自动将数据进行删除,当 Memcached 服务器内存满了,就会调用 LRU 将旧数据删除,然后插入新数据。

 

解决方案:

采用 Memcached 集群

集群需要注意:集群里面的 Memcached 的实例是互相独立,不能互通。集群方案有很多:比如可以采用第三方集群代理 magent 进行数据的分发,或者自己编写一个分发的策略等。

编写脚本监控,Memached 实例是否稳定,比如内存是否满了,服务器是否宕机等。

将数据持久化到磁盘(比如数据库),我们要知道 Memcached 是内存数据库,当服务器宕机是会导致数据丢失的,因此不能将 Memcached 作为数据存储的终端,而要做好备份

不要将修改过于频繁的数据存储在 Memcached 中,如果将频繁修改的数据存入Memecached,那么就失去了缓存的意义。

以上是关于高性能的分布式内存对象缓存系统--Memcached详解的主要内容,如果未能解决你的问题,请参考以下文章

memcache 搭建缓存服务器

Linux之搭建memcache缓存服务器

走进缓存的世界 - Memcache

Memcache缓存服务器(Nginx+php+Memcache+MySQL)

分布式缓存-Memcache定义

memcache