2024 年 PHP 日本會議

Memcache 函式

目錄

新增註釋

使用者貢獻的註釋 13 則註釋

ed at me3inc dot com
18 年前
關於安裝 memcache 擴充功能

我在連接它時遇到了各種麻煩,因為在我閱讀的所有說明中,我從未得到最後也是最重要的一步 - 您必須有一個 php.ini 檔案,並且在其中包含 "extension=memcache.so"。

所以,步驟如下
首先 - 使用 --enable-memcache 進行 ./configure。這應該會顯示在您的 phpinfo() 的頂部(即使 memcache 擴充功能的任何部分都還不能運作)。

第二
使用 pecl install memcache 安裝
或者
下載原始碼
tar -xzvf [thesourcetarball]
phpize
./configure
make
make install

最後:將 extension=memcache.so 新增到您的 php.ini。(如果您沒有 php.ini,它應該放在呼叫 php 的根目錄下,例如 /usr/local/lib)

呼叫 phpinfo(),您應該會看到一個 memcache 區段。
mogmios at gmail dot com
17 年前
當使用非標準位置為 Apache/PHP 安裝 memcache 模組時,似乎在建置配置時無法定義位置。您會收到一個錯誤,抱怨找不到 php_session.h。我修改了 configure 以嘗試 PREFIX 位置,這似乎運作良好。

if test -f "${prefix}/include/php/ext/session/php_session.h"; then
session_inc_path="${prefix}/include/php"
elif test -f "$abs_srcdir/include/php/ext/session/php_session.h"; then
session_inc_path="$abs_srcdir/include/php"
elif test -f "$abs_srcdir/ext/session/php_session.h"; then
session_inc_path="$abs_srcdir"
elif test -f "$phpincludedir/ext/session/php_session.h"; then
session_inc_path="$phpincludedir"
fi
iliya at pisem dot net
18 年前
另一個「智慧型」快取聚合器
https://svn.shadanakar.org/onPHP/ trunk/core/Cache/AggregateCache.class.php
可以與多個快取連接器一起使用 - memcached、檔案系統等。
(請手動移除空格)
Ron
19 年前
這是一個簡單的 memcached 聚合器類別,它在多個快取伺服器之間分配快取。如果伺服器發生故障,負載會自動重新分配。它使用持續連線。

建構函式接受一個陣列的陣列,每個內部陣列代表一個伺服器,具有 'server'(字串)屬性,它是 memcached 伺服器的 IP 位址或主機名稱,以及 'port'(整數)屬性,它是 memcached 在伺服器上執行的埠號。

除了 getStats() 和 getVersion() 之外,所有現有的 memcached API 函式都已實作,它們是伺服器特定的。

<?php
class MemcachedAggregator {
var
$connections;

public function
__construct($servers) {
// Attempt to establish/retrieve persistent connections to all servers.
// If any of them fail, they just don't get put into our list of active
// connections.
$this->connections = array();
for (
$i = 0, $n = count($servers); $i < $n; $i++) {
$server = $servers[$i];
$con = memcache_pconnect($server['host'], $server['port']);
if (!(
$con == false)) {
$this->connections[] = $con;
}
}
}

private function
_getConForKey($key) {
$hashCode = 0;
for (
$i = 0, $len = strlen($key); $i < $len; $i++) {
$hashCode = (int)(($hashCode*33)+ord($key[$i])) & 0x7fffffff;
}
if ((
$ns = count($this->connections)) > 0) {
return
$this->connections[$hashCode%$ns];
}
return
false;
}

public function
debug($on_off) {
$result = false;
for (
$i = 0; $i < count($connections); $i++) {
if (
$this->connections[$i]->debug($on_off)) $result = true;
}
return
$result;
}

public function
flush() {
$result = false;
for (
$i = 0; $i < count($connections); $i++) {
if (
$this->connections[$i]->flush()) $result = true;
}
return
$result;
}

/// The following are not implemented:
///getStats()
///getVersion()

public function get($key) {
if (
is_array($key)) {
$dest = array();
foreach (
$key as $subkey) {
$val = get($subkey);
if (!(
$val === false)) $dest[$subkey] = $val;
}
return
$dest;
} else {
return
$this->_getConForKey($key)->get($key);
}
}

public function
set($key, $var, $compress=0, $expire=0) {
return
$this->_getConForKey($key)->set($key, $var, $compress, $expire);
}

public function
add($key, $var, $compress=0, $expire=0) {
return
$this->_getConForKey($key)->add($key, $var, $compress, $expire);
}

public function
replace($key, $var, $compress=0, $expire=0) {
return
$this->_getConForKey($key)->replace
($key, $var, $compress, $expire);
}

public function
delete($key, $timeout=0) {
return
$this->_getConForKey($key)->delete($key, $timeout);
}

public function
increment($key, $value=1) {
return
$this->_getConForKey($key)->increment($key, $value);
}

public function
decrement($key, $value=1) {
return
$this->_getConForKey($key)->decrement($key, $value);
}

}
?>
dweller at devonweller dot com
15 年前
在 memcache PECL 擴充功能 2.2.5 版中,delete 函式不適用於 memcached 1.4.3。為了因應這個問題,這裡有一個 memcache PECL 擴充功能的版本,其中套用了由 harv at pringo dot com 提供的修補程式

http://code.google.com/p/phpmemcachepatch/downloads/list

安裝方法:下載

http://phpmemcachepatch.googlecode.com/files/memcache-2.2.5b.tgz

然後執行

pecl install memcache-2.2.5b.tgz
restlessmind at I dot gmail dot HATE dot com dot SPAM
16 年前
如果您嘗試在 Windows 系統下為 PHP 5.2 安裝此模組,但它在啟動時無法載入,請確保您已安裝所有依賴項,包括正確執行緒安全版本的 PHP。

我花了幾個小時試圖找出為什麼無法載入 php_memcache.dll,最後在 .dll 檔案上使用了 Dependency Walker(來自 http://www.dependencywalker.com)。這讓我意識到,雖然我使用的是非執行緒安全的 PHP 5.2.5 版本,但 pecl4win 提供的 .dll 需要執行緒安全的 PHP 版本。更正之後,一切正常。
jcastromail at yahoo dot es
17 年前
您好

在 Windows 系統上執行 memcached 的方法:(已在 XP SP2 上使用最新的 php、apache 和 memcache 測試過)

a) 下載 php_memcache.dll,它可以在 pecl 檔案中找到。

b) 將 dll 放入 extension 資料夾(例如 c:/php/extension)。這個資料夾很容易找到,因為裡面都是 php*.dll 檔案。在某些情況下,使用的 extension 資料夾是 system32,這是一種非標準的 dll 放置方式,但仍然有效。

c) 設定 php.ini
; 我把它放在像最新的擴充功能一樣的位置
extension=php_memcache.dll

; 我不確定這樣做是否有必要,但應該無害。
[Memcache]
memcache.allow_failover = 1
memcache.max_failover_attempts=20
memcache.chunk_size =8192
memcache.default_port = 11211

d) 這一點很重要,memcached 與一個外部服務一起運作。在使用 memcache 之前,必須先下載並安裝此服務。我使用:http://jehiah.cz/projects/memcached-win32/

e) 記得安裝服務並啟動服務。使用 memcached.exe -d install 進行安裝,並執行 services.msc 來啟動 memcached 服務(或重新啟動系統)。

f) 檢查防火牆連接埠。

最後重新啟動 apache/iis 並執行一些測試。至少在 phpinfo 中必須顯示一些關於 memcache 的資訊。

最後說明:memcache 的「驚人之處」不僅在於它可以幫助加速某些流程(或減少 CPU 使用率),還可以像全域工作階段一樣用於儲存整個物件,而且這個「全域工作階段」可以在所有使用者之間共用,就像 ASP 中的 APPLICATION 一樣。因此(例如)可以製作一個使用者計數器,而不需要資料庫或寫入檔案。
gil at squidoo dot com
17 年前
Aggregator 類別的 flush() 函式中有一個小錯誤。對 $connections 的引用應該是 $this->connections。



public function flush() {
$result = false;
for ($i = 0; $i < count($connections); $i++) {
if ($this->connections[$i]->flush()) {
$result = true;
}
}
return $result;
}

改為

public function flush() {
$result = false;
for ($i = 0; $i < count($this->connections); $i++) {
if ($this->connections[$i]->flush()) {
$result = true;
}
}
return $result;
}
markfrawley at gmail dot com
17 年前
這是上述 MemcacheAggregator 類別的 PHP4 回溯移植版本。

<?php
class MemcachedAggregator {
var
$connections;
var
$_servers;

function
MemcachedAggregator($servers) {
$this->_servers = $servers;
// Attempt to establish/retrieve persistent connections to all servers.
// If any of them fail, they just don't get put into our list of active
// connections.
$this->connections = array();
for (
$i = 0, $n = count($servers); $i < $n; $i++) {
$server = $servers[$i];
$con = memcache_connect($server['host']);
//memcache_debug(1);
//$memcache = &new Memcache;
//$con = $memcache->connect($server['host']);
if (!($con == false)) {
$this->connections[] = &$con;
}

}
}

function
_getConForKey($key) {
$hashCode = 0;
for (
$i = 0, $len = strlen($key); $i < $len; $i++) {
$hashCode = (int)(($hashCode*33)+ord($key[$i])) & 0x7fffffff;
}
if ((
$ns = count($this->connections)) > 0) {
return
$this->connections[$hashCode%$ns];
//return $this->connections[0];
}
return
false;
}

function
debug($on_off) {
$result = false;
for (
$i = 0; $i < count($this->connections); $i++) {
if (
$this->connections[$i]->debug($on_off)) $result = true;
}
return
$result;
}

function
flush() {
$result = false;
for (
$i = 0; $i < count($this->connections); $i++) {
if (
$this->connections[$i]->flush()) $result = true;
}
return
$result;
}

/// The following are not implemented:
///getStats()
///getVersion()

function get($key) {
if (
is_array($key)) {
$dest = array();
foreach (
$key as $subkey) {
$val = get($subkey);
if (!(
$val === false)) $dest[$subkey] = $val;
}
return
$dest;
} else {
$conn = &$this->_getConForKey($key);
return
$conn->get($key);
}
}

function
set($key, $var, $compress=0, $expire=0) {
$conn = &$this->_getConForKey($key);
return
$conn->set($key, $var, $compress, $expire);
}

function
add($key, $var, $compress=0, $expire=0) {
$conn = &$this->_getConForKey($key);
return
$conn->add($key, $var, $compress, $expire);
}

function
replace($key, $var, $compress=0, $expire=0) {
$conn = &$this->_getConForKey($key);
return
$conn->replace($key, $var, $compress, $expire);
}

function
delete($key, $timeout=0) {
$conn = &$this->_getConForKey($key);
return
$conn->delete($key, $timeout);
}

function
increment($key, $value=1) {
$conn = &$this->_getConForKey($key);
return
$conn->increment($key, $value);
}

function
decrement($key, $value=1) {
$conn = &$this->_getConForKey($key);
return
$conn->decrement($key, $value);
}

function
showStats($server=null) {
$stats_out = '';
if(
$server == null) {
$i=0;
foreach(
$this->connections as $conn) {
$server = $this->_servers[$i];
$stats_array = memcache_get_stats($conn);
$stats_out .= "</br><b>Server: ".$server['host'].": </b><br/>";
foreach(
$stats_array as $key => $val) {
$stats_out .= "$key => $val <br/>";
}
$i++;
}
}
return
$stats_out;
}
}
?>
moazzamk at gmail dot com
17 年前
如果您要繼承 memcache 類別,則不能在類別的建構函式中呼叫 parent::__construct()。但是,不執行建構函式仍然會初始化它,並且可以正常運作。

<?php

// 錯誤

class a extends Memcache {
function
__construct($host, $port)
{
parent::__construct();
$this->connect($host, $port);
}

//正確
class a extends Memcache {
function
__construct($host, $port)
{
parent::__construct();
$this->connect($host, $port);
}

?>

我猜這適用於所有原生/PECL 類別。
Ron
19 年前
以上內容的改進

如果所有快取伺服器都關閉,上述類別將會導致錯誤。較佳的做法是只產生快取未命中(或在寫入操作的情況下不採取任何動作)並返回 false,以便應用程式可以在所有快取伺服器都關閉時以非快取模式運行。

要實現這一點,只需在每個受影響的函式中將連線用法更改為類似以下內容。此程式碼適用於 get() 函式

$con = $this->_getConForKey($key);
if ($con === false) return false;
return $con->get($key);

同樣,set() 函式中受影響的程式碼如下所示
$con = $this->_getConForKey($key);
if ($con === false) return false;
return $con->set($key, $var, $compress, $expire);

相應地修改每個函式,即使所有快取伺服器都關閉,您仍然可以正常運作(儘管由於 100% 的快取未命中率而速度較慢)。
contact at codeassembly dot com
16 年前
請注意,沒有辦法擁有您自己的雜湊機制,將一組物件分組到伺服器的最佳方法是手動選擇要使用的伺服器。

我想將特定使用者的所有物件保留在同一伺服器上。

user_54_description
user_54_info
user_54_comments
user_54_etc
.
.

如果我將所有這些物件放在同一伺服器上,我只需呼叫一次 memcache -> get (get_multi) 即可取得所有資料,因此可以大幅提高效能。

我的做法是將使用者/物件 ID 雜湊到伺服器數量。

<?php
$memcache_hosts
= array
(
'192.168.1.1',
'192.168.1.2',
'192.168.1.3',
'192.168.1.4',
'192.168.1.5',
);

$server = $id % count($memcache_hosts);

$memcache = new Memcache;
$memcache->connect($memcache_hosts[$server], 11211);

//在此處取得或設定您的物件
?>

您可以將不想分組的其他物件留給 memcache 擴充功能進行雜湊並選擇適當的伺服器。
Colin Guthrie
17 年前
我發現了一個錯誤/文件錯誤

以上文件關於 session.save_path 參數的說明如下
每個網址都可能包含應用於該伺服器的參數,它們與 Memcache::addServer() 方法的參數相同。

addServer 方法的說明文件指出:
「連接埠 (port)

指向 memcached 監聽連線的連接埠。此參數是選用的,預設值為 11211。使用 UNIX 域套接字時,請將此參數設定為 0。」

然而,在指定 save_path 時,我發現在使用 PHP 5.2.3 和 memcache 2.1.2 的情況下,連接埠是字串的*必要*部分。

希望這能幫助一些正在苦惱的人。
To Top