『壹』 如何配置Memcached伺服器
Windows下的Memcache安裝
1. 下載memcache的windows穩定版,解壓放某個盤下面,比如在c:\memcached
2. 在終端(也即cmd命令界面)下輸入 c:\memcached\memcached.exe -d install --安裝memcached成為服務,這樣才能正常運行,否則運行失敗!
3. 再輸入: c:\memcached\memcached.exe -d start --啟動memcached的。
以後memcached將作為windows的一個服務每次開機時自動啟動。這樣伺服器端已經安裝完畢了。
linux下的安裝:
1.下載memcached和libevent,放到 /tmp 目錄下
# cd /tmp
# wget http://www.danga.com/memcached/dist/memcached-1.2.0.tar.gz
# wget http://www.monkey.org/~provos/libevent-1.2.tar.gz
2.先安裝libevent:
# tar zxvf libevent-1.2.tar.gz
# cd libevent-1.2
# ./configure –prefix=/usr
# make
# make install
3.測試libevent是否安裝成功:
# ls -al /usr/lib | grep libevent
lrwxrwxrwx 1 root root 21 11?? 12 17:38 libevent-1.2.so.1 -> libevent-1.2.so.1.0.3
-rwxr-xr-x 1 root root 263546 11?? 12 17:38 libevent-1.2.so.1.0.3
-rw-r–r– 1 root root 454156 11?? 12 17:38 libevent.a
-rwxr-xr-x 1 root root 811 11?? 12 17:38 libevent.la
lrwxrwxrwx 1 root root 21 11?? 12 17:38 libevent.so -> libevent-1.2.so.1.0.3
4.安裝memcached,同時需要安裝中指定libevent的安裝位置:
# cd /tmp
# tar zxvf memcached-1.2.0.tar.gz
# cd memcached-1.2.0
# ./configure –with-libevent=/usr
# make
# make install
如果中間出現報錯,請仔細檢查錯誤信息,按照錯誤信息來配置或者增加相應的庫或者路徑。
安裝完成後會把memcached放到 /usr/local/bin/memcached ,
5.測試是否成功安裝memcached:
# ls -al /usr/local/bin/mem*
-rwxr-xr-x 1 root root 137986 11?? 12 17:39 /usr/local/bin/memcached
-rwxr-xr-x 1 root root 140179 11?? 12 17:39 /usr/local/bin/memcached-debug
memcached的基本設置:
1.啟動Memcache的伺服器端:
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.0.200 -p 12000 -c 256 -P /tmp/memcached.pid
-d選項是啟動一個守護進程,
-m是分配給Memcache使用的內存數量,單位是MB,這里是10MB,
-u是運行Memcache的用戶,這里是root,
-l是監聽的伺服器IP地址,如果有多個地址的話,這里指定了伺服器的IP地址192.168.0.200,
-p是設置Memcache監聽的埠,這里設置了12000,最好是1024以上的埠,
-c選項是最大運行的並發連接數,默認是1024,這里設置了256,按照你伺服器的負載量來設定,
-P是設置保存Memcache的pid文件,這里是保存在 /tmp/memcached.pid,
2.如果要結束Memcache進程,執行:
# kill `cat /tmp/memcached.pid`
也可以啟動多個守護進程,不過埠不能重復。
3.重啟apache,service httpd restart
java的客戶端連接程序:
將java_memcached-release_1.6.zip解壓後的目錄中的java_memcached-release_2.0.jar文件復制到java項目的lib目錄下。
package utils.cache;
import java.util.Date;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
/**
* 使用memcached的緩存實用類.
*/
public class MemCached
{
// 創建全局的唯一實例
protected static MemCachedClient mcc = new MemCachedClient();
protected static MemCached memCached = new MemCached();
// 設置與緩存伺服器的連接池
static {
// 伺服器列表和其權重
String[] servers = {"127.0.0.1:11211"};
Integer[] weights = {3};
// 獲取socke連接池的實例對象
SockIOPool sockIOPool = SockIOPool.getInstance();
// 設置伺服器信息
sockIOPool.setServers( servers );
sockIOPool.setWeights( weights );
// 設置初始連接數、最小和最大連接數以及最大處理時間
sockIOPool.setInitConn( 5 );
sockIOPool.setMinConn( 5 );
sockIOPool.setMaxConn( 250 );
sockIOPool.setMaxIdle( 1000 * 60 * 60 * 6 );
// 設置主線程的睡眠時間
sockIOPool.setMaintSleep( 30 );
// 設置TCP的參數,連接超時等
sockIOPool.setNagle( false );
sockIOPool.setSocketTO( 3000 );
sockIOPool.setSocketConnectTO( 0 );
//sockIOPool.setFailover(bFailover);
//sockIOPool.setAliveCheck(bAliveCheck);
// 初始化連接池
sockIOPool.initialize();
// 壓縮設置,超過指定大小(單位為K)的數據都會被壓縮
if (memCachedClient == null)
{
mcc = new MemCachedClient(sPoolName);
mcc.setCompressEnable(true);
mcc.setCompressThreshold(4096);
mcc.setPrimitiveAsString(true);
}
}
/*
<h3>基於Spring的配置,如下:</h3>
<pre>
<bean id="memCachedService" class="com.ms.memcached.MemCachedServiceImpl">
<constructor-arg index="0" value="${memcached.pool.name}" />
<constructor-arg index="1" value="${memcached.pool.servers}" />
<constructor-arg index="2" value="${memcached.pool.initConn}" />
<constructor-arg index="3" value="${memcached.pool.maxConn}" />
<constructor-arg index="4" value="${memcached.pool.minConn}" />
<constructor-arg index="5" value="${memcached.pool.socketTO}" />
<constructor-arg index="6" value="${memcached.pool.maintSleep}" />
<constructor-arg index="7" value="${memcached.pool.nagle}" />
<constructor-arg index="8" value="${memcached.pool.failover}" />
<constructor-arg index="9" value="${memcached.pool.aliveCheck}" />
</bean>
</pre>
<h3>利用com.MS.cache.properties來設置參數,如下:</h3>
<pre>
memcached.pool.name = MS
memcached.pool.servers = 192.168.9.132:12000,192.168.9.133:12000
memcached.pool.initConn = 128
memcached.pool.maxConn = 1024
memcached.pool.minConn = 20
memcached.pool.socketTO = 3000
memcached.pool.maintSleep = 30
memcached.pool.nagle = false
memcached.pool.failover = true
memcached.pool.aliveCheck = true
</pre>
*/
/**
* 保護型構造方法,不允許實例化!
*/
protected MemCached()
{
}
/**
* 獲取唯一實例.
*/
public static MemCached getInstance()
{
return memCached;
}
/**
* 添加一個指定的值到緩存中.
* @param key
* @param value
*/
//新增指定key的緩存內容,但不覆蓋已存在的內容。
public boolean add(String key, Object value)
{
return mcc.add(key, value);
}
//expiry過期時間
public boolean add(String key, Object value, Date expiry)
{
return mcc.add(key, value, expiry);
}
//新增或覆蓋指定Key的緩存內容
public boolean set(String key, Object value)
{
return mcc.set(key, value);
}
//lExpiry過期時間
public boolean set(String key, Object value, long lExpiry)
{
return mcc.set(key, value, new Date(lExpiry));
}
//根據指定的Key獲取緩存內容
public boolean get(String key)
{
return mcc.get(key);
}
//根據指定Key更新緩存內容
public boolean replace(String key, Object value)
{
return mcc.replace(key, value);
}
//lExpiry 指定的時間
public boolean replace(String key, Object value, long lExpiry)
{
return mcc.replace(key, value, new Date(lExpiry));
}
//根據指定Key刪除緩存內容
public boolean delete(String key, Object value)
{
return mcc.delete(key, value);
}
//根據指定Key在指定時間後刪除緩存內容
public boolean delete(String key, Object value, long lExpiry)
{
return mcc.delete(key, value, new Date(lExpiry));
}
//檢測Cache中當前Key是否存在
public boolean exists(String key)
{
return mcc.exists(key);
}
//根據指定一批Key批量獲取緩存內容。
/*
* @param sKeys 指定的一批Key。
* @return Object[oValue]
*/
public Object[] getMultiArray(String[] sKeys) throws ServiceException
{
return memCachedClient.getMultiArray(sKeys);
}
/**
* 根據指定一批Key批量獲取緩存內容。
*
* @param sKeys 指定的一批Key。
* @return Map<sKey, oValue>
*/
public Map<String, Object> getMulti(String[] sKeys) throws ServiceException
{
return memCachedClient.getMulti(sKeys);
}
public static void main(String[] args)
{
MemCached memCached= MemCached.getInstance();
memCached.add("hello", 234);
System.out.print("get value : " + memCached.get("hello"));
}
}
那麼我們就可以通過簡單的像main方法中操作的一樣存入一個變數,然後再取出進行查看,我們可以看到先調用了add,然後再進行get,我們運行一次 後,234這個值已經被我們存入了memcached的緩存中的了,我們將main方法中紅色的那一行注釋掉後,我們再運行還是可以看到get到的 value也是234,即緩存中我們已經存在了數據了。
對基本的數據我們可以操作,對於普通的POJO而言,如果要進行存儲的話,那麼比如讓其實現java.io.Serializable介面,因為 memcached是一個分布式的緩存伺服器,多台伺服器間進行數據共享需要將對象序列化的,所以必須實現該介面,否則會報錯的。
Entity
/**
* 獲取當前實體的緩存Id
*
* @return
*/
public String getCacheId()
{
return getCacheId(this.getClass(), sBreedId);
}
get
public Breed getBreedById(String sBreedId) throws ServiceException
{
Breed breed = (Breed)memCachedService.get(getCacheId(Breed.class, sBreedId));
if(breed == null)
{
breed = service.get("breed.getBreedById", sBreedId);
if(breed != null)
{
memCachedService.set(breed.getBreedId(), breed);
}
}
return breed;
}
save
memCachedService.set(spider.getCacheId(), breed);
update
memCachedService.replace(spider.getCacheId(), breed);
remove
memCachedService.delete(getCacheId(Spider.class, IbreedId));
或
memCachedService.delete(breed.getCacheId());
listAll
public List listAll() throws ServiceException
{
List breeds = new ArrayList ();
List breedIds = (List)memCachedService.get(getKeyByMap("Breed", null));
if(ObjectUtils.isEmpty(breedIds))
{
breeds = service.list("breed.getAllBreed", null);
if (!ObjectUtils.isEmpty(breeds))
{
breedIds = new ArrayList();
for (Breed breed : breeds)
{
breedIds.add(breed.getBreedId());
}
memCachedService.set(getKeyByMap("Breed", null), breedIds);
}
}
else
{
for (String sBreedId : breedIds)
{
Breed breed = getBreedById(sBreedId);
if (breed != null)
{
breeds.add(breed);
}
}
}
return breeds;
}
『貳』 怎樣用MemCached存儲自己創建的對象
各種監控設備開啟時候需要進行注冊(就像手機開機時總是要找個基站注冊一樣,或類似互聯網站的登錄操作),設備數量為千至萬的級別,他們注冊到不同的「基站」中,由基站再統一連接到中心伺服器上(java程序,協議為http based,多台集群布屬)。注冊要牽扯到不少表/對象,不僅僅只是設備對象,而且系統要求設備注冊要非常快。設備運行時,總是不時會發生各種安全報警、故障報警、狀態報警發送到「基站」,由「基站」轉發到中控伺服器。發生報警時候,若有預設預案,則設備按照該預案執行響應。預案是操作員事前在中控伺服器上定製,在設備注冊時返回給設備的。還有一部分操作員,就是整天盯著監控客戶端,實時人工處理警報,同時他們還會處理一些小量請求,比如偶爾調整一下設備基本信息(如GIS信息),增加一個設備,增加一個用戶,注釋一下各種報警事件等等。
『叄』 你使用過 Memcache 緩存嗎如果使用過,能夠簡單的描述一下它的工作原理嗎
首先 memcached 是以守護程序方式運行於一個或多個伺服器中,隨時接受客戶端的連接操作,客戶端可以由各種語言編寫,目前已知的客戶端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。PHP 等客戶端在與 memcached 服務建立連接之後,接下來的事情就是存取對象了,每個被存取的對象都有一個唯一的標識符 key,存取操作均通過這個 key 進行,保存到 memcached 中的對象實際上是放置內存中的,並不是保存在 cache 文件中的,這也是為什麼PHP內存緩存技術memcached 能夠如此高效快速的原因。注意,這些對象並不是持久的,服務停止之後,里邊的數據就會丟失。
『肆』 Memcached 在 Spring 里怎麼用
本文將對在Java環境下Memcached應用進行詳細介紹。Memcached主要是集群環境下的緩存解決方案,可以運行在Java或者.NET平台上,這里我們主要講的是Windows下的Memcached應用。
這些天在設計SNA的架構,接觸了一些遠程緩存、集群、session復制等的東西,以前做企業應用的時候感覺作用不大,現在設計面對internet的系統架構時就非常有用了,而且在調試後看到壓力測試的情況還是比較好的。
在緩存的選擇上有過很多的思考,雖然說memcached結合java在序列化上性能不怎麼樣,不過也沒有更好的集群環境下的緩存解決方案了,就選擇了memcached。本來計劃等公司買的伺服器到位裝個linux再來研究memcached,但這兩天在找到了一個windows下的Memcached版本,就動手開始調整現有的框架了。
Windows下的Server端很簡單,不用安裝,雙擊運行後默認服務埠是11211,沒有試著去更改埠,因為反正以後會用Unix版本,到時再記錄安裝步驟。下載客戶端的JavaAPI包,介面非常簡單,參考API手冊上就有現成的例子。
目標,對舊框架緩存部分進行改造:
1、緩存工具類
2、hibernate的provider
3、用緩存實現session機制
今天先研究研究緩存工具類的改造,在舊框架中部分函數用了ehcache對執行結果進行了緩存處理,現在目標是提供一個緩存工具類,在配置文件中配置使用哪種緩存(memcached或ehcached),使其它程序對具體的緩存不依賴,同時使用AOP方式來對方法執行結果進行緩存。
首先是工具類的實現:
在Spring中配置
Java代碼
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>classpath:ehcache.xmlvalue>
property>
bean>
<bean id="localCache"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager" />
<property name="cacheName"
value="×××.cache.LOCAL_CACHE" />
bean>
<bean id="cacheService"
class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">
<property name="cacheServerList" value="${cache.servers}"/>
<property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>
<property name="cacheCluster" value="${cache.cluster}"/>
<property name="localCache" ref="localCache"/>
bean>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>classpath:ehcache.xmlvalue>
property>
bean>
<bean id="localCache"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager" />
<property name="cacheName"
value="×××.cache.LOCAL_CACHE" />
bean>
<bean id="cacheService"
class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">
<property name="cacheServerList" value="${cache.servers}"/>
<property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>
<property name="cacheCluster" value="${cache.cluster}"/>
<property name="localCache" ref="localCache"/>
bean>
在properties文件中配置${cache.servers} ${cache.cacheServerWeights} ${cache.cluster}
具體工具類的代碼
Java代碼
/**
* @author Marc
*
*/
public class CacheService {
private Log logger = LogFactory.getLog(getClass());
private Cache localCache;
String cacheServerList;
String cacheServerWeights;
boolean cacheCluster = false;
int initialConnections = 10;
int minSpareConnections = 5;
int maxSpareConnections = 50;
long maxIdleTime = 1000 * 60 * 30; // 30 minutes
long maxBusyTime = 1000 * 60 * 5; // 5 minutes
long maintThreadSleep = 1000 * 5; // 5 seconds
int socketTimeOut = 1000 * 3; // 3 seconds to block on reads
int socketConnectTO = 1000 * 3; // 3 seconds to block on initial
// connections. If 0, then will use blocking
// connect (default)
boolean failover = false; // turn off auto-failover in event of server
// down
boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in
// pool
MemCachedClient mc;
public CacheService(){
mc = new MemCachedClient();
mc.setCompressEnable(false);
}
/**
* 放入
*
*/
public void put(String key, Object obj) {
Assert.hasText(key);
Assert.notNull(obj);
Assert.notNull(localCache);
if (this.cacheCluster) {
mc.set(key, obj);
} else {
Element element = new Element(key, (Serializable) obj);
localCache.put(element);
}
}
/**
* 刪除
*/
public void remove(String key){
Assert.hasText(key);
Assert.notNull(localCache);
if (this.cacheCluster) {
mc.delete(key);
}else{
localCache.remove(key);
}
}
/**
* 得到
*/
public Object get(String key) {
Assert.hasText(key);
Assert.notNull(localCache);
Object rt = null;
if (this.cacheCluster) {
rt = mc.get(key);
} else {
Element element = null;
try {
element = localCache.get(key);
} catch (CacheException cacheException) {
throw new DataRetrievalFailureException("Cache failure: "
+ cacheException.getMessage());
}
if(element != null)
rt = element.getValue();
}
return rt;
}
/**
* 判斷是否存在
*
*/
public boolean exist(String key){
Assert.hasText(key);
Assert.notNull(localCache);
if (this.cacheCluster) {
return mc.keyExists(key);
}else{
return this.localCache.isKeyInCache(key);
}
}
private void init() {
if (this.cacheCluster) {
String[] serverlist = cacheServerList.split(",");
Integer[] weights = this.split(cacheServerWeights);
// initialize the pool for memcache servers
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(serverlist);
pool.setWeights(weights);
pool.setInitConn(initialConnections);
pool.setMinConn(minSpareConnections);
pool.setMaxConn(maxSpareConnections);
pool.setMaxIdle(maxIdleTime);
pool.setMaxBusyTime(maxBusyTime);
pool.setMaintSleep(maintThreadSleep);
pool.setSocketTO(socketTimeOut);
pool.setSocketConnectTO(socketConnectTO);
pool.setNagle(nagleAlg);
pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);
pool.initialize();
logger.info("初始化memcached pool!");
}
}
private void destory() {
if (this.cacheCluster) {
SockIOPool.getInstance().shutDown();
}
}
}
/**
* @author Marc
*
*/
public class CacheService {
private Log logger = LogFactory.getLog(getClass());
private Cache localCache;
String cacheServerList;
String cacheServerWeights;
boolean cacheCluster = false;
int initialConnections = 10;
int minSpareConnections = 5;
int maxSpareConnections = 50;
long maxIdleTime = 1000 * 60 * 30; // 30 minutes
long maxBusyTime = 1000 * 60 * 5; // 5 minutes
long maintThreadSleep = 1000 * 5; // 5 seconds
int socketTimeOut = 1000 * 3; // 3 seconds to block on reads
int socketConnectTO = 1000 * 3; // 3 seconds to block on initial
// connections. If 0, then will use blocking
// connect (default)
boolean failover = false; // turn off auto-failover in event of server
// down
boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in
// pool
MemCachedClient mc;
public CacheService(){
mc = new MemCachedClient();
mc.setCompressEnable(false);
}
/**
* 放入
*
*/
public void put(String key, Object obj) {
Assert.hasText(key);
Assert.notNull(obj);
Assert.notNull(localCache);
if (this.cacheCluster) {
mc.set(key, obj);
} else {
Element element = new Element(key, (Serializable) obj);
localCache.put(element);
}
}
/**
* 刪除
*/
public void remove(String key){
Assert.hasText(key);
Assert.notNull(localCache);
if (this.cacheCluster) {
mc.delete(key);
}else{
localCache.remove(key);
}
}
/**
* 得到
*/
public Object get(String key) {
Assert.hasText(key);
Assert.notNull(localCache);
Object rt = null;
if (this.cacheCluster) {
rt = mc.get(key);
} else {
Element element = null;
try {
element = localCache.get(key);
} catch (CacheException cacheException) {
throw new DataRetrievalFailureException("Cache failure: "
+ cacheException.getMessage());
}
if(element != null)
rt = element.getValue();
}
return rt;
}
/**
* 判斷是否存在
*
*/
public boolean exist(String key){
Assert.hasText(key);
Assert.notNull(localCache);
if (this.cacheCluster) {
return mc.keyExists(key);
}else{
return this.localCache.isKeyInCache(key);
}
}
private void init() {
if (this.cacheCluster) {
String[] serverlist = cacheServerList.split(",");
Integer[] weights = this.split(cacheServerWeights);
// initialize the pool for memcache servers
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(serverlist);
pool.setWeights(weights);
pool.setInitConn(initialConnections);
pool.setMinConn(minSpareConnections);
pool.setMaxConn(maxSpareConnections);
pool.setMaxIdle(maxIdleTime);
pool.setMaxBusyTime(maxBusyTime);
pool.setMaintSleep(maintThreadSleep);
pool.setSocketTO(socketTimeOut);
pool.setSocketConnectTO(socketConnectTO);
pool.setNagle(nagleAlg);
pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);
pool.initialize();
logger.info("初始化memcachedpool!");
}
}
private void destory() {
if (this.cacheCluster) {
SockIOPool.getInstance().shutDown();
}
}
}
然後實現函數的AOP攔截類,用來在函數執行前返回緩存內容
Java代碼
public class CachingInterceptor implements MethodInterceptor {
private CacheService cacheService;
private String cacheKey;
public void setCacheKey(String cacheKey) {
this.cacheKey = cacheKey;
}
public void setCacheService(CacheService cacheService) {
this.cacheService = cacheService;
}
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = cacheService.get(cacheKey);
//如果函數返回結果不在Cache中,執行函數並將結果放入Cache
if (result == null) {
result = invocation.proceed();
cacheService.put(cacheKey,result);
}
return result;
}
}
public class CachingInterceptor implements MethodInterceptor {
private CacheService cacheService;
private String cacheKey;
public void setCacheKey(String cacheKey) {
this.cacheKey = cacheKey;
}
public void setCacheService(CacheService cacheService) {
this.cacheService = cacheService;
}
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = cacheService.get(cacheKey);
//如果函數返回結果不在Cache中,執行函數並將結果放入Cache
if (result == null) {
result = invocation.proceed();
cacheService.put(cacheKey,result);
}
return result;
}
}
Spring的AOP配置如下:
Java代碼
<aop:config proxy-target-class="true">
<aop:advisor
pointcut="execution(* ×××.PoiService.getOne(..))"
advice-ref="PoiServiceCachingAdvice" />
aop:config>
<bean id="BasPoiServiceCachingAdvice"
class="×××.core.cache.CachingInterceptor">
<property name="cacheKey" value="PoiService" />
<property name="cacheService" ref="cacheService" />
bean>
轉載
『伍』 spring mvc 用memcached做緩存
首先可以在多台伺服器裝memcached,啟動時分別指定容量和埠
訪問時採用集群方式訪問,只需要spring配置文件裡面配置即可
value可以放任何對象,包括集合
每個鍵值的生命周期可以在放入時獨立設置
類庫可以用spymemcached
數據更新方式可以在後台的定時任務中執行
下面是spring mvc中配置:
<bean id="memcachedClient" class="net.spy.memcached.spring.MemcachedClientFactoryBean">
<property name="servers" value="伺服器A:埠,伺服器B:埠,伺服器C:埠" />
<property name="protocol" value="BINARY" />
<property name="transcoder">
<bean class="net.spy.memcached.transcoders.SerializingTranscoder">
<property name="compressionThreshold" value="1024" />
</bean>
</property>
<property name="opTimeout" value="2000" />
<property name="timeoutExceptionThreshold" value="1998" />
<property name="locatorType" value="CONSISTENT" />
<property name="hashAlg">
<value type="net.spy.memcached.DefaultHashAlgorithm">KETAMA_HASH</value>
</property>
<property name="failureMode" value="Redistribute" />
<property name="useNagleAlgorithm" value="false" />
</bean>
『陸』 java怎麼獲取memcached-session-manager裡面的session
這個屬性必須包含所有的 memcached nodes或者membase bucket uri(s) ,所有的tomcat都必須配置好。每個節點用","分割例如對於一個節點來說<id>是可選的(e.g. memcachedNodes="n1:app01:11211,n2:app02:11211"),所以還可以使用<host>:<port>來定義 (e.g. memcachedNodes="localhost:11211"),這樣sessionId就不會改變(沒有添加node id),這個選項在配置 membase+moxi是非常有用的,所有的tomcat僅僅認識一個"memcached"(實際上是moxi)
memcached nodes:每一個memcached node 定義方式為<id>:<host>:<port>.
membase bucket uris (since 1.6.0): 使用membase 必須配置一個或者多個membase bucket uris, 例如 http://host1:8091/pools,http://host2:8091/pools. Bucket用戶名和密碼必須通過 username跟password 配置(下面還會講到)。 連接到 membase 需要一些支持memcached 協議的jar包. 需要把 jettison.jar 跟 netty.jar 放到 CATALINA_HOME/lib/.
failoverNodes (可選的, 在 non-sticky sessions 是必須的)
當有其他可以使用的memcache 節點的時候使用,因此你應該列出那些跟你的tomcat在同一台機器上的memcached node例如,host1上安裝了tomcat1(t1) memcached1(m1),host2上安裝了tomcat1(t2) memcached1(m2),你應該設置n1作為tomcat1的failover node.因此當memcached2(tomcat2 failoverNodes 設置為 n2)不能使用的時候tomcat1 的session 僅僅存儲在memcached1. 這種設置當host1宕機的時候tomcat1的session 還是可以繼續工作的。
對於非粘性會話的會話是不依賴於一個單一的tomcat failoverNodes不得指定。對於membase buckets 這個屬性可以省略。
多個memcached node 必須用空格「 」或者逗號「,」分隔。
username (1.6.0以後, 可選的)
membase bucket或者SASL 使用的username,如果memcachedNodes 包含一個(或多個)membase bucket uri,這就是bucket的名稱。如果memcachedNodes 使用了username 給SASL授權。還需要一個memcached 協議的包。
password (1.6.0以後, 可選的)
membase bucket 或者 SASL 授權密碼(如果沒有密碼默認為空就好)。
memcachedProtocol (1.3以後, 可選的, 默認值 text)
使用的memcached的協議, text或者binary.
sticky (1.4.0以後, 可選的, 默認值 true)
設置 sticky Session 或者 non-sticky Session.
『柒』 在抽象工廠模式中怎樣使用memcached緩存數據
一、Memcached簡介
memcached 常被用來加速應用程序的處理,在這里,我們將著重於介紹將它部署於應用程序和環境中的最佳實踐。這包括應該存儲或不應存儲哪些、如何處理數據的靈活分布以 及如何調節用來更新 memcached 和所存儲數據的方法。我們還將介紹對高可用性的解決方案的支持,比如 IBM WebSphere® eXtreme Scale。
所有的應用程序,特別是很多 web 應用程序都需要優化它們訪問客戶機和將信息返回至客戶機的速度。可是,通常,返回的都是相同的信息。從數據源(資料庫或文件系統)載入數據十分低效,若是每次想要訪問該信息時都運行相同的查詢,就尤顯低效。
雖然很多 web 伺服器都可被配置成使用緩存發回信息,但那與大多數應用程序的動態特性無法相適。而這正是 memcached 的用武之地。它提供了一個通用的內存存儲器,可保存任何東西,包括本地語言的對象,這就讓您可以存儲各種各樣的信息並可以從諸多的應用程序和環境訪問這些信息。
二、基礎知識
memcached 是一個開源項目,旨在利用多個伺服器內的多餘 RAM 來充當一個可存放經常被訪問信息的內存緩存。這里的關鍵是使用了術語緩存:memcached 為載入自他處的信息提供的是內存中的暫時存儲。
比如,考慮這樣一個典型的基於 web 的應用程序。即便是一個動態網站可能也會有一些組件或信息常量是貫穿頁面整個生命周期的。在一個博客站點內,針對單個 blog post 的類別列表不大可能在頁面查看間經常性地變更。每次都通過一個對資料庫的查詢載入此信息相對比較昂貴,特別是在數據沒有更改的情況下,就更是如此。從圖 1 可以看到一個博客站點內可被緩存的頁面分區。
圖1.一個典型的博客頁面內的可緩存元素
將這種結構放在 blog 站點的其他元素,poster 信息、注釋 — 設置 blog post 本身 — 進行推斷,可以看出為了顯示主頁的內容很可能需要發生 10-20 次資料庫查詢和格式化。 每天對數百甚至數千的的頁面查看重復此過程,那麼您的伺服器和應用程序執行的查詢要遠遠多於為了顯示頁面內容所需執行的查詢。
通過使用 memcached,可以將載入自資料庫的格式化信息存儲為一種可直接用在 Web 頁面上的格式。並且由於信息是從 RAM 而不是通過資料庫和其他處理從磁碟載入的,所以對信息的訪問幾乎是瞬時的。
再強調一下,memcached 是一個用來存儲常用信息的緩存,有了它,您便無需從緩慢的資源,比如磁碟或資料庫,載入並處理信息了。
對 memcached 的介面是通過網路連接提供的。這意味著您可以在多個客戶機間共享單個的 memcached 伺服器(或多個伺服器,如本文稍後所示的)。這個網路介面非常迅速,並且為了改善性能,伺服器會故意不支持身份驗證或安全性通信。但這不應限制部署選項。 memcached 伺服器應該存在於您網路的內部。網路介面的實用性以及可以部署多個 memcached 實例的簡便性讓您可以使用多個機器上的多餘 RAM 來提高您緩存的整體大小。
三、存儲方法
memcached 的存儲方法是一個簡單的鍵/值對,類似於很多語言內的散列或關聯數組。通過提供鍵和值來將信息存儲到 memcached 內,通過按特定的鍵請求信息來恢復信息。
信息會無限期地保留在緩存內,除非發生如下的情況:
為緩存分配的內存耗盡 — 在這種情況下,memcached 使用 LRU(最近最少使用)方法從此緩存刪除條目。最近未曾使用的條目會從此緩存中先刪除,最舊的最先訪問。
條目被明確刪除 — 總是可以從此緩存內刪除條目。
條目過期失效 — 各條目均有一個有效的期限以便針對此鍵存儲的信息在過於陳舊時可從緩存中清除這些條目。
上述這些情況可以與您應用程序的邏輯綜合使用以便確保緩存內的信息是最新的。有了這些基礎知識後,讓我們來看看在應用程序內如何能最好地利用 memcached。
四、何時使用memcached?
在使用 memcached 改進應用程序性能時,可以對一些關鍵的過程和步驟進行修改。
在載入信息時,典型的場景如圖 2 所示。
圖2.載入要顯示的信息的典型順序
一般而言,這些步驟是:
執行一個或多個查詢來從資料庫載入信息
格式化適合於顯示(或進一步處理)的信息
使用或顯示格式化了的數據
在使用 memcached 時,為配合這個緩存,可對應用程序的邏輯進行稍許修改:
盡量從緩存載入信息
如果存在,使用信息的被緩存版本
如果它不存在:
執行一個或多個查詢來從資料庫載入信息
格式化適合於顯示或進一步處理的信息
將信息存儲到緩存內
使用格式化了的數據
圖 3 是對這些步驟的總結。
圖3.在使用memcached時載入適合於顯示的信息
數據載入成為了至多三個步驟的一個過程,從緩存載入數據或從資料庫(視情況而定)載入數據並存儲在緩存內。
當這個過程首次發生時,數據將正常地從資料庫或其他數據源載入,然後再存儲到 memcached 內。當下一次訪問此信息時,它就會從 memcached 拉出,而不是從資料庫載入,節省了時間和 CPU 循環。
問題的另一個方面是要確保如果更改了要存儲在 memcached 內的信息,在更新後端信息的同時還要更新 memcached 的版本。這會讓圖 4 內所示的這個典型順序發生稍許變化,如 圖 5 所示。
圖4.在一個典型的應用程序內更新或存儲數據
圖 5 顯示了使用 memcached 後發生了變化的流程。
圖5.在使用memcached時更新或存儲數據
比如,仍以博客站點為例,在博客系統更新資料庫內的類別列表時,更新應該遵循如下順序:
更新資料庫內的類別列表
格式化信息
將信息存儲到 memcached 內
將信息返回至客戶機
memcached 內的存儲操作是原子的,所以信息的更新不會讓客戶機只獲得部分數據;它們獲得的或者是老版本,或者是新版本。
對於大多數應用程序,這兩個操作是您惟一需要注意的。在訪問他人使用的數據時,它會自動被添加到這個緩存內,而且如果對該數據進行了更改,此緩存內也會自動進行更新。
五、鍵、名稱空間和值
memcached 另一個需要重點考慮的因素是如何組織和命名存儲在緩存內的這些數據。從之前博客站點的例子中,不難看出需要使用一種一致的命名結構以便您能載入博客類別、歷史和其他信息,然後再在載入信息(並更新緩存)時或者在更新數據(同樣也要更新緩存)時使用。
使用的何種具體的命名系統特定於應用程序,但通常可以使用一種與現有應用程序類似的結構,並且這種結構很可能基於某種惟一識別符。當從資料庫拉出信息或在整理信息集時,就會發生這種情況。
以 blog post 為例,可以在一個具有鍵 category-list 的項中存儲類別列表。與此 post ID 對應的單個 post,比如 blogpost-29 相關的值都可以使用,而該項的注釋則可以存儲在 blogcomments-29內,其中 29 就是這個 blog post 的 ID。這樣一來, 您就可以將各種各樣的信息存儲在緩存內,使用不同的前綴來標識這些信息。
memcached 鍵/值存儲的簡便性(以及安全性的缺乏)意味著如果您想要在使用同一個 memcached 伺服器的同時支持多個應用程序,那麼就可以考慮使用其他格式的量詞來標識數據屬於某種特定的應用程序。比如,可以添加像 blogapp:blogpost-29 這樣的應用程序前綴。這些鍵是沒有格式的,所以可以使用任何字元串作為鍵的名稱。
在存儲值的方面,應該確保存儲在緩存內的信息適合於您的應用程序。比如,對於這個博客系統,您可能想要存儲被博客應用程序使用的對象以便格式化博客信息,而不是原始的 HTML。如果同一個基礎結構用在應用程序內的多個地方,這一點更具實用性。
大多數語言的介面,包括 Java™、Perl、PHP 等,都能串列化語言對象以便存儲在 memcached 內。這就讓您可以存儲並隨後從內存存儲恢復全部對象,而不是在您的應用程序內手動重構它們。 很多對象,或它們使用的結構,都基於某種散列或數組結構。對於跨語言的環境,比如在 JSP 環境和 JavaScript 環境間共享相同信息,可以使用一種架構中立的格式,比如 JavaScript Object Notation (JSON) 甚或 XML。
六、填充並使用memcached
作為一種開源產品以及一種最初開發用來工作於現有開源環境內的產品,memcached 受大量環境和平台支持。與 memcached 伺服器通信的介面有很多,並常常具有針對所有語言的多個實現。參見參考資料 以獲得常用的庫和工具箱。
要列出所有受支持的介面和環境不太可能,但它們均支持 memcached 協議提供的基礎 API。這些描述已經被簡化並應用在不同語言的上下文內,在這些語言中,使用不同的值可指示錯誤。主要的函數有:
get(key) — 從存儲了特定鍵的 memcached 獲得信息。 如果鍵不存在,就返回錯誤。
set(key, value [, expiry]) — 使用緩存內的標識符鍵存儲這個特定的值。如果鍵已經存在,那麼它就會被更新。期滿時間的單位為秒,並且如果值小於 30 天 (30*24*60*60),那麼就用作相對時間,如果值大於 30 天,那麼就用作絕對時間 (epoch)。
add(key, value [, expiry]) — 如果鍵不存在就將這個鍵添加到緩存內,如果鍵已經存在就返回錯誤。如果您想要顯式地添加一個新鍵而又不會因它已經存在而更新它,那麼這個函數將十分有用。
replace(key, value [, expiry]) — 更新此特定鍵的值,如果鍵不存在就返回一個錯誤。
delete(key [, time]) — 從緩存中刪除此鍵/值對。如果您提供一個時間,那麼添加具有此鍵的一個新值就會被阻塞這個特定的時期。超時讓您可以確保此值總是可以重新讀取自您的數據中心。
incr(key [, value]) — 為特定的鍵增 1 或特定的值。只適用於數值。
decr(key [, value]) — 為特定的鍵減 1 或特定的值,只適用於數值。
flush_all — 讓緩存內的所有當前條目無效(或到期失效)。
比如,在 Perl 內,基本 set 操作可以如清單 1 所示的那樣處理。
清單 1. Perl 內的基本 set 操作
use Cache::Memcached;
my $cache = new Cache::Memcached {
'servers' => [
'localhost:11211',
],
};
$cache->set('mykey', 'myvalue');
Ruby 內的相同的基本操作如清單 2 所示。
清單 2. Ruby 內的基本 set 操作
require 'memcache'
memc = MemCache::new '192.168.0.100:11211'
memc["mykey"] = "myvalue"
在兩個例子中可以看到相同的基本結構:設置 memcached 伺服器,然後分配或設置值。其他的介面也可用,包括適合於 Java 技術的那些介面,讓您可以在 WebSphere 應用程序內使用 memcached。memcached 介面類允許將 Java 對象直接序列化到 memcached 以便於存儲和載入復雜的結構。當在像 WebSphere 這樣的環境內進行部署時,有兩個事情非常重要:服務的彈性(在 memcached 不可用時如何做)以及如何提高緩存存儲量來改進在使用多個應用程序伺服器或在使用像 WebSphere eXtreme Scale 這樣的環境時的性能。我們接下來就來看看這兩個問題。
七、彈性和可用性
有關 memcached 最常見的一個問題是:「若緩存不可用了,會發生什麼情況呢?」正如之前章節中明示的,緩存內的信息不應該成為信息的的惟一資源。必須要能夠從其他位置載入存儲在緩存內的數據。
雖然,無法從緩存訪問信息將會減緩應用程序的性能,但它不應該阻止應用程序的運轉。可能會發生這樣幾個場景:
如果 memcached 服務宕掉,應用程序應該回退到從原始數據源載入信息並對信息進行顯示所需的格式化。此應用程序還應繼續嘗試在 memcached 內載入和存儲信息。
一旦 memcached 伺服器恢復可用,應用程序就應該自動嘗試存儲數據。沒有必要強制重載已緩存了的數據,可以使用標準的訪問來用信息載入和填充緩存。最終,緩存將會被最常用的數據重新填充。
再次重申,memcached 是信息的緩存但並非惟一的數據源。memcached 伺服器不可用不應該是應用程序的終結,雖然這意味著在 memcached 伺服器恢復正常之前性能會有所降低。實際上,memcached 伺服器相對簡單,並且雖然不是絕對無故障的,但它的簡單性的結果就是它很少會出錯。
八、分配緩存
memcached 伺服器只是網路上針對一些鍵存儲值的一個緩存。如果有多台機器,那麼很自然地會想要在所有多餘機器上設置一個 memcached 的實例來提供一個超大的聯網 RAM 緩存存儲。
有了這個想法後,還有一種想當然是需要使用某種分配或復制機制來在機器之間復制鍵/值對。這種方式的問題是如果這么做反而會減少可用的 RAM 緩存,而不是增加。如圖 6 所示,可以看出這里有三個應用程序伺服器,每個伺服器都可以訪問一個 memcached 實例。
圖6.多重memcached實例的不正確使用
盡管每個 memcached 實例都是 1 GB 的大小(產生 3 GB 的 RAM 緩存),但如果每個應用程序伺服器只有其自己的緩存(或者在 memcached 之間存在著數據的復制),那麼整個安裝也仍只能有 1 GB 的緩存在每個實例間復制。
由於 memcached 通過一個網路介面提供信息,因此單個的客戶機可以從它所能訪問的任何一個 memcached 實例訪問數據。如果數據沒有跨每個實例被復制,那麼最終在每個應用程序伺服器上,就可以有 3 GB 的 RAM 緩存可用,如圖 7 所示。
圖7.多重memcached實例的正確使用
這個方法的問題是選擇哪個伺服器來儲存鍵/值對,以及當想要重新獲得一個值時,如何決定要與哪個 memcached 伺服器對話。問題的解決方案就是忽略復雜的東西,比如查找表,或是寄望 memcached 伺服器來為您處理這個過程。而 memcached 客戶機則必須要力求簡單。
memcached 客戶機不必決定此信息,它只需對在存儲信息時指定的鍵使用一個簡單的散列演算法。當想要從一列 memcached 伺服器存儲或獲取信息時,memcached 客戶機就會用一個一致的散列演算法從這個鍵獲取一個數值。舉個例子,鍵 mykey 被轉換成數值 23875 。是保存還是獲取信息無關緊要,這個鍵將總是被用作惟一標識符來從 memcached 伺服器載入,因此在本例中,「mykey」 散列轉化後對應的值總是 23875。
如果有兩個伺服器,那麼 memcached 客戶機將對這個數值進行一個簡單的運算(例如,系數)來決定它應將此值存儲在第一個還是第二個配置了的 memcached 實例上。
當存儲一個值時,客戶機會從這個鍵確定出散列值以及它原來存儲在哪個伺服器上。當獲取一個值時,客戶機會從這個鍵確定出相同的散列值並會選擇相同的伺服器來獲取信息。
如果在每個應用程序伺服器上使用的是相同的伺服器列表(並且順序相同),那麼當需要保存或檢索同一個鍵時,每個應用程序伺服器都將選擇同一個 伺服器。現在,在這個例子中,有 3GB 的 memcached 空間可以共享,而不是同一個 1 GB 的空間的復制,這就帶來了更多的可用緩存,並很有可能會提高有多個用戶情況下的應用程序的性能。
九、如何能不使用memcached?
盡管 memcached 很簡單,但 memcached 實例有時候還是會被不正確地使用。
memcached不是一個資料庫
最常見的 memcached 誤用就是把它用作一個數據存儲,而不是一個緩存。memcached 的首要目的就是加快數據的響應時間,否則數據從其他數據源構建或恢復需要很長時間。一個典型的例子就是從一個資料庫中恢復信息,特別是在信息顯示給用戶前 需要對信息進行格式化或處理的時候。Memcached 被設計用來將信息存儲在內存中以避免每次在數據需要恢復時重復執行相同的任務。
切不可將 memcached 用作運行應用程序所需信息的惟一信息源;數據應總是可以從其他信息源獲取。此外,要記住 memcached 只是一個鍵/值的存儲。不能在數據上執行查詢,或者對內容進行迭代來提取信息。應該使用它來存儲數據塊或對象以備批量使用。
不要緩存資料庫行或文件
雖然可以使用 memcached 存儲載入自資料庫的數據行,但這實際上是查詢緩存,並且大多數資料庫都提供各自的查詢緩存的機制。其他的對象,比如文件系統的圖像或文件的情況與此相同。很多應用程序和 web 伺服器針對此類工作已經有了一些很好的解決方案。
如果在載入和格式化後,使用它來存儲全部信息塊,就可以從 memcached 獲得更多的實用工具和性能上的改善。仍以我們的博客站點為例,存儲信息的最佳點是在將博客類別格式化為對象,甚至是在格式化成 HTML 後。博客頁面的構造可通過從 memcached 載入各個組件(比如 blog post、category list、post history 等)並將完成的 HTML 寫回至客戶機實現。
memcached並不安全
為了確保最佳性能,memcached 並未提供任何形式的安全性,沒有身份驗證,也沒有加密。這意味著對 memcached 伺服器的訪問應該這么處理:一是通過將它們放到應用程序部署環境相同的私有側,二是如果安全性是必須的,那麼就使用 UNIX® socket 並只允許當前主機上的應用程序訪問此 memcached 伺服器。
這多少犧牲了一些靈活性和彈性,以及跨網路上的多台機器共享 RAM 緩存的能力,但這是在目前的情況下確保 memcached 數據安全性的惟一一種解決方案。
十、不要限制自己
除了不應該使用 memcached 實例的情況外,memcached 的靈活性不應忽視。由於 memcached 與應用程序處於相同的架構水平,所以很容易集成並連接到它。並且更改應用程序以便利用 memcached 也並不復雜。此外,由於 memcached 只是一個緩存,所以在出現問題時它不會停止應用程序的執行。如果使用正確的話,它所做的是減輕其餘伺服器基礎設施的負載(減少對資料庫和數據源的讀操 作),這意味著無需更多的硬體就可以支持更多的客戶機。
但請記住,它僅僅是個緩存!
結束語
在本文中,我們了解了 memcached 以及如何最佳地使用它。我們看到了信息如何存儲、如何選擇合理的鍵以及如何選擇要存儲的信息。我們還討論了所有 memcached 用戶都要遇到的一些關鍵的部署問題,包括多伺服器的使用、當 memcached 實例消亡時該怎麼做,以及(也許最為重要的)在哪些情況下不能使用 memcached。
作為一種開源的應用程序並且是目的簡單而直白的應用程序,memcached 的功能和實用性均來自於這種簡單性。通過為信息提供巨大的 RAM 存儲空間、讓它在網路上可用,然後再讓它可通過各種不同的介面和語言訪問到,memcached 可被集成到多種多樣的安裝和環境中。
『捌』 java中memcache怎麼用
1. memcached client for java客戶端API:memcached client for java
引入jar包:java-memcached-2.6.2.jar
package com.pcitc.memcached;
import com.danga.MemCached.*;
public class TestMemcached {
public static void main(String[] args) {
/* 初始化SockIOPool,管理memcached的連接池 */
String[] servers = { "192.168.1.111:11211" };
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(servers);
pool.setFailover(true);
pool.setInitConn(10);
pool.setMinConn(5);
pool.setMaxConn(250);
pool.setMaintSleep(30);
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setAliveCheck(true);
pool.initialize();
/* 建立MemcachedClient實例 */
MemCachedClient memCachedClient = new MemCachedClient();
for (int i = 0; i < 10; i++) {
/* 將對象加入到memcached緩存 */
boolean success = memCachedClient.set("" + i, "Hello!");
/* 從memcached緩存中按key值取對象 */
String result = (String) memCachedClient.get("" + i);
System.out.println(String.format("set( %d ): %s", i, success));
System.out.println(String.format("get( %d ): %s", i, result));
}
}
}
2. spymemcached客戶端API:spymemcached client
引入jar包:spymemcached-2.10.3.jar
package com.pcitc.memcached;
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MClient {
public static void main(String[] args) {
setValue();
getValue();
}
// 用spymemcached將對象存入緩存
public static void setValue() {
try {
/* 建立MemcachedClient 實例,並指定memcached服務的IP地址和埠號 */
MemcachedClient mc = new MemcachedClient(new InetSocketAddress(
"192.168.1.111", 11211));
Future<Boolean> b = null;
/* 將key值,過期時間(秒)和要緩存的對象set到memcached中 */
b = mc.set("neead", 900, "someObject");
if (b.get().booleanValue() == true) {
mc.shutdown();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 用spymemcached從緩存中取得對象
public static void getValue() {
try {
/* 建立MemcachedClient 實例,並指定memcached服務的IP地址和埠號 */
MemcachedClient mc = new MemcachedClient(new InetSocketAddress(
"192.168.1.111", 11211));
/* 按照key值從memcached中查找緩存,不存在則返回null */
Object b = mc.get("neead");
mc.shutdown();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
3.兩種API比較
memcached client for java:較早推出的memcached JAVA客戶端API,應用廣泛,運行比較穩定。
spymemcached:A simple, asynchronous, single-threaded memcached client written in java. 支持非同步,單線程的memcached客戶端,用到了java1.5版本的concurrent和nio,存取速度會高於前者,但是穩定性不好,測試中常報timeOut等相關異常。
由於memcached client for java發布了新版本,性能上有所提高,並且運行穩定,所以建議使用memcached client for java
『玖』 java memcached怎麼緩存部分數據
其實就相當於在應用程序和資料庫之間開了一塊內存區域,將一些高頻訪問的數據放在其中,避免每次都請求資料庫。至於之所以用memcached和redis,而不是自己在程序里開個hashmap,是因為這塊區域可以共享且容易管理,在集群環境下更方便使用。
『拾』 java怎麼樣用memcache緩存一張表的數據
其實就相當於在應用程序和資料庫之間開了一塊內存區域,將一些高頻訪問的數據放在其中,避免每次都請求資料庫。至於之所以用memcached和redis,而不是自己在程序里開個hashmap,是因為這塊區域可以共享且容易管理,在集群環境下更方便使用。
有些做法是直接將數據序列化後存在redis的string或是memcached中,也有些其他做法是利用redis特有的數據結構存儲一些關系,例如用sorted set存排行榜,string用來計數,set做一些倒排索引、用戶好友關系之類的。我覺得這些都可以稱之為緩存。