Java-191 Netflix EVCache Client 接入 Memcached 实战:安装、配备与踩坑记录

TL;DR

  • 场景:Java 应用想在本地或小团队环境体验 Netflix EVCache,但服务端未开源,只能基于 Memcached 自建。
  • 结论:通过源码编译 Memcached 1.6.39,并按 EVCache 的节点配置规范启动,就能完成基本读写与链路验证。
  • 产出:给出从编译安装 Memcached、启动参数说明,到 EVCache Client POM 依赖与示例代码的一条龙配置指引。

Java-191 Netflix EVCache Client 接入 Memcached 实战:安装、配置与踩坑记录

版本矩阵

组件/环境版本/说明已验证说明
Memcached1.6.39按文中步骤在 Linux 环境下载源码、./configure 编译并安装。
libevent系统仓库默认(yum 安装)通过 yum install libevent libevent-devel gcc-c++ 获取。
EVCache Client4.139.0作为核心客户端依赖,负责与 Memcached 通信与封装。
spymemcached2.12.3EVCache 底层 Memcached 客户端实现,需与服务端协议兼容。
Eureka Client1.5.6(runtime)文中作为依赖引入,当前示例中主要满足 EVCache 依赖链。
Spectator0.80.1用于指标采集与监控,示例中作为运行时组件引入。
Archaius / Archaius20.6.0 / 2.3.13动态配置组件,满足 EVCache 配置体系依赖。

安装使用

由于Netflix没有开源 EVCache的服务器部分,这里采用 Memcached 作为服务器。

Memcached 介绍

Memcached 是一个开源的、高性能的分布式内存对象缓存系统,主要用于减轻数据库负载,提升动态 Web 应用的访问速度。它通过在内存中缓存数据和对象来减少对数据库的直接访问次数,从而提高动态网站的性能。

核心特性

  1. 内存存储:所有数据都存储在内存中,读写速度极快(通常在微秒级别完成操作)
  2. 键值存储:采用简单的键值对(key-value)存储结构
  3. 分布式架构:支持多服务器集群部署
  4. LRU 算法:当内存不足时,采用最近最少使用算法自动清除数据

工作原理

当应用程序需要数据时:

  1. 首先检查 Memcached 中是否存在该数据
  2. 如果存在(缓存命中),直接从内存返回结果
  3. 如果不存在(缓存未命中),则从数据库获取数据,并将结果存入 Memcached 供后续使用

典型应用场景

  • 数据库查询缓存:缓存频繁访问的数据库查询结果
  • 会话存储:存储用户会话信息
  • API 缓存:缓存第三方 API 的响应结果
  • 页面片段缓存:缓存动态页面的部分内容

优势与局限

优势

  • 极高的读写性能
  • 简单的部署和使用
  • 良好的水平扩展能力
  • 降低数据库负载

局限

  • 数据不具备持久性(重启服务数据会丢失)
  • 没有内置的安全机制(如认证)
  • 缺乏数据同步和复制功能

基本命令示例

# 连接 Memcached
telnet localhost 11211
# 存储数据
set key 0 900 10
helloworld
# 获取数据
get key

Memcached 通常与 MySQL、PostgreSQL 等关系型数据库配合使用,是构建高性能 Web 应用的重要组件之一。

安装 Memcached

# 安装libevent库
yum install libevent libevent-devel gcc-c++
cd /opt/software
# 下载最新的memcached
wget http://memcached.org/latest
tar -zxvf latest

Memcached 安装测试

cd memcached-1.6.39
./configure --prefix=/usr/memcached
make
make install

Memcached 编译

./memcached -d -m 1000 -u root -l 0.0.0.0 -p 11211 -c 256 -P /tmp/memcached.pid

以下是扩展后的内容,增加了参数说明和使用示例:

  • -d 选项:以守护进程(daemon)模式启动Memcache服务,使服务在后台运行而不占用终端。例如:memcached -d 会立即返回shell提示符。

  • -m 参数:设置分配给Memcache服务使用的内存总量,单位为MB。例如:-m 64表示分配64MB内存。建议根据服务器可用内存合理配置,通常设置为总内存的10-30%。

  • -u 参数:指定运行Memcache服务的系统用户。出于安全考虑,建议使用非root用户。例如:-u nobody会以nobody用户身份运行服务。

  • -l 参数:设置Memcache监听的服务器IP地址。默认监听所有可用网络接口(0.0.0.0)。例如:-l 192.168.1.100只监听指定IP。

  • -p 参数:配置Memcache服务监听的TCP端口号,默认是11211。例如:-p 11211。如果修改默认端口,客户端连接时需指定相同端口。

  • -c 参数:设置最大并发连接数,默认1024。在高并发场景下可能需要调高此值。例如:-c 2048允许最多2048个并发连接。

  • -P 参数:指定存储Memcache进程ID(pid)的文件路径。例如:-P /var/run/memcached.pid。通过pid文件可以方便地管理服务进程。

典型启动示例:

memcached -d -m 256 -u memcache -l 192.168.1.100 -p 11211 -c 2048 -P /var/run/memcached.pid

这个命令会启动一个Memcache守护进程,分配256MB内存,以memcache用户身份运行,监听192.168.1.100的11211端口,允许2048个并发连接,并将进程ID保存在指定文件。

Memcached 启动服务

使用 EVCache Client

POM

<dependencies>
  <dependency>
  <groupId>com.netflix.evcache</groupId>
  <artifactId>evcache-client</artifactId>
  <version>4.139.0</version>
  </dependency>
  <dependency>
  <groupId>net.spy</groupId>
  <artifactId>spymemcached</artifactId>
  <version>2.12.3</version>
  </dependency>
  <dependency>
  <groupId>com.netflix.eureka</groupId>
  <artifactId>eureka-client</artifactId>
  <version>1.5.6</version>
  <scope>runtime</scope>
  </dependency>
  <dependency>
  <groupId>com.netflix.spectator</groupId>
  <artifactId>spectator-nflx-plugin</artifactId>
  <version>0.80.1</version>
  <scope>runtime</scope>
  </dependency>
  <dependency>
  <groupId>com.netflix.spectator</groupId>
  <artifactId>spectator-api</artifactId>
  <version>0.80.1</version>
  </dependency>
  <dependency>
  <groupId>com.netflix.rxjava</groupId>
  <artifactId>rxjava-core</artifactId>
  <version>0.20.7</version>
  </dependency>
  <dependency>
  <groupId>com.netflix.servo</groupId>
  <artifactId>servo-core</artifactId>
  <version>0.12.25</version>
  </dependency>
  <dependency>
  <groupId>com.google.code.findbugs</groupId>
  <artifactId>annotations</artifactId>
  <version>3.0.1</version>
  </dependency>
  <dependency>
  <groupId>com.netflix.nebula</groupId>
  <artifactId>nebula-core</artifactId>
  <version>4.0.1</version>
  <scope>runtime</scope>
  </dependency>
  <dependency>
  <groupId>com.netflix.archaius</groupId>
  <artifactId>archaius2-core</artifactId>
  <version>2.3.13</version>
  <scope>runtime</scope>
  </dependency>
  <dependency>
  <groupId>com.netflix.archaius</groupId>
  <artifactId>archaius-aws</artifactId>
  <version>0.6.0</version>
  </dependency>
  <dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <version>1</version>
  </dependency>
  <dependency>
  <groupId>io.reactivex</groupId>
  <artifactId>rxjava</artifactId>
  <version>1.3.8</version>
  </dependency>
</dependencies>

编写代码

package icu.wzk;
import com.netflix.evcache.EVCache;
public class CacheDemo01 {
public static void main(String[] args) throws Exception {
String server = "SERVERGROUP1=172.16.1.130:11211";
System.setProperty("EVCACHE_1.use.simple.node.list.provider", "true");
System.setProperty("EVCACHE_1-NODES", server);
EVCache evCache = new EVCache.Builder()
.setAppName("EVCACHE_1")
.build();
evCache.set("wzk", "icu", 10);
String data = evCache.get("wzk");
System.out.println(data);
}
}

测试运行代码如下:
Memcached 运行测试

错误速查

症状根因定位思路修复方式
Java 代码中 EVCache set 正常,get(“wzk”) 返回 null 或空key 过期时间过短,或拼写不一致,或 Memcached 未正确启动通过 telnet host 11211 手动 get key,确认服务端是否有值且未过期延长过期时间参数,统一 key 命名;确保 Memcached 已正常启动且无重启/杀进程
客户端启动时报 Connection refused 或超时-l 监听地址与客户端连接地址不一致,或端口被防火墙拦截在服务端执行 `netstat -ntlpgrep 11211` 确认监听地址与端口;检查防火墙
使用文中命令启动 Memcached 报 permission denied-P 指定的 pid 文件路径目录无写权限,或非 root 用户无权限检查 /tmp/memcached.pid 或自定义路径的目录权限与所属用户将 -P 指向有写权限的目录,或调整目录权限;生产中使用专门的非 root 用户与目录
Memcached 启动后占用内存远高于预期-m 设置过大,或多实例叠加,或系统其他进程内存紧张通过 `ps auxgrep memcachedtop` 观察内存占用与参数
编译阶段 ./configure 或 make 报找不到 libevent 等错误未安装 libevent-devel 或编译工具链不完整检查 `yum list installedgrep libevent`,确认是否安装 -devel 包
EVCache Client 运行时报依赖冲突或 NoSuchMethodError项目中已有不同版本的 rxjava/spectator 等依赖导致冲突通过 mvn dependency:tree 排查同名依赖的版本,定位冲突来源使用 Maven 依赖排除()或在父 POM 锁定统一版本,减少多版本并存
通过 telnet set/get 正常,但 Java 中读写报错或乱码字符编码、序列化方式不一致,或客户端对 value 做了自定义处理对比 telnet 与 Java 中的实际字节内容,检查序列化/编码设置确保客户端与服务器统一使用 UTF-8 等约定编码;若有自定义序列化,要在文中提示读者注意
本地能连,跨机器连不上 Memcached-l 绑定为 127.0.0.1,外部机器无法访问在服务端确认 -l 参数值和监听 IP;用外部机器 telnet IP 11211 测试将 -l 修改为内网 IP 或 0.0.0.0 并重启服务,必要时调整安全组与防火墙策略

其他系列

AI篇持续更新中(长期更新)

AI炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究,持续打造实用AI工具指南!
AI研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地
AI模块直达链接

Java篇持续更新中(长期更新)

Java-180 Java 接入 FastDFS:自编译客户端与 Maven/Spring Boot 实战
MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务已完结,Dubbo已完结,MySQL已完结,MongoDB已完结,Neo4j已完结,FastDFS 已完结,OSS正在更新… 深入浅出助你打牢基础!
Java模块直达链接

大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解
大数据模块直达链接

posted @ 2026-01-21 15:22  gccbuaa  阅读(0)  评论(0)    收藏  举报