2012-07-11 73 views
0

我試圖構建一個Java應用程序,它將在Memcached中設置數據,並且有一個PHP腳本在稍後的過程中獲取相同的數據。到目前爲止,我還沒有找到一種獲得100%命中率的方法。爲確保SETs沒有問題,我手動確認數據已添加到Memcached。基於Consistent hashing in PHP and Java,我嘗試使用KETAMA(請參閱下面的代碼),但沒有取得任何成功。Java(spymemcached)和PHP(memcached)

配置:
- Spymemcached(2.8.1)
- PHP(5.3.10)
- PECL/memcached的(2.0.1)
- libmemcached(1.0.4)

會是什麼是在Java和PHP之間共享數據的最佳策略?有沒有我沒有正確使用的配置?我應該使用另一個圖書館嗎?

謝謝你的幫助!


MemcachedClient client = new MemcachedClient 
(ConnectionFactory) new ConnectionFactoryBuilder() 
.setProtocol (Protocol.TEXT) 
.setHashAlg (DefaultHashAlgorithm.KETAMA_HASH) 
.setFailureMode (FailureMode.Redistribute) 
.setLocatorType (Locator.CONSISTENT).build(), 
AddrUtil.getAddresses("192.168.0.101:11211 192.168.0.102:11211")); 

$memcached = new Memcached(); 
$memcached->addserver('192.168.0.101', 11211); 
$memcached->addserver('192.168.0.102', 11211); 
$memcached->setOption(Memcached::OPT_DISTRIBUTION ,Memcached::DISTRIBUTION_CONSISTENT); 
$memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true); 
+0

你用的關鍵是什麼? – DarthVader 2012-07-11 20:13:46

+0

對於我的測試,我使用「test_1」來「test_1000」 – Fretre 2012-07-11 20:26:09

+0

,你是說php客戶端和java客戶端返回一個鍵的不同值? – DarthVader 2012-07-11 20:28:43

回答

0

在spymemcached有一個報道issue與KETAMA散列算法。它指的是版本2.5rc1,但似乎仍然存在。

嘗試另一個Java memcached客戶端:xmemcached

+0

謝謝你的回覆,仍然無法獲得這個工作與xmemcached。 – Fretre 2012-07-12 17:04:03

+0

不幸的是,xmemcached也使用不同的字符串來計算hash比libmemcached。好的新功能是xmemcached具有LibmemcachedMemcachedSessionLocator,所以試試吧。 – ragnor 2012-07-12 17:44:07

0

對於那些想要做同樣事情的人來說,有一個更好的策略。 Twitter提供了twemproxy(胡桃夾子),這是一款快速輕量級的memcached代理。使用它,我不必擔心Java和PHP是否使用相同的散列算法,代理會處理這一點。

0

我也遇到過這個問題。經過許多小時的調查後,我發現這是因爲在PHP和Java memecached客戶端中定義了不同的flags

我用xmemcached使它工作。

首先,創建一個新的StringTranscoder到響應解碼,無視標誌的定義,他們都轉換爲String

/** 
* 
* Php memcached extension uses flags=0 or 1 for all SET values, the default StringTranscoder in Xmemcached uses 0 for string 
* 
*/ 
class PhpStringTranscoder extends PrimitiveTypeTranscoder<String> { 

    private String charset = BaseSerializingTranscoder.DEFAULT_CHARSET; 

    public PhpStringTranscoder(String charset) { 
     this.charset = charset; 
    } 

    public PhpStringTranscoder() { 
     this(BaseSerializingTranscoder.DEFAULT_CHARSET); 
    } 

    public String decode(CachedData d) { 
      String rv = null; 
      try { 
       if (d.getData() != null) { 
        rv = new String(d.getData(), this.charset); 
       } 
      } catch (UnsupportedEncodingException e) { 
       throw new RuntimeException(e); 
      } 
      return rv; 
    } 

    public static final int STRING_FLAG = 1; 

    public CachedData encode(String o) { 
     byte[] b; 
     try { 
      b = o.getBytes(this.charset); 
     } catch (UnsupportedEncodingException e) { 
      throw new RuntimeException(e); 
     } 
     return new CachedData(STRING_FLAG, b); 
    } 

} 

最後,使用這個新PhpStringTranscoder創建會話:

MemcachedClientBuilder builder = new XMemcachedClientBuilder(String.format("%s:%s",address,portNum)); 
    builder.setCommandFactory(new TextCommandFactory()); 
    builder.setTranscoder(new PhpStringTranscoder()); 
    builder.setSessionLocator(new LibmemcachedMemcachedSessionLocator(100, HashAlgorithm.ONE_AT_A_TIME)); 
    MemcachedClient memcachedClient = builder.build(); 

memcachedClient是你應該使用的。