Memcached

キャッシュライブラリ分散キャッシュ高速軽量シンプル

GitHub概要

linsomniac/python-memcached

A python memcached client library.

スター467
ウォッチ21
フォーク201
作成日:2013年3月27日
言語:Python
ライセンス:-

トピックス

なし

スター履歴

linsomniac/python-memcached Star History
データ取得日時: 2025/10/22 08:07

ライブラリ

Memcached

概要

Memcachedは高速分散メモリオブジェクトキャッシュシステムです。シンプルなkey-valueストレージによる軽量キャッシュ実装で、マルチスレッド設計により高スループットを実現し、動的Webアプリケーションのデータベース負荷軽減に特化しています。2025年において高スループット文字列キャッシュの分野でRedisと双璧をなす存在として、シンプルさとパフォーマンスを重視する環境、特に大規模Webサービスで継続的に選択されています。

詳細

Memcached 1.6系列は2025年現在も活発に開発されており、TLS暗号化サポート、プロキシ機能、ホットキー検出、slab自動再配分機能を搭載。マルチスレッド設計により複数CPUコアを効率的に活用し、特に大きなデータセットの保存・管理でRedisを上回る性能を発揮。外部依存なしの純粋なキャッシュソリューションとして、最大限のシンプルさと予測可能性を提供します。一時的なデータ保存に特化し、永続化機能は持たないため軽量でメモリ効率的な運用が可能。

主な特徴

  • マルチスレッド設計: 複数CPUコアの効率的活用による高いスループット
  • シンプルなプロトコル: テキストベースの簡潔なコマンド体系
  • 水平スケーリング: クライアント側ハッシュによる分散配置
  • メモリ効率: slabアロケーターによる効率的なメモリ管理
  • 高い安定性: 10年以上の本番運用実績
  • 軽量実装: 最小限の機能セットと低リソース消費

メリット・デメリット

メリット

  • Redisに匹敵するサブミリ秒応答時間の高性能
  • マルチスレッドによる大規模データセットでの優位性
  • 設定とメンテナンスが極めて簡単
  • メモリ使用量の予測が容易(key-valueのみ)
  • 軽量で安定した運用が可能
  • 豊富なクライアントライブラリとフレームワーク統合

デメリット

  • データ永続化機能なし(サーバー再起動でデータ消失)
  • 複雑なデータ構造サポートなし(文字列のみ)
  • クラスタリング・レプリケーション機能の欠如
  • 高可用性機能が限定的(フェイルオーバー不可)
  • パブリッシュ/サブスクライブ機能なし
  • 原子的操作の制限(インクリメント・デクリメント程度)

参考ページ

書き方の例

インストールとセットアップ

# Ubuntu/Debian でのインストール
sudo apt update
sudo apt install memcached

# CentOS/RHEL でのインストール
sudo yum install memcached

# Docker での起動
docker run --name memcached-server -p 11211:11211 -d memcached:1.6

# サービス起動と確認
sudo systemctl start memcached
sudo systemctl enable memcached
sudo systemctl status memcached

# 設定ファイル確認
cat /etc/memcached.conf

基本的なキャッシュ操作

# telnet で接続テスト
telnet localhost 11211

# 基本的な SET/GET 操作
set user_name 0 3600 4
john
STORED

get user_name
VALUE user_name 0 4
john
END

# 数値のインクリメント/デクリメント
set counter 0 0 1
0
STORED

incr counter 5
5

decr counter 2
3

# 複数キー取得
set key1 0 3600 6
value1
STORED

set key2 0 3600 6  
value2
STORED

get key1 key2
VALUE key1 0 6
value1
VALUE key2 0 6
value2
END

クライアントライブラリの使用(Python)

import memcache

# サーバー接続
mc = memcache.Client(['127.0.0.1:11211'], debug=0)

# 基本的なキャッシュ操作
mc.set("user:1", "John Doe", time=3600)
user = mc.get("user:1")
print(user)  # "John Doe"

# 複数キー操作
mc.set_multi({
    "user:1": "John Doe",
    "user:2": "Jane Smith", 
    "user:3": "Bob Johnson"
}, time=3600)

users = mc.get_multi(["user:1", "user:2", "user:3"])
print(users)  # {'user:1': 'John Doe', 'user:2': 'Jane Smith', 'user:3': 'Bob Johnson'}

# 条件付き更新(CAS)
mc.set("inventory_count", 100)
gets_result = mc.gets("inventory_count")
if gets_result:
    # CAS (Compare And Swap)
    success = mc.cas("inventory_count", 95)
    print(f"CAS Success: {success}")

# TTL 確認と削除
mc.set("temp_data", "temporary", time=60)
mc.delete("temp_data")

# 統計情報取得
stats = mc.get_stats()
print(stats)

Node.js でのキャッシュ実装

const memjs = require('memjs');

// サーバー接続
const client = memjs.Client.create('localhost:11211');

// Promise ベースの操作
async function cacheOperations() {
    try {
        // データ設定
        await client.set('session:abc123', 'user_data', {expires: 3600});
        
        // データ取得
        const result = await client.get('session:abc123');
        if (result.value) {
            console.log('Cached data:', result.value.toString());
        }
        
        // 複数操作
        await Promise.all([
            client.set('key1', 'value1', {expires: 1800}),
            client.set('key2', 'value2', {expires: 1800}),
            client.set('key3', 'value3', {expires: 1800})
        ]);
        
        // インクリメント
        await client.set('view_count', '100');
        const newCount = await client.increment('view_count', 1);
        console.log('New view count:', newCount.value?.toString());
        
        // 削除
        await client.delete('session:abc123');
        
    } catch (error) {
        console.error('Cache error:', error);
    } finally {
        client.close();
    }
}

cacheOperations();

分散Memcachedクラスター

import memcache
import hashlib

# 複数サーバーでの分散設定
servers = [
    '192.168.1.10:11211',
    '192.168.1.11:11211', 
    '192.168.1.12:11211'
]

mc = memcache.Client(servers, debug=0)

# 一貫性ハッシュによる分散
def get_server_for_key(key, servers):
    hash_value = int(hashlib.md5(key.encode()).hexdigest(), 16)
    return servers[hash_value % len(servers)]

# ラウンドロビンによる負荷分散
class DistributedMemcache:
    def __init__(self, servers):
        self.servers = servers
        self.clients = {
            server: memcache.Client([server]) 
            for server in servers
        }
    
    def _get_client(self, key):
        server = get_server_for_key(key, self.servers)
        return self.clients[server]
    
    def set(self, key, value, time=0):
        client = self._get_client(key)
        return client.set(key, value, time)
    
    def get(self, key):
        client = self._get_client(key)
        return client.get(key)
    
    def delete(self, key):
        client = self._get_client(key)
        return client.delete(key)

# 使用例
distributed_cache = DistributedMemcache(servers)
distributed_cache.set("user:1000", "John Doe", time=3600)
user_data = distributed_cache.get("user:1000")

セッション管理の実装

<?php
// PHP でのセッション管理
class MemcachedSessionHandler {
    private $memcached;
    private $ttl = 3600; // 1時間
    
    public function __construct($servers) {
        $this->memcached = new Memcached();
        $this->memcached->addServers($servers);
    }
    
    public function read($session_id) {
        $data = $this->memcached->get("session:$session_id");
        return $data === false ? '' : $data;
    }
    
    public function write($session_id, $data) {
        return $this->memcached->set("session:$session_id", $data, $this->ttl);
    }
    
    public function destroy($session_id) {
        return $this->memcached->delete("session:$session_id");
    }
    
    public function gc($maxlifetime) {
        // Memcached は TTL で自動的に期限切れデータを削除
        return true;
    }
}

// セッションハンドラー登録
$servers = [
    ['localhost', 11211],
    ['192.168.1.20', 11211]
];

$handler = new MemcachedSessionHandler($servers);
session_set_save_handler($handler, true);

// セッション開始
session_start();
$_SESSION['user_id'] = 1234;
$_SESSION['username'] = 'john_doe';
?>

監視とパフォーマンス最適化

# 統計情報の確認
echo "stats" | nc localhost 11211

# 重要な統計項目
# curr_connections: 現在の接続数
# get_hits: ヒット数
# get_misses: ミス数  
# hit_ratio: ヒット率 = hits/(hits+misses)

# slab 情報の確認(メモリ使用状況)
echo "stats slabs" | nc localhost 11211

# アイテム情報の確認
echo "stats items" | nc localhost 11211

# パフォーマンス監視スクリプト
#!/bin/bash
while true; do
    echo "=== Memcached Stats $(date) ==="
    echo "stats" | nc localhost 11211 | grep -E "(get_hits|get_misses|curr_connections|bytes)"
    echo ""
    sleep 10
done