高性能的分布式内存对象缓存系统--Memcached详解
Posted 嗨码歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高性能的分布式内存对象缓存系统--Memcached详解相关的知识,希望对你有一定的参考价值。
15
Memcached 是什么?
Memcached能够做什么?
为什么需要Memcached?
学习新知识,亘古不变的三原则。
1.Memcached简单概述
2、Memcached的操作
3、Memcached的注意事项
纯享文字版
一、Memcached 是什么?
l Memcached 是一个基于内存的 key-value非关系型数据库
1、通过 Key 存值
2、通过 Key 取值
l Memcached是一个能够通过 API 访问的共享服务
二、Memcached做什么?
l 缓存
1、数据存储:提高查询性能,缓解数据库压力;
2、用户认证token和 session 存储,分布式情况下可以将用户认证的 token 和 session 存入 Memcached 中达到共用;
3、API 调用和结果计算:比如在电商网站中的秒杀和抢购这种高并发情况下,可以讲商品的库存写入 Memcached, 然后调用 Memcached 的 decr 命令进行减法运算,decr 是原子操作,因此线程安全。
三、为什么需要 Memcached
提高系统性能:Memcached 是内存数据库,性能非常高
l 降低应用成本:Memcached 是免费开源的,而且构建非常简单
四、Memcached客户端操作
1、客户端
l Java客户端
1. Memcached Client for Java
2. Spymemcached
3. XMemcached
l Python客户端
1. pymemcache
2. python-memcached
2、使用方式
l 读取数据
先判断Memcached是否存在value
a) 存在:直接获取使用
b) 不存在:先从数据库中获取,然后再写入Memcached
l 写入数据
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))
# key、value 为字符串,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的值或其他属性不会被其他的进程修改的。同理,在并发环境下,当前线程也可能会修改其他进程set的Item。
怎样解决?
第一步:通过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 的数据会丢失:
l 数据过期
l 服务器内存满了
l Memcached 服务器宕机
Memcached 内部基于LRU(最近最少使用)的淘汰算法自动将数据进行删除,当 Memcached 服务器内存满了,就会调用 LRU 将旧数据删除,然后插入新数据。
解决方案:
l 采用 Memcached 集群
集群需要注意:集群里面的 Memcached 的实例是互相独立,不能互通。集群方案有很多:比如可以采用第三方集群代理 magent 进行数据的分发,或者自己编写一个分发的策略等。
编写脚本监控,Memached 实例是否稳定,比如内存是否满了,服务器是否宕机等。
l 将数据持久化到磁盘(比如数据库),我们要知道 Memcached 是内存数据库,当服务器宕机是会导致数据丢失的,因此不能将 Memcached 作为数据存储的终端,而要做好备份
l 不要将修改过于频繁的数据存储在 Memcached 中,如果将频繁修改的数据存入Memecached,那么就失去了缓存的意义。
以上是关于高性能的分布式内存对象缓存系统--Memcached详解的主要内容,如果未能解决你的问题,请参考以下文章