Memcached
高性能な分散メモリオブジェクトキャッシングシステム。シンプルなキーバリューストアで軽量性に特化。マルチスレッド対応。
Memcached
Memcachedは、高性能な分散メモリキャッシュシステムです。データベースの負荷軽減、動的Webアプリケーションの高速化を目的として設計され、シンプルなKey-Valueストアとして動作します。
主な特徴
高性能・軽量設計
- インメモリ処理による超高速アクセス
- シンプルなプロトコルによる低オーバーヘッド
- マルチスレッドアーキテクチャ
- 効率的なメモリ管理(Slab Allocation)
分散対応
- クライアントサイドでの分散ハッシュ
- 水平スケーリング対応
- ノード追加・削除の容易さ
- 単一障害点なしのアーキテクチャ
シンプルなKey-Valueモデル
- 文字列キーとバイナリ値のペア
- TTL(Time To Live)による自動期限切れ
- LRU(Least Recently Used)による自動削除
- アトミックな増減操作
インストール
Ubuntu/Debian
# パッケージマネージャからインストール
sudo apt update
sudo apt install memcached libmemcached-tools
# サービス開始
sudo systemctl start memcached
sudo systemctl enable memcached
CentOS/RHEL
# EPEL リポジトリの有効化
sudo dnf install epel-release
sudo dnf install memcached libmemcached
# サービス開始
sudo systemctl start memcached
sudo systemctl enable memcached
Docker
# Memcached の起動
docker run --name memcached-cache \
-p 11211:11211 \
-d memcached:1.6-alpine
# メモリ制限付きで起動
docker run --name memcached-cache \
-p 11211:11211 \
-d memcached:1.6-alpine memcached -m 64
ソースからのビルド
# 依存関係のインストール
sudo apt-get install build-essential libevent-dev
# Memcached のダウンロードとビルド
wget https://memcached.org/latest
tar -zxf memcached-x.x.x.tar.gz
cd memcached-x.x.x
./configure --prefix=/usr/local/memcached
make && make test && sudo make install
基本設定
起動オプション
# 基本的な起動
memcached -d -m 64 -p 11211 -u memcached
# 詳細オプション指定
memcached \
-d \ # デーモンモード
-m 128 \ # メモリ使用量 (MB)
-p 11211 \ # TCPポート
-U 11211 \ # UDPポート (0で無効化)
-l 127.0.0.1 \ # リスニングアドレス
-u memcached \ # 実行ユーザー
-c 1024 \ # 最大同時接続数
-t 4 \ # ワーカースレッド数
-f 1.25 \ # チャンクサイズ成長因子
-n 48 \ # 最小チャンクサイズ
-v # 詳細ログ
systemd設定 (/etc/systemd/system/memcached.service)
[Unit]
Description=Memcached
After=network.target
[Service]
Type=notify
User=memcached
Group=memcached
ExecStart=/usr/bin/memcached -d -m 128 -p 11211 -u memcached -l 127.0.0.1
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
推奨本番設定
# 高性能設定
memcached \
-d \
-m 512 \
-p 11211 \
-U 0 \ # UDP無効化 (セキュリティ)
-l 127.0.0.1 \
-u memcached \
-c 2048 \
-t 8 \
-o slab_reassign,slab_automove,lru_crawler,lru_maintainer \
-o maxconns_fast,hash_algorithm=murmur3
基本操作
telnetまたはnetcatでの接続
# telnetで接続
telnet localhost 11211
# netcatで接続
nc localhost 11211
基本コマンド
# データの設定
set mykey 0 3600 5
hello
STORED
# データの取得
get mykey
VALUE mykey 0 5
hello
END
# 複数キーの取得
get key1 key2 key3
# データの削除
delete mykey
DELETED
# 全データクリア
flush_all
OK
条件付き操作
# add: キーが存在しない場合のみ設定
add newkey 0 3600 5
world
STORED
# replace: キーが存在する場合のみ置換
replace mykey 0 3600 7
updated
STORED
# append: 既存値の末尾に追加
append mykey 0 3600 6
_value
STORED
# prepend: 既存値の先頭に追加
prepend mykey 0 3600 7
prefix_
STORED
数値操作
# カウンターの設定
set counter 0 0 1
0
STORED
# インクリメント
incr counter 1
1
# デクリメント
decr counter 1
0
# 大きな増減
incr counter 100
100
統計情報とモニタリング
基本統計
# 全般的な統計
stats
STAT pid 12345
STAT uptime 3600
STAT curr_connections 5
STAT total_connections 100
STAT bytes 1024
STAT curr_items 10
STAT total_items 50
STAT evictions 2
STAT hit_ratio 0.85
END
# アイテム統計
stats items
STAT items:1:number 5
STAT items:1:age 1234
STAT items:1:evicted 0
STAT items:1:evicted_nonzero 0
STAT items:1:evicted_time 0
END
# スラブ統計
stats slabs
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 5
STAT 1:free_chunks 10917
STAT 1:get_hits 25
STAT 1:cmd_set 10
END
詳細統計
# 設定値確認
stats settings
STAT maxbytes 67108864
STAT maxconns 1024
STAT tcpport 11211
STAT udpport 11211
STAT verbosity 0
STAT num_threads 4
STAT growth_factor 1.25
STAT chunk_size 48
END
# サイズ分布確認(開発時のみ)
stats sizes
STAT 96 5
STAT 120 2
STAT 152 1
END
クライアント実装例
Python (pymemcache)
from pymemcache.client.base import Client
# 単一サーバー接続
client = Client(('localhost', 11211))
# データ操作
client.set('key', 'value', expire=3600)
result = client.get('key')
client.delete('key')
# 数値操作
client.set('counter', 0)
client.incr('counter', 1)
client.decr('counter', 1)
# バッチ操作
client.set_many({'key1': 'value1', 'key2': 'value2'}, expire=3600)
values = client.get_many(['key1', 'key2'])
Python (分散設定)
from pymemcache.client.hash import HashClient
# 複数サーバー設定
servers = [
('server1', 11211),
('server2', 11211),
('server3', 11211)
]
client = HashClient(servers)
# 自動的に適切なサーバーに分散
client.set('user:1000', user_data)
client.set('session:abc123', session_data)
PHP
<?php
$memcached = new Memcached();
// サーバー追加
$memcached->addServer('localhost', 11211);
$memcached->addServer('server2', 11211);
// データ操作
$memcached->set('key', 'value', 3600);
$value = $memcached->get('key');
$memcached->delete('key');
// バッチ操作
$items = [
'key1' => 'value1',
'key2' => 'value2'
];
$memcached->setMulti($items, 3600);
$values = $memcached->getMulti(['key1', 'key2']);
?>
Node.js (memjs)
const memjs = require('memjs');
// クライアント作成
const client = memjs.Client.create('localhost:11211');
// データ操作
await client.set('key', 'value', {expires: 3600});
const value = await client.get('key');
await client.delete('key');
// 条件付き操作
await client.add('newkey', 'value');
await client.replace('existingkey', 'newvalue');
パフォーマンス最適化
メモリチューニング
# スラブクラス確認
memcached -vv
# slab class 1: chunk size 80 perslab 13107
# slab class 2: chunk size 104 perslab 10082
# ...
# 成長因子調整(デフォルト: 1.25)
memcached -f 1.1 # より細かいスラブクラス
memcached -f 2.0 # より粗いスラブクラス
# 最小チャンクサイズ調整
memcached -n 64 # 64バイトから開始
接続・スレッド最適化
# スレッド数最適化(CPUコア数と同じ)
memcached -t $(nproc)
# 接続数上限調整
memcached -c 4096
# 高速接続処理
memcached -o maxconns_fast
高度な最適化
# LRU機能有効化
memcached -o lru_crawler,lru_maintainer
# スラブ自動管理
memcached -o slab_reassign,slab_automove
# 高性能ハッシュアルゴリズム
memcached -o hash_algorithm=murmur3
# 組み合わせ設定
memcached -o slab_reassign,slab_automove,lru_crawler,lru_maintainer,maxconns_fast,hash_algorithm=murmur3
分散・クラスタリング
クライアントサイド分散
import hashlib
from pymemcache.client.base import Client
class DistributedMemcache:
def __init__(self, servers):
self.servers = [Client(server) for server in servers]
self.server_count = len(self.servers)
def _get_server(self, key):
hash_value = int(hashlib.md5(key.encode()).hexdigest(), 16)
return self.servers[hash_value % self.server_count]
def get(self, key):
server = self._get_server(key)
return server.get(key)
def set(self, key, value, expire=0):
server = self._get_server(key)
return server.set(key, value, expire)
# 使用例
servers = [('server1', 11211), ('server2', 11211), ('server3', 11211)]
cache = DistributedMemcache(servers)
cache.set('user:1000', user_data)
一貫性ハッシュ実装
import bisect
import hashlib
class ConsistentHash:
def __init__(self, servers, replicas=150):
self.replicas = replicas
self.ring = {}
self.sorted_keys = []
for server in servers:
self.add_server(server)
def _hash(self, key):
return int(hashlib.md5(key.encode()).hexdigest(), 16)
def add_server(self, server):
for i in range(self.replicas):
key = self._hash(f"{server}:{i}")
self.ring[key] = server
bisect.insort(self.sorted_keys, key)
def remove_server(self, server):
for i in range(self.replicas):
key = self._hash(f"{server}:{i}")
del self.ring[key]
self.sorted_keys.remove(key)
def get_server(self, key):
if not self.ring:
return None
hash_key = self._hash(key)
idx = bisect.bisect_right(self.sorted_keys, hash_key)
if idx == len(self.sorted_keys):
idx = 0
return self.ring[self.sorted_keys[idx]]
セキュリティ
ネットワークセキュリティ
# ローカルホストのみリスニング
memcached -l 127.0.0.1
# 特定IPのみリスニング
memcached -l 192.168.1.100
# UDP無効化(DDoS対策)
memcached -U 0
# ファイアウォール設定
sudo ufw allow from 192.168.1.0/24 to any port 11211
sudo ufw deny 11211
iptables設定
# 特定サブネットからのみアクセス許可
sudo iptables -A INPUT -p tcp --dport 11211 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 11211 -j DROP
# レート制限
sudo iptables -A INPUT -p tcp --dport 11211 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
監視とメンテナンス
監視スクリプト例
#!/bin/bash
# memcached-monitor.sh
MEMCACHED_HOST="localhost"
MEMCACHED_PORT="11211"
# 接続テスト
if ! echo "version" | nc -w1 $MEMCACHED_HOST $MEMCACHED_PORT > /dev/null 2>&1; then
echo "ERROR: Cannot connect to Memcached"
exit 1
fi
# 統計取得
STATS=$(echo "stats" | nc -w1 $MEMCACHED_HOST $MEMCACHED_PORT)
# ヒット率計算
GET_HITS=$(echo "$STATS" | grep "STAT get_hits" | awk '{print $3}')
GET_MISSES=$(echo "$STATS" | grep "STAT get_misses" | awk '{print $3}')
TOTAL_GETS=$((GET_HITS + GET_MISSES))
if [ $TOTAL_GETS -gt 0 ]; then
HIT_RATE=$(echo "scale=2; $GET_HITS * 100 / $TOTAL_GETS" | bc)
echo "Hit Rate: ${HIT_RATE}%"
fi
# メモリ使用率
BYTES=$(echo "$STATS" | grep "STAT bytes " | awk '{print $3}')
LIMIT_MAXBYTES=$(echo "$STATS" | grep "STAT limit_maxbytes" | awk '{print $3}')
MEMORY_USAGE=$(echo "scale=2; $BYTES * 100 / $LIMIT_MAXBYTES" | bc)
echo "Memory Usage: ${MEMORY_USAGE}%"
# エビクション確認
EVICTIONS=$(echo "$STATS" | grep "STAT evictions" | awk '{print $3}')
echo "Evictions: $EVICTIONS"
自動復旧設定
#!/bin/bash
# memcached-watchdog.sh
MEMCACHED_HOST="localhost"
MEMCACHED_PORT="11211"
MAX_RETRIES=3
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if echo "version" | timeout 5 nc $MEMCACHED_HOST $MEMCACHED_PORT > /dev/null 2>&1; then
echo "Memcached is running"
exit 0
fi
echo "Memcached is not responding, attempting restart..."
sudo systemctl restart memcached
sleep 10
RETRY_COUNT=$((RETRY_COUNT + 1))
done
echo "Failed to restart Memcached after $MAX_RETRIES attempts"
exit 1
ベストプラクティス
キー設計
# 名前空間の使用
user_key = f"user:{user_id}"
session_key = f"session:{session_id}"
cache_key = f"cache:article:{article_id}"
# バージョニング
cache_key = f"v2:user:{user_id}:profile"
# 期限設定の工夫
SHORT_TTL = 300 # 5分
MEDIUM_TTL = 3600 # 1時間
LONG_TTL = 86400 # 24時間
エラーハンドリング
def safe_cache_get(client, key, default=None):
try:
result = client.get(key)
return result if result is not None else default
except Exception as e:
logger.warning(f"Cache get failed for key {key}: {e}")
return default
def safe_cache_set(client, key, value, expire=3600):
try:
return client.set(key, value, expire)
except Exception as e:
logger.warning(f"Cache set failed for key {key}: {e}")
return False
プールド接続
from pymemcache.client.base import PooledClient
# 接続プール使用
client = PooledClient(
('localhost', 11211),
max_pool_size=100,
connect_timeout=5,
timeout=2
)
Memcachedは、そのシンプルさと高性能により、Webアプリケーションのキャッシング層として広く採用されています。適切な設定と運用により、システム全体のパフォーマンスを大幅に向上させることができます。