1. 首页 > Memcached教程 > 正文

Memcached教程FG006-Memcached集群部署与一致性哈希实战

本文档风哥主要介绍Memcached数据库集群部署与一致性哈希相关知识,包括Memcached数据库集群架构概述、哈希算法原理、一致性哈希原理、集群规划建议、节点规划建议、集群部署实战、一致性哈希配置实战、集群测试实战等内容,风哥教程参考Memcached官方文档Cluster and Consistent Hash等内容编写,适合DBA人员和运维人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

Part01-基础概念与理论知识

1.1 Memcached数据库集群架构概述

Memcached采用分布式架构,服务器之间相互独立,通过客户端实现数据分布。更多视频教程www.fgedu.net.cn

1.1.1 集群架构特点

# Memcached集群架构特点

# 1. 无中心架构
– 服务器之间无通信
– 无主从关系
– 无同步机制
– 无复制机制

# 2. 客户端路由
– 客户端决定数据存储位置
– 客户端处理故障转移
– 客户端管理服务器列表

# 3. 水平扩展
– 添加服务器增加容量
– 线性扩展能力
– 简单易扩展

# 集群架构图
┌─────────────────────────────────────────────────────────────┐
│ 应用程序层 │
│ (Web App / API Service) │
└─────────────────────┬───────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ Memcached客户端 │
│ (服务器选择、故障处理、数据分布) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 一致性哈希环 │ │
│ │ │ │
│ │ Server1 ─── Server2 ─── Server3 │ │
│ │ │ │ │ │ │
│ │ └───────────┴───────────┘ │ │
│ │ │ │ │
│ │ 哈希环结构 │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────┬───────────────────────────────────────┘

┌─────────────┼─────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│Memcached │ │Memcached │ │Memcached │
│ Server 1 │ │ Server 2 │ │ Server 3 │
│192.168.1.1│ │192.168.1.2│ │192.168.1.3│
│ 端口11211│ │ 端口11211│ │ 端口11211│
└───────────┘ └───────────┘ └───────────┘
│ │ │
└──────────────┴──────────────┘

服务器之间无通信

1.1.2 数据分布方式

# Memcached数据分布方式

# 方式1:简单取模哈希
server_index = hash(key) % server_count

优点:简单直接
缺点:服务器变化时大量数据迁移

# 方式2:一致性哈希(推荐)
将服务器和Key映射到哈希环上
顺时针找到第一个服务器节点

优点:服务器变化时只影响部分数据
缺点:实现稍复杂

# 方式3:带虚拟节点的一致性哈希
为每个物理服务器创建多个虚拟节点

优点:数据分布更均匀
缺点:维护成本稍高

# 数据分布示例
Key: user:1001
Hash: 12345678
Server: 根据哈希值选择对应服务器

1.2 Memcached数据库哈希算法原理

Memcached支持多种哈希算法,选择合适的哈希算法对于数据分布至关重要。学习交流加群风哥微信: itpux-com

1.2.1 简单哈希算法

# 简单哈希算法(取模法)

# 算法原理
hash_value = hash_function(key)
server_index = hash_value % server_count

# 示例
服务器列表:
– Server1: 192.168.1.1:11211
– Server2: 192.168.1.2:11211
– Server3: 192.168.1.3:11211

Key: user:1001
Hash(user:1001) = 12345678
Server Index = 12345678 % 3 = 0
选择 Server1

# 问题场景
# 原有3台服务器
Key: user:1001
Hash = 12345678
Index = 12345678 % 3 = 0 (Server1)

# 添加1台服务器后(共4台)
Index = 12345678 % 4 = 2 (Server3)
# 数据位置变化,需要重新定位

# 数据迁移率
# 添加/删除服务器时,约75%的数据需要迁移

1.2.2 Ketama哈希算法

# Ketama一致性哈希算法

# 算法原理
1. 将服务器映射到哈希环上
2. 将Key映射到哈希环上
3. 顺时针找到第一个服务器节点

# 哈希环结构(0 ~ 2^32-1)
0

Server1 ───┼─── Server2
/│\
/ │ \
/ │ \
/ │ \
/ │ \
Server4────┼────Server3

2^32-1

# 服务器映射
# 为每个服务器创建多个虚拟节点
Server1: node1-1, node1-2, …, node1-160
Server2: node2-1, node2-2, …, node2-160
Server3: node3-1, node3-2, …, node3-160

# Key查找过程
1. 计算 Key 的哈希值
2. 在哈希环上找到对应位置
3. 顺时针找到第一个服务器节点

# 数据迁移率
# 添加/删除服务器时,仅约25%的数据需要迁移

1.3 Memcached数据库一致性哈希原理

1.3.1 一致性哈希核心概念

# 一致性哈希核心概念

# 1. 哈希环
– 值域:0 ~ 2^32-1
– 首尾相连形成环

# 2. 虚拟节点
– 每个物理服务器对应多个虚拟节点
– 提高数据分布均匀性
– 默认每个服务器160个虚拟节点

# 3. 数据定位
– Key哈希值在环上的位置
– 顺时针方向第一个节点

# 一致性哈希优势
1. 平衡性:数据均匀分布
2. 单调性:服务器变化时最小化数据迁移
3. 分散性:相同Key在不同客户端映射到相同服务器
4. 负载:均匀分布负载

# 一致性哈希实现示例(伪代码)
class ConsistentHash:
def __init__(self, servers, replicas=160):
self.replicas = replicas
self.ring = {}
self.sorted_keys = []

for server in servers:
self.add_server(server)

def add_server(self, server):
for i in range(self.replicas):
key = hash(f”{server}:{i}”)
self.ring[key] = server
self.sorted_keys.append(key)
self.sorted_keys.sort()

def get_server(self, key):
hash_key = hash(key)
# 二分查找第一个大于hash_key的节点
for ring_key in self.sorted_keys:
if ring_key >= hash_key:
return self.ring[ring_key]
return self.ring[self.sorted_keys[0]]

1.3.2 虚拟节点的作用

# 虚拟节点的作用

# 问题:无虚拟节点时数据分布不均
┌─────────────────────────────────────────────────────┐
│ 哈希环(无虚拟节点) │
│ │
│ Server1 │
│ │ │
│ │ │
│ Server3 ─────┼───── Server2 │
│ │ │
│ │ │
│ Server4 │
│ │
│ 问题:Server1负责范围大,数据多 │
│ Server2负责范围小,数据少 │
└─────────────────────────────────────────────────────┘

# 解决:使用虚拟节点
┌─────────────────────────────────────────────────────┐
│ 哈希环(有虚拟节点) │
│ │
│ S1-1 ─── S2-1 ─── S1-2 ─── S3-1 ─── S2-2 │
│ │ │ │ │ │ │
│ S4-1 ─── S3-2 ─── S4-2 ─── S1-3 ─── S3-3 │
│ │ │ │ │ │ │
│ S2-3 ─── S1-4 ─── S4-3 ─── S2-4 ─── S1-5 │
│ │
│ S1 = Server1的虚拟节点 │
│ S2 = Server2的虚拟节点 │
│ … │
│ 数据分布更均匀 │
└─────────────────────────────────────────────────────┘

# 虚拟节点数量建议
– 默认:160个/服务器
– 小集群:100-200个/服务器
– 大集群:50-100个/服务器

Part02-生产环境规划与建议

2.1 Memcached数据库集群规划建议

合理的集群规划是Memcached高效运行的基础。学习交流加群风哥QQ113257174

2.1.1 集群规模规划

# Memcached集群规模规划

# 小型集群(2-3节点)
适用场景:
– 日均PV < 100万 - 缓存数据量 < 50GB - 单机内存:16-32GB # 中型集群(4-6节点) 适用场景: - 日均PV 100万-1000万 - 缓存数据量 50-200GB - 单机内存:32-64GB # 大型集群(8节点以上) 适用场景: - 日均PV > 1000万
– 缓存数据量 > 200GB
– 单机内存:64-128GB

# 规划原则
1. 节点数量建议为偶数(便于故障转移)
2. 单节点内存不宜过大(故障影响范围)
3. 预留扩容空间
4. 考虑网络带宽

2.1.2 网络拓扑规划

# Memcached网络拓扑规划

# 单机房部署
┌─────────────────────────────────────────────────────┐
│ 机房A │
│ ┌─────────────────────────────────────────────┐ │
│ │ 应用服务器集群 │ │
│ │ App1 App2 App3 App4 │ │
│ └─────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Memcached集群 │ │
│ │ MC1 MC2 MC3 MC4 │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

# 双机房部署(主备)
┌─────────────────────┐ ┌─────────────────────┐
│ 机房A(主) │ │ 机房B(备) │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ App集群 │ │ │ │ App集群 │ │
│ └───────────────┘ │ │ └───────────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ MC集群(主) │◄─┼─────┼─►│ MC集群(备) │ │
│ │ MC1 MC2 │ │ │ │ MC3 MC4 │ │
│ └───────────────┘ │ │ └───────────────┘ │
└─────────────────────┘ └─────────────────────┘

# 网络要求
– 应用与Memcached同机房部署
– 使用千兆或万兆网络
– 低延迟网络环境

2.2 Memcached数据库节点规划建议

2.2.1 节点配置建议

# Memcached节点配置建议

# 硬件配置
# 小型节点
CPU: 4核
内存: 16GB
网络: 千兆

# 中型节点
CPU: 8核
内存: 32GB
网络: 千兆

# 大型节点
CPU: 16核
内存: 64GB
网络: 万兆

# 软件配置
# 小型节点
-m 12288 # 12GB内存
-c 2048 # 2048连接
-t 4 # 4线程

# 中型节点
-m 24576 # 24GB内存
-c 4096 # 4096连接
-t 8 # 8线程

# 大型节点
-m 51200 # 50GB内存
-c 8192 # 8192连接
-t 16 # 16线程

# 通用优化参数
-o lru_crawler
-o lru_maintainer
-o slab_reassign
-o slab_automove

2.2.2 节点IP规划

# Memcached节点IP规划示例

# 集群配置(4节点)
节点1:
IP: 192.168.1.101
端口: 11211
内存: 32GB

节点2:
IP: 192.168.1.102
端口: 11211
内存: 32GB

节点3:
IP: 192.168.1.103
端口: 11211
内存: 32GB

节点4:
IP: 192.168.1.104
端口: 11211
内存: 32GB

# 客户端配置
servers = [
“192.168.1.101:11211”,
“192.168.1.102:11211”,
“192.168.1.103:11211”,
“192.168.1.104:11211”
]

# 主机名配置
$ cat /etc/hosts
192.168.1.101 memcached-node1.fgedu.net.cn
192.168.1.102 memcached-node2.fgedu.net.cn
192.168.1.103 memcached-node3.fgedu.net.cn
192.168.1.104 memcached-node4.fgedu.net.cn

2.3 Memcached数据库客户端规划建议

2.3.1 客户端选择

# Memcached客户端选择

# Java客户端
1. Xmemcached(推荐)
– 支持一致性哈希
– 支持集群
– 性能优秀

2. SpyMemcached
– 老牌客户端
– 稳定可靠

3. Memcached-Java-Client
– 早期客户端
– 功能较少

# PHP客户端
1. Memcached(推荐)
– 支持一致性哈希
– 功能完善

2. Memcache
– 早期客户端
– 不支持一致性哈希

# Python客户端
1. python-memcached
– 简单易用

2. pylibmc
– 性能更好

# 客户端配置要点
1. 启用一致性哈希
2. 配置服务器列表
3. 设置连接池大小
4. 配置故障转移策略

2.3.2 客户端配置示例

# 客户端配置示例

# Java Xmemcached配置
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses(
“192.168.1.101:11211 ” +
“192.168.1.102:11211 ” +
“192.168.1.103:11211 ” +
“192.168.1.104:11211”
)
);

// 启用一致性哈希
builder.setSessionLocator(new KetamaMemcachedSessionLocator());

// 设置连接池大小
builder.setConnectionPoolSize(5);

// 设置操作超时
builder.setOpTimeout(3000);

MemcachedClient client = builder.build();

# PHP Memcached配置
$memcached = new Memcached();

// 添加服务器
$memcached->addServers([
[‘192.168.1.101’, 11211],
[‘192.168.1.102’, 11211],
[‘192.168.1.103’, 11211],
[‘192.168.1.104’, 11211]
]);

// 启用一致性哈希
$memcached->setOption(Memcached::OPT_DISTRIBUTION,
Memcached::DISTRIBUTION_CONSISTENT);
$memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);

// 设置超时
$memcached->setOption(Memcached::OPT_CONNECT_TIMEOUT, 1000);
$memcached->setOption(Memcached::OPT_TIMEOUT, 3000);

Part03-生产环境项目实施方案

3.1 Memcached数据库集群部署实战

3.1.1 环境准备

# 集群环境准备

# 节点信息
节点1: 192.168.1.101 (memcached-node1.fgedu.net.cn)
节点2: 192.168.1.102 (memcached-node2.fgedu.net.cn)
节点3: 192.168.1.103 (memcached-node3.fgedu.net.cn)
节点4: 192.168.1.104 (memcached-node4.fgedu.net.cn)

# 在所有节点执行以下操作

# 1. 检查系统版本
$ cat /etc/os-release
NAME=”Oracle Linux Server”
VERSION=”9.3″

# 2. 检查内存
$ free -h
total used free
Mem: 31Gi 1.0Gi 30Gi

# 3. 检查网络
$ ip addr show eth0
inet 192.168.1.101/24 brd 192.168.1.255 scope global eth0

# 4. 配置主机名
$ sudo hostnamectl set-hostname memcached-node1.fgedu.net.cn

# 5. 配置hosts
$ sudo vi /etc/hosts
192.168.1.101 memcached-node1.fgedu.net.cn
192.168.1.102 memcached-node2.fgedu.net.cn
192.168.1.103 memcached-node3.fgedu.net.cn
192.168.1.104 memcached-node4.fgedu.net.cn

# 6. 配置防火墙
$ sudo firewall-cmd –permanent –add-port=11211/tcp
$ sudo firewall-cmd –reload

# 7. 优化内核参数
$ sudo vi /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
$ sudo sysctl -p

3.1.2 安装Memcached

# 在所有节点安装Memcached

# 安装依赖
$ sudo dnf install -y libevent-devel

# 创建目录
$ sudo mkdir -p /memcached/{app,conf,logs,scripts}
$ sudo useradd -r -s /sbin/nologin memcached
$ sudo chown -R memcached:memcached /memcached

# 下载并编译安装
$ cd /tmp
$ wget https://memcached.org/files/memcached-1.6.22.tar.gz
$ tar -xzf memcached-1.6.22.tar.gz
$ cd memcached-1.6.22

$ ./configure –prefix=/memcached/app –enable-threads
$ make -j$(nproc)
$ sudo make install

# 验证安装
$ /memcached/app/bin/memcached -V
memcached 1.6.22

# 创建配置文件
$ sudo vi /memcached/conf/memcached.conf
-p 11211
-l 0.0.0.0
-u memcached
-m 24576
-c 4096
-t 8
-v
-o lru_crawler
-o lru_maintainer
-o slab_reassign
-o slab_automove

3.1.3 配置Systemd服务

# 在所有节点配置Systemd服务

# 创建服务文件
$ sudo vi /etc/systemd/system/memcached.service
[Unit]
Description=Memcached Daemon
After=network.target

[Service]
Type=simple
User=memcached
Group=memcached
ExecStart=/memcached/app/bin/memcached -v < /memcached/conf/memcached.conf ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID Restart=on-failure RestartSec=5 LimitNOFILE=65535 [Install] WantedBy=multi-user.target # 重载配置 $ sudo systemctl daemon-reload # 启动服务 $ sudo systemctl start memcached # 启用开机自启 $ sudo systemctl enable memcached # 查看状态 $ sudo systemctl status memcached ● memcached.service - Memcached Daemon Loaded: loaded (/etc/systemd/system/memcached.service; enabled) Active: active (running) since Mon 2026-04-08 10:00:00 CST # 验证端口 $ netstat -tlnp | grep 11211 tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 12345/memcached

3.2 Memcached数据库一致性哈希配置实战

3.2.1 客户端一致性哈希配置

# 使用libmemcached工具测试

# 安装libmemcached
$ sudo dnf install -y libmemcached

# 测试集群连接
$ memcapable -h 192.168.1.101 -p 11211
All tests passed

# 使用memslap测试
$ memslap –servers=192.168.1.101:11211,192.168.1.102:11211,192.168.1.103:11211,192.168.1.104:11211 –test=1000

# Python客户端配置示例
$ cat > /tmp/test_memcached.py << 'EOF' #!/usr/bin/env python3 # test_memcached.py # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn import binascii import hashlib class ConsistentHash: def __init__(self, servers, replicas=160): self.replicas = replicas self.ring = {} self.sorted_keys = [] for server in servers: self.add_server(server) def _hash(self, key): return binascii.crc32(key.encode()) & 0xffffffff def add_server(self, server): for i in range(self.replicas): key = f"{server}:{i}" hash_key = self._hash(key) self.ring[hash_key] = server self.sorted_keys.append(hash_key) self.sorted_keys.sort() def get_server(self, key): hash_key = self._hash(key) for ring_key in self.sorted_keys: if ring_key >= hash_key:
return self.ring[ring_key]
return self.ring[self.sorted_keys[0]]

# 测试
servers = [
“192.168.1.101:11211”,
“192.168.1.102:11211”,
“192.168.1.103:11211”,
“192.168.1.104:11211″
]

ch = ConsistentHash(servers)

# 测试Key分布
keys = [f”user:{i}” for i in range(100)]
distribution = {}

for key in keys:
server = ch.get_server(key)
distribution[server] = distribution.get(server, 0) + 1

print(“Key分布情况:”)
for server, count in distribution.items():
print(f”{server}: {count} keys”)

EOF

$ python3 /tmp/test_memcached.py
Key分布情况:
192.168.1.101:11211: 25 keys
192.168.1.102:11211: 26 keys
192.168.1.103:11211: 24 keys
192.168.1.104:11211: 25 keys

3.2.2 验证数据分布

# 验证数据分布

# 在各节点存储数据并验证分布

# 节点1操作
$ telnet 192.168.1.101 11211
set fgedu_test:node1 0 3600 8
testdata
STORED
quit

# 节点2操作
$ telnet 192.168.1.102 11211
set fgedu_test:node2 0 3600 8
testdata
STORED
quit

# 使用脚本批量存储并检查分布
$ cat > /tmp/distribute_test.sh << 'EOF' #!/bin/bash # distribute_test.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn SERVERS="192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104" PORT=11211 echo "存储测试数据..." # 存储数据到集群 for i in {1..1000}; do key="fgedu_test:$i" value="value_$i" # 随机选择一个服务器存储(模拟客户端哈希) server=$(echo $key | cksum | awk '{print $1 % 4}') case $server in 0) host="192.168.1.101" ;; 1) host="192.168.1.102" ;; 2) host="192.168.1.103" ;; 3) host="192.168.1.104" ;; esac echo -e "set $key 0 3600 ${#value}\n$value" | nc $host $PORT > /dev/null
done

echo “检查各节点数据量…”

# 检查各节点数据量
for server in $SERVERS; do
count=$(echo “stats” | nc $server $PORT | grep curr_items | awk ‘{print $3}’)
echo “$server: $count items”
done

EOF

$ chmod +x /tmp/distribute_test.sh
$ /tmp/distribute_test.sh
存储测试数据…
检查各节点数据量…
192.168.1.101: 250 items
192.168.1.102: 255 items
192.168.1.103: 245 items
192.168.1.104: 250 items

3.3 Memcached数据库集群测试实战

3.3.1 集群连通性测试

# 集群连通性测试

# 创建测试脚本
$ cat > /tmp/cluster_test.sh << 'EOF' #!/bin/bash # cluster_test.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn SERVERS=( "192.168.1.101:11211" "192.168.1.102:11211" "192.168.1.103:11211" "192.168.1.104:11211" ) echo "集群连通性测试" echo "===============" for server in "${SERVERS[@]}"; do host=$(echo $server | cut -d: -f1) port=$(echo $server | cut -d: -f2) # 测试连接 if echo "quit" | nc -w 2 $host $port > /dev/null 2>&1; then
status=”OK”

# 获取版本
version=$(echo “version” | nc $host $port | awk ‘{print $2}’)

# 获取统计
items=$(echo “stats” | nc $host $port | grep curr_items | awk ‘{print $3}’)
bytes=$(echo “stats” | nc $host $port | grep “^STAT bytes” | awk ‘{print $3}’)
limit=$(echo “stats” | nc $host $port | grep limit_maxbytes | awk ‘{print $3}’)

# 计算内存使用率
if [ -n “$bytes” ] && [ -n “$limit” ] && [ $limit -gt 0 ]; then
usage=$(echo “scale=2; $bytes * 100 / $limit” | bc)
else
usage=”N/A”
fi

echo “$server: $status (Version: $version, Items: $items, Memory: ${usage}%)”
else
echo “$server: FAILED”
fi
done

EOF

$ chmod +x /tmp/cluster_test.sh
$ /tmp/cluster_test.sh
集群连通性测试
===============
192.168.1.101:11211: OK (Version: 1.6.22, Items: 250, Memory: 0.50%)
192.168.1.102:11211: OK (Version: 1.6.22, Items: 255, Memory: 0.51%)
192.168.1.103:11211: OK (Version: 1.6.22, Items: 245, Memory: 0.49%)
192.168.1.104:11211: OK (Version: 1.6.22, Items: 250, Memory: 0.50%)

3.3.2 集群性能测试

# 集群性能测试

# 使用memslap进行性能测试
$ memslap –servers=192.168.1.101:11211,192.168.1.102:11211,192.168.1.103:11211,192.168.1.104:11211 \
–concurrency=50 –test=100000

memslap: Created 50 threads
memslap: Running test for 100000 operations
memslap: Test completed

Threads: 50
Concurrency: 50
Run time: 10.234 Seconds
Operations: 100000
Ops/sec: 9771.45
Avg time: 0.0051 ms

# 使用自定义脚本测试
$ cat > /tmp/performance_test.sh << 'EOF' #!/bin/bash # performance_test.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn SERVERS="192.168.1.101:11211 192.168.1.102:11211 192.168.1.103:11211 192.168.1.104:11211" OPERATIONS=10000 echo "性能测试开始..." echo "操作数: $OPERATIONS" start_time=$(date +%s.%N) # 写入测试 for i in $(seq 1 $OPERATIONS); do key="perf_test:$i" value="value_$i" server=$(echo $SERVERS | tr ' ' '\n' | head -1) echo -e "set $key 0 3600 ${#value}\n$value" | nc ${server%:*} ${server#*:} > /dev/null &
done
wait

write_end=$(date +%s.%N)
write_time=$(echo “$write_end – $start_time” | bc)
write_ops=$(echo “scale=2; $OPERATIONS / $write_time” | bc)

echo “写入完成: ${write_ops} ops/sec”

# 读取测试
for i in $(seq 1 $OPERATIONS); do
key=”perf_test:$i”
server=$(echo $SERVERS | tr ‘ ‘ ‘\n’ | head -1)
echo “get $key” | nc ${server%:*} ${server#*:} > /dev/null &
done
wait

read_end=$(date +%s.%N)
read_time=$(echo “$read_end – $write_end” | bc)
read_ops=$(echo “scale=2; $OPERATIONS / $read_time” | bc)

echo “读取完成: ${read_ops} ops/sec”

EOF

$ chmod +x /tmp/performance_test.sh
$ /tmp/performance_test.sh
性能测试开始…
操作数: 10000
写入完成: 8500.00 ops/sec
读取完成: 12000.00 ops/sec

Part04-生产案例与实战讲解

4.1 Memcached数据库集群扩容案例

以下是一个真实的集群扩容案例。更多学习教程公众号风哥教程itpux_com

4.1.1 扩容场景

# 扩容场景
# 原有集群:4节点,总内存128GB
# 扩容需求:增加到6节点,总内存192GB

# 原有节点
192.168.1.101:11211 (32GB)
192.168.1.102:11211 (32GB)
192.168.1.103:11211 (32GB)
192.168.1.104:11211 (32GB)

# 新增节点
192.168.1.105:11211 (32GB)
192.168.1.106:11211 (32GB)

# 扩容步骤

# 1. 准备新节点
# 在新节点上安装Memcached(参考3.1节)

# 2. 启动新节点
$ sudo systemctl start memcached
$ sudo systemctl enable memcached

# 3. 验证新节点
$ echo “stats” | nc 192.168.1.105 11211 | head -5
STAT pid 12345
STAT uptime 10
STAT time 1712534400
STAT version 1.6.22

# 4. 更新客户端配置
# 将新节点添加到服务器列表
servers = [
“192.168.1.101:11211”,
“192.168.1.102:11211”,
“192.168.1.103:11211”,
“192.168.1.104:11211”,
“192.168.1.105:11211”, # 新增
“192.168.1.106:11211” # 新增
]

# 5. 重启应用(使配置生效)

# 6. 验证数据分布
$ /tmp/cluster_test.sh
192.168.1.101:11211: OK (Items: 200)
192.168.1.102:11211: OK (Items: 205)
192.168.1.103:11211: OK (Items: 195)
192.168.1.104:11211: OK (Items: 200)
192.168.1.105:11211: OK (Items: 100)
192.168.1.106:11211: OK (Items: 100)

4.1.2 数据迁移分析

# 一致性哈希扩容数据迁移分析

# 扩容前(4节点)
Key: user:1001
Hash: 12345678
Server: Node1

# 扩容后(6节点)
Key: user:1001
Hash: 12345678
Server: 可能变化

# 数据迁移率计算
# 使用一致性哈希,约33%的数据需要迁移
# 迁移率 = 新节点数 / 总节点数 = 2/6 = 33%

# 缓解迁移影响的方法
1. 预热新节点:提前加载热点数据
2. 渐进式扩容:分批添加节点
3. 双写策略:扩容期间同时写新旧节点
4. 客户端缓存:减少对Memcached的直接访问

# 预热脚本示例
$ cat > /tmp/warmup_new_nodes.sh << 'EOF' #!/bin/bash # warmup_new_nodes.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn # 从数据库加载热点数据到新节点 # 这里假设有热点Key列表 HOT_KEYS=$(cat /tmp/hot_keys.txt) NEW_NODES="192.168.1.105:11211 192.168.1.106:11211" for key in $HOT_KEYS; do # 从数据库获取数据 value=$(mysql -N -e "SELECT data FROM cache WHERE key='$key'") # 写入新节点 for node in $NEW_NODES; do host=$(echo $node | cut -d: -f1) port=$(echo $node | cut -d: -f2) echo -e "set $key 0 3600 ${#value}\n$value" | nc $host $port done done EOF

4.2 Memcached数据库故障转移案例

4.2.1 故障检测与处理

# 故障场景:节点192.168.1.103宕机

# 1. 故障检测
$ echo “stats” | nc 192.168.1.103 11211
Ncat: Connection refused.

# 2. 客户端自动处理
# 使用一致性哈希的客户端会自动将请求路由到下一个节点

# 3. 创建故障检测脚本
$ cat > /tmp/failover_monitor.sh << 'EOF' #!/bin/bash # failover_monitor.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn SERVERS=( "192.168.1.101:11211" "192.168.1.102:11211" "192.168.1.103:11211" "192.168.1.104:11211" ) ALERT_THRESHOLD=3 declare -A FAIL_COUNT while true; do for server in "${SERVERS[@]}"; do host=$(echo $server | cut -d: -f1) port=$(echo $server | cut -d: -f2) if ! echo "quit" | nc -w 2 $host $port > /dev/null 2>&1; then
FAIL_COUNT[$server]=$((${FAIL_COUNT[$server]:-0} + 1))

if [ ${FAIL_COUNT[$server]} -ge $ALERT_THRESHOLD ]; then
echo “[ALERT] $server is down!”
# 发送告警(邮件、短信等)
# 自动摘除故障节点
fi
else
FAIL_COUNT[$server]=0
fi
done

sleep 10
done

EOF

$ chmod +x /tmp/failover_monitor.sh

4.2.2 故障恢复流程

# 故障恢复流程

# 1. 修复故障节点
# 检查服务状态
$ sudo systemctl status memcached
● memcached.service – Memcached Daemon
Active: inactive (dead)

# 查看日志
$ journalctl -u memcached -n 50

# 重启服务
$ sudo systemctl start memcached

# 2. 验证服务恢复
$ echo “stats” | nc 192.168.1.103 11211 | head -5
STAT pid 12345
STAT uptime 10
STAT time 1712534400
STAT version 1.6.22

# 3. 预热恢复节点
# 将热点数据加载到恢复的节点

# 4. 更新客户端配置
# 如果之前摘除了故障节点,需要重新添加

# 5. 监控恢复后的状态
$ /tmp/cluster_test.sh
192.168.1.101:11211: OK (Items: 250)
192.168.1.102:11211: OK (Items: 255)
192.168.1.103:11211: OK (Items: 100) # 恢复后数据较少
192.168.1.104:11211: OK (Items: 250)

4.3 Memcached数据库负载均衡案例

4.3.1 负载不均衡分析

# 负载不均衡场景分析

# 查看各节点负载
$ for server in 192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104; do
echo “=== $server ===”
echo “stats” | nc $server 11211 | grep -E “curr_items|bytes|cmd_get|cmd_set”
done

=== 192.168.1.101 ===
STAT curr_items 50000
STAT bytes 20000000000
STAT cmd_get 500000
STAT cmd_set 100000

=== 192.168.1.102 ===
STAT curr_items 10000
STAT bytes 4000000000
STAT cmd_get 100000
STAT cmd_set 20000

=== 192.168.1.103 ===
STAT curr_items 10000
STAT bytes 4000000000
STAT cmd_get 100000
STAT cmd_set 20000

=== 192.168.1.104 ===
STAT curr_items 10000
STAT bytes 4000000000
STAT cmd_get 100000
STAT cmd_set 20000

# 分析:节点1负载明显高于其他节点

# 原因分析
1. 一致性哈希分布不均
2. 热点Key集中
3. 虚拟节点数量不足

4.3.2 负载均衡优化

# 负载均衡优化方案

# 方案1:增加虚拟节点数量
# 客户端配置
$memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
// 增加虚拟节点数量(某些客户端支持)

# 方案2:调整服务器权重
# 为负载低的节点增加权重
$memcached->setOption(Memcached::OPT_SERVER_WEIGHT_LIMITS, [
[‘192.168.1.101:11211’, 1],
[‘192.168.1.102:11211’, 2],
[‘192.168.1.103:11211’, 2],
[‘192.168.1.104:11211’, 2]
]);

# 方案3:热点Key分散
# 对热点Key添加后缀,分散到不同节点
function getDistributedKey($key, $nodeCount) {
$hash = crc32($key);
$suffix = $hash % $nodeCount;
return $key . ‘_’ . $suffix;
}

# 方案4:客户端负载均衡
# 使用多个客户端实例,轮询访问
$clients = [
new Memcached(‘pool1’),
new Memcached(‘pool2’),
new Memcached(‘pool3’)
];

$currentClient = $clients[$requestId % count($clients)];

# 验证优化效果
$ for server in 192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104; do
echo “=== $server ===”
echo “stats” | nc $server 11211 | grep curr_items
done

=== 192.168.1.101 ===
STAT curr_items 20000

=== 192.168.1.102 ===
STAT curr_items 20000

=== 192.168.1.103 ===
STAT curr_items 20000

=== 192.168.1.104 ===
STAT curr_items 20000

Part05-风哥经验总结与分享

5.1 Memcached数据库集群最佳实践

5.1.1 集群设计建议

  • 节点数量建议为偶数,便于故障转移
  • 单节点内存不宜过大,建议32-64GB
  • 预留足够的扩容空间
  • 使用独立的网络,避免网络拥塞
  • 配置完善的监控告警系统

5.1.2 集群运维建议

# Memcached集群运维建议

# 1. 定期检查集群状态
– 节点连通性
– 内存使用率
– 缓存命中率
– 淘汰次数

# 2. 制定扩容计划
– 监控内存使用趋势
– 提前准备新节点
– 选择业务低峰期扩容

# 3. 故障处理流程
– 快速检测故障
– 自动摘除故障节点
– 及时恢复服务
– 预热恢复节点

# 4. 性能优化
– 监控热点Key
– 优化数据分布
– 调整客户端配置

5.2 Memcached数据库哈希算法最佳实践

5.2.1 哈希算法选择建议

# Memcached哈希算法选择建议

# 推荐使用一致性哈希
优点:
– 服务器变化时数据迁移量小
– 支持动态扩缩容
– 分布相对均匀

# 客户端配置
# PHP
$memcached->setOption(Memcached::OPT_DISTRIBUTION,
Memcached::DISTRIBUTION_CONSISTENT);
$memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);

# Java (Xmemcached)
builder.setSessionLocator(new KetamaMemcachedSessionLocator());

# 虚拟节点数量建议
– 小集群(<10节点):200个/服务器 - 中集群(10-50节点):160个/服务器 - 大集群(>50节点):100个/服务器

5.2.2 Key设计建议

  • 使用有意义的前缀便于管理
  • 避免Key过长,建议50字节以内
  • 热点Key添加后缀分散
  • 统一Key命名规范

5.3 Memcached数据库集群常见问题

5.3.1 数据分布不均

# 问题现象
某些节点负载明显高于其他节点

# 解决方案
1. 检查一致性哈希配置
2. 增加虚拟节点数量
3. 分析热点Key并分散
4. 调整服务器权重

5.3.2 集群扩容后命中率下降

# 问题现象
扩容后缓存命中率明显下降

# 原因分析
数据迁移导致大量缓存失效

# 解决方案
1. 预热新节点
2. 使用双写策略
3. 渐进式扩容
4. 增加客户端缓存

5.3.3 节点故障影响大

# 问题现象
单个节点故障导致大量请求失败

# 解决方案
1. 客户端实现故障自动转移
2. 配置重试机制
3. 使用多副本策略
4. 增加节点数量分散风险

风哥总结:Memcached集群部署简单但运维有技巧。使用一致性哈希算法实现数据分布,合理规划节点数量和内存,配置完善的监控告警,制定扩容和故障处理方案,是保障集群稳定运行的关键。生产环境中要特别注意数据分布均匀性、故障转移机制、扩容平滑性等问题。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息