XMemcachedClient 操作 Memcached
Posted 笑虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XMemcachedClient 操作 Memcached相关的知识,希望对你有一定的参考价值。
XMemcachedClient 操作 Memcached
安装
CentOS
docker 安装/运行 memcached
# 查看镜像是否存在
docker search memcached
# 拉取镜像
docker pull memcached
# 运行
docker run -dp 11211:11211 --name memcache memcached
--name
:给容器指定名称 memcache
。如果不加 docker 会自己取。
-p
:本服务器端口11211
–> 容器端口11211
。
-d
:后台运行。
memcached
:这个就是要启动的镜像名
docker ps -a
:查看容器是运行
netstat -anlp | grep 11211
:查看服务端口 11211
是否在监听中。
Windows
去 菜鸟教程 Windows 下安装 Memcached 下载 直接运行即可。
配个 启动-memcached.bat
memcached.exe -p 9527 -l 127.0.0.1 localhost -m 50 -vv
启动参数
-d: 选项是启动一个守护进程,
-m: 是分配给Memcache使用的内存数量,单位是MB,默认64MB
-M: 内存耗尽时返回错误(而不是删除项)
-u: 是运行Memcache的用户,如果当前为root 的话,需要使用此参数指定用户。
-l: 是监听的服务器IP地址,默认为所有网卡。支持多个地址空格分隔,默认 0.0.0.0 允许任何人连接。
-p: 是设置Memcache的TCP监听的端口,最好是1024以上的端口
-c: 选项是最大运行的并发连接数,默认是1024
-P: 是设置保存Memcache的pid文件
-f: chunk 大小的扩容因子 (默认: 1.25)
-vv: 打印客户端的请求和返回信息
操作命令
命令 | 说明 |
---|---|
stats items | 按 slab 细分返回:所储存元素的一些信息。如:个数 |
stats slabs | 获取所有slab 的信息,如 page, chunk 的数量、大小、各操作的命中情况等 |
set 添加数据,如果存在就修改
set key flags exptime bytes [noreply]
value
STORED
key:键。存取都靠它。
flags:一个标识符,存什么返什么。但是客户端可能对其做封装。
exptime:在缓存中保存键值对的时间长度(单位秒,0 永不过期)
bytes:在缓存中存储的字节数 (和 value
大小要一至,否则报错)
noreply(可选): 该参数告知服务器不需要返回数据
value:值。在第二行输入。
set jerry 0 666 3 sssssssssssssssss
abc
STORED # 成功返回提示
get jerry
VALUE jerry 0 3
abc
END
- 多余的
sssssssssssssssss
被忽略,值在第二行输入 。 - 成功显示
STORED
add 新增键值
参数一样,与 set
的区别在于,已经有了就保持不变。
add jerry 0 300 3
123
STORED
add jerry 0 300 3
asd
NOT_STORED
get jerry
VALUE jerry 0 3
123
END
replace
参数一样,替换值,如果键
不存在则失败。
append 在 value 后追加数据
append jerry 0 300 3
789
STORED
get jerry
VALUE jerry 0 6
efg789
END
prepend 在 value 前插入数据
prepend jerry 0 300 3
fff
STORED
get jerry
VALUE jerry 0 9
fffefg789
END
CAS 比较和交换
再比较再更新,提交时需要带上 gets
返回的 unique_cas_token
gets jerry
VALUE jerry 0 5 13587
abcde
END
# 拿到 unique_cas_token = 13587
cas jerry 0 8000 3 13587
123
STORED # 保存成功后输出
# 取值查看
get jerry
VALUE jerry 0 3
123
END
# 再用原来的令牌提交一次
cas jerry 0 8000 3 13587
abe
EXISTS # 在最后一次取值后另外一个用户也在更新该数据。
delete 删除
delete jerry
DELETED
get jerry
END
incr 与 decr 自增自减命令
值
必须是十进制的32位无符号整数
。
如果 key
不存在返回 NOT_FOUND,如果键的值不为数字,则返回 CLIENT_ERROR,其他错误返回 ERROR。
add jerry 0 8000 1
0
STORED
incr jerry 1
1
incr jerry 1
2
incr jerry 1
3
incr jerry 1
4
incr jerry 1
5
get jerry
VALUE jerry 0 1
5
END
decr jerry 3
2
get jerry
VALUE jerry 0 1
2
END
stats
属性 | 说明 |
---|---|
pid | memcache服务器进程ID |
uptime | 服务器已运行秒数 |
time | 服务器当前Unix时间戳 |
version | memcache版本 |
pointer_size | 操作系统指针大小 |
rusage_user | 进程累计用户时间 |
rusage_system | 进程累计系统时间 |
curr_connections | 当前连接数量 |
total_connections | Memcached运行以来连接总数 |
connection_structures | Memcached分配的连接结构数量 |
cmd_get | get命令请求次数 |
cmd_set | set命令请求次数 |
cmd_flush | flush命令请求次数 |
get_hits | get命令命中次数 |
get_misses | get命令未命中次数 |
delete_misses | delete命令未命中次数 |
delete_hits | delete命令命中次数 |
incr_misses | incr命令未命中次数 |
incr_hits | incr命令命中次数 |
decr_misses | decr命令未命中次数 |
decr_hits | decr命令命中次数 |
cas_misses | cas命令未命中次数 |
cas_hits | cas命令命中次数 |
cas_badval | 使用擦拭次数 |
auth_cmds | 认证命令处理的次数 |
auth_errors | 认证失败数目 |
bytes_read | 读取总字节数 |
bytes_written | 发送总字节数 |
limit_maxbytes | 分配的内存总大小(字节) |
accepting_conns | 服务器是否达到过最大连接(0/1) |
listen_disabled_num | 失效的监听数 |
threads | 当前线程数 |
conn_yields | 连接操作主动放弃数目 |
bytes | 当前存储占用的字节数 |
curr_items | 当前存储的数据总数 |
total_items | 启动以来存储的数据总数 |
evictions | LRU释放的对象数目 |
reclaimed | 已过期的数据条目来存储新数据的数目 |
客户端 XMemcachedClient 演示
客户端封装后,最简单的版本 set
只需要输入 key
,value
,过期时间
。
顺便提一句,有 SpringBoot
版的。
- pom.xml
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
</dependency>
- 简单测几个效果
private static String url = "192.168.0.258:11211";
private static MemcachedClient memcachedClient;
public static final InetSocketAddress address = AddrUtil.getOneAddress(url);
static
try
// 当很多额外参数支持自定义配置时使用:建造者模式
memcachedClient = new XMemcachedClientBuilder(AddrUtil.getAddresses(url)).build();
catch (IOException e)
e.printStackTrace();
@Test
public void setTest() throws InterruptedException, MemcachedException, TimeoutException
String key = "jerry"; // 键
int exptime = 300 ; // 过期时间,单位为秒。最长可达30天。在30天之后,被视为一个精确日期的unix时间戳
String value = "耀眼的笨笨"; // 值
long timeout = 60000; // 操作超时,单位毫秒
memcachedClient.set(key, exptime, value, timeout);
@Test
public void getTest() throws InterruptedException, MemcachedException, TimeoutException
String value = memcachedClient.get("jerry");
System.out.println(value); // 耀眼的笨笨
// CAS
@Test
public void casTest() throws InterruptedException, MemcachedException, TimeoutException
GetsResponse<Object> getsResponse = memcachedClient.gets("jerry");
memcachedClient.cas("jerry", 30, "xyz", getsResponse.getCas());
// CAS 自动提交。不必每次手动获取。
@Test
public void CASOperationTest() throws InterruptedException, MemcachedException, TimeoutException
CASOperation<String> casOperation = new CASOperation<String>()
public int getMaxTries() return 3; // 最多尝试 3 次
public String getNewValue(long currentCAS, String currentValue) return "耀眼的笨笨";
;
memcachedClient.add("jerry", 3, "笑虾");
memcachedClient.cas("jerry", 1, casOperation);
System.out.println(""+memcachedClient.get("jerry"));
// CAS 自动提交。不必每次手动获取。10个线程争抢,反而更慢了。
@Test
public void CASOperationTest() throws InterruptedException, MemcachedException, TimeoutException
AtomicInteger l = new AtomicInteger();
CASOperation casOperation = new CASOperation<String>()
public int getMaxTries()
System.out.println(Thread.currentThread().getName() + " 尝试 " + l.incrementAndGet() + " 次");
return 10; // 最多尝试 10 次。因为有10个线程争抢,重试要浪费好多时间。
public String getNewValue(long currCAS, String currV)
String newValue = "耀眼的笨笨" + l.get();
System.out.println("当前CAS=" + currCAS + "; 当前Value=" + currV +"; 目标Value=" + newValue);
return newValue;
;
memcachedClient.add("jerry", 3, "耀眼的笨笨");
IntStream.rangeClosed(1,10).parallel().forEach(i ->
try
memcachedClient.cas("jerry", 0, casOperation);
System.out.println(l.get());
catch (Exception e) e.printStackTrace();
);
System.out.println("最终结果: "+ memcachedClient.get("jerry"));
// 遍历所有键值对
@Test
@SuppressWarnings("deprecation")
public void getAllTest() throws InterruptedException, MemcachedException, TimeoutException
HashMap<String, Object> map = new HashMap<>();
KeyIterator keyIterator = memcachedClient.getKeyIterator(address);
while (keyIterator.hasNext())
String key = keyIterator.next();
map.put(key, memcachedClient.get(key));
System.out.println(map);
// 获取信息
@Test
public void statsTest() throws InterruptedException, MemcachedException, TimeoutException
String statsJson = memcachedClient.stats(address).entrySet().stream()
.map(entry -> String.format("\\"%s\\":\\"%s\\"", entry.getKey(), entry.getValue()))
.collect(Collectors.joining(", ", "", ""));
System.out.println(statsJson);
// 更新有效时间
@Test
public void touchTest() throws InterruptedException, MemcachedException, TimeoutException
memcachedClient.add("jerry", 3, "耀眼的笨笨");
TimeUnit.SECONDS.sleep(2);
memcachedClient.touch ("jerry", 3); // 更新过期时间,否则再取就是 null 了
TimeUnit.SECONDS.sleep(1);
String value = memcachedClient.get("jerry");
System.out.println("获得:" + value);
// 清空所有数据
@Test
public void clear() throws InterruptedException, MemcachedException, TimeoutException
memcachedClient.flushAll();
// 命名空间内的值,可以统一失效。
@Test
public void withNamespaceTest() throws InterruptedException, MemcachedException, TimeoutException
// 向命名空间 jerry 内批量插入数据。
Boolean bool = memcachedClient.withNamespace("jerry", client ->
IntStream.rangeClosed(1, 10).mapToObj(i ->
try
return client.add("key" + i, 30, "value="+i);
catch (Exception e) e.printStackTrace();
return false;
).allMatch(b -> b)
);
System.out.println("向命名空间 jerry 内批量插入数据成功:" + bool);
// 获取命名空间内的值
String s = memcachedClient.withNamespace("jerry", client -> client.get("key5"));
System.out.println("从命名空间 jerry 获取 key5 的值:"+ s);
// 批量取一波
IntStream.rangeClosed(1, 10).forEach(i->try
String str = memcachedClient.withNamespace("jerry", client -> client.get("key"+i));
System.out.println("获取第 "+i+" 个值:" + str);
catch (Exception e) e.printStackTrace(); );
// 让整个命名空间内容失效
this.memcachedClient.invalidateNamespace("jerry");
System.out.println("让整个命名空间内容失效");
// 再获取命名空间内的值,已经为 null
String ss = memcachedClient.withNamespace("jerry", client -> client.get("key5"));
System.out.println("再获取命名空间内的值,已经为:"+ ss);
参考资料
Memcached 官网
官方手册 Commands
memcached 命令行参数
XMemcachedClient JavaDoc
killme2008 / Xmemcached 中文用户指南
菜鸟教程 Windows 下安装 Memcached
菜鸟教程 Docker 命令大全
阿里云培训中心 Memcache完全自学手册
知乎dubx:memcached
以上是关于XMemcachedClient 操作 Memcached的主要内容,如果未能解决你的问题,请参考以下文章