MemcacheQ 是基於 Memcached 協議的持久化消息隊列,底層依賴 Berkeley DB 存儲、Libevent 事件驅動,適合異步任務處理、日誌收集、訂單隊列等場景。本文提供從依賴編譯到生產部署的完整標準化流程。
MemcacheQ
├── Libevent (≥ 2.0) ── 事件通知庫(非阻塞 IO)
└── Berkeley DB (≥ 5.x) ── 持久化存儲引擎(B-tree/Hash/Queue)
# 下載穩定版
wget https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz
tar xzf libevent-2.1.12-stable.tar.gz
cd libevent-2.1.12-stable
./configure --prefix=/usr/local/libevent
make -j$(nproc)
make install
# 註冊庫路徑
echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
ldconfig
# Oracle 官方下載(需登錄)或使用發行版包
# yum install -y libdb-devel # CentOS/RHEL
# apt-get install -y libdb-dev # Debian/Ubuntu
# 或源碼編譯(指定版本)
wget https://download.oracle.com/otn/berkeley-db/db-6.2.32.tar.gz
tar xzf db-6.2.32.tar.gz
cd db-6.2.32/build_unix
../dist/configure --prefix=/usr/local/berkeleydb --enable-cxx
make -j$(nproc)
make install
# 創建软链接供編譯器查找
ln -sf /usr/local/berkeleydb/lib/libdb-6.2.so /usr/lib/
echo "/usr/local/berkeleydb/lib" > /etc/ld.so.conf.d/berkeleydb.conf
ldconfig
# 克隆活躍分支(原版久未更新)
git clone https://github.com/stvchu/memcacheq.git
cd memcacheq
# 或下載發布版
# wget https://github.com/stvchu/memcacheq/archive/refs/tags/v0.2.0.tar.gz
./configure --prefix=/usr/local/memcacheq \
--with-bdb=/usr/local/berkeleydb \
--with-libevent=/usr/local/libevent \
--enable-threads \
--enable-queue
make -j$(nproc)
make install
/usr/local/memcacheq/bin/memcacheq \
-d # 守護進程模式
-u memcacheq # 運行用戶(需預先創建)
-r # 最大化核心文件限制
-l 127.0.0.1 # 監聽地址(內網 IP 或 0.0.0.0)
-p 11211 # TCP 端口(避開 Memcached 默認 11211)
-U 0 # 禁用 UDP
-H /data/memcacheq # 隊列數據存儲目錄(須預創建、寫權限)
-N # 不同步刷盤(高性能,風險自負)
-R # 允許原始協議命令
-v # 詳細日誌
-L 1024 # 最大隊列長度(內存中)
-B 1024 # 批量刷盤閾值
>> /var/log/memcacheq.log 2>&1 &
| 參數 | 說明 | 建議值 |
|---|---|---|
-p | TCP 監聽端口 | 11211(避開 Memcached) |
-U | UDP 端口(0=禁用) | 0(安全) |
-H | 隊列數據目錄(Berkeley DB 環境) | /data/memcacheq(獨立分區、SSD) |
-N | 異步刷盤(不 fsync) | 高吞吐場景啟用,掉電丟數據 |
-L | 內存中最大隊列項數 | 1024-10000(視內存而定) |
-B | 批量寫入閾值 | 1024(平衡延遲/吞吐) |
-t | 工作線程數 | CPU 核心數 |
-c | 最大並發連接 | 1024-65535 |
[Unit]
Description=MemcacheQ Message Queue
After=network.target local-fs.target
Wants=network.target
[Service]
Type=forking
User=memcacheq
Group=memcacheq
Environment=MEMCACHEQ_HOME=/usr/local/memcacheq
Environment=MEMCACHEQ_DATA=/data/memcacheq
ExecStartPre=/bin/mkdir -p ${MEMCACHEQ_DATA}
ExecStartPre=/bin/chown memcacheq:memcacheq ${MEMCACHEQ_DATA}
ExecStart=${MEMCACHEQ_HOME}/bin/memcacheq \
-d -u memcacheq -r \
-l 0.0.0.0 -p 11211 -U 0 \
-H ${MEMCACHEQ_DATA} -N -R -v \
-L 4096 -B 1024 -t 4
ExecStop=${MEMCACHEQ_HOME}/bin/memcacheq -p 11211 -k
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
LimitMEMLOCK=infinity
[Install]
WantedBy=multi-user.target
# 創建用戶與目錄
useradd -r -s /sbin/nologin -d /data/memcacheq memcacheq
mkdir -p /data/memcacheq
chown memcacheq:memcacheq /data/memcacheq
# 部署服務
systemctl daemon-reload
systemctl enable --now memcacheq
systemctl status memcacheq
addServer('127.0.0.1', 11211);
// 入隊:使用同一 key 多次 set 模擬隊列推入
for ($i = 1; $i <= 5; $i++) {
$mq->set('queue_key', "message_$i", 0, 0); // flag=0, expire=0
echo "Pushed: message_$i\n";
usleep(100000);
}
// 出隊:反覆 get 同一 key
for ($i = 1; $i <= 6; $i++) {
$val = $mq->get('queue_key');
if ($val === false) {
echo "Queue empty (null)\n";
} else {
echo "Popped: $val\n";
}
usleep(50000);
}
$mq->quit();
?>
php test_memcacheq.php
# 預期輸出:
# Pushed: message_1 ... message_5
# Popped: message_1 ... message_5
# Popped: Queue empty (null)
# Telnet 方式
echo "stats" | nc 127.0.0.1 11211
# 關鍵指標
# queue_total_items: 總隊列項數
# queue_bytes: 佔用字節
# curr_connections: 當前連接數
# total_connections: 總連接數
# cmd_get/cmd_set: 吞吐統計
# 熱備份(Berkeley DB 支持熱備份)
/usr/local/berkeleydb/bin/db_hotbackup -h /data/memcacheq -b /backup/memcacheq_$(date +%F)
# 恢復:停止服務 -> 替換目錄 -> 啟動
| 現象 | 原因 | 解決 |
|---|---|---|
啟動報 libdb not found | 庫路徑未註冊 | ldconfig、檢查 ld.so.conf.d |
| 隊列數據不持久化 | 未指定 -H 或目錄權限錯誤 | 檢查目錄擁有者、啟動參數 |
| 內存增長不釋放 | -L 過大或未消費 | 調整 -L、檢查消費端 |
| 并發性能差 | 單線程/鎖競爭 | 啟用 --enable-threads、增加 -t |
MemcacheQ 以 Memcached 協議為介面、Berkeley DB 為存儲,實現了「零學習成本」的持久化隊列。生產部署關鍵在:**獨立數據目錄(SSD)、合理調優 -L/-B/-t、systemd 托管、監告警覆蓋**。大規模場景建議遷移至 Redis Streams、Kafka、RabbitMQ 等成熟消息中間件。