本人菜鳥一名,剛畢業出來沒多久,在上海一家公司工作,公司有算上我有3個java程式員,其他兩個有兩到三年的工作經驗,他們負責APP的介面開發,我一個人負責後台管理介面開發,公司項目架構是用Spring搭建的,開發工具也是Spring的,持久層整合了Spring data jap和Mybatis,控制層用的是Spring MVC ,對於剛出校園的我來說覺得這架構塔的特別牛。由於項目的許可權做的有點複雜,而且查詢的地方特別多,網頁載入速度特別慢,老大說把那些許可權判斷放我緩衝裡,讓我去做,我當時就楞住了,我剛從學校出來,只知道hibernate二級緩衝,老大讓我在memcached和redis中選一個,還要做叢集模式的,我那時還是試用期,為了突顯自己的能力,就硬著頭皮答應下來了。現在就寫下我學習這兩個緩衝的路程。
redis sentinel 介紹:(此處copy)
Redis 的 Sentinel 系統用於管理多個 Redis 伺服器(instance),該系統執行以下三個任務: 監控(Monitoring):Sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。 提醒(Notification):當被監控的某個 Redis 伺服器出現問題時,Sentinel 可以通過 API 向管理員或者其他應用程式發送通知。 自動故障遷移(Automatic failover):當一個主伺服器不能正常工作時,Sentinel 會開始一次自動故障遷移操作,它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器,並讓失效主伺服器的其他從伺服器改為複製新的主伺服器;當用戶端試圖串連失效的主伺服器時,叢集也會向用戶端返回新主伺服器的地址,使得叢集可以使用新主伺服器代替失效伺服器。
首先介紹redis sentinel服務端配置
這是連接埠號碼為6479的redis主伺服器
##redis.conf
##redis-0,預設為def_master
port 6479
##授權密碼,請各個配置保持一致
requirepass 123456
masterauth 123456
##暫且禁用指令重新命名
##rename-command
##開啟AOF,禁用snapshot
appendonly yes
save 900 1
save 300 10
save 60 10000
##slaveof no one
slave-read-only yes
這是連接埠號碼為6480的從伺服器
##redis.conf
##redis-0,預設為def_master
port 6480
slaveof 127.0.0.1 6479
##授權密碼,請各個配置保持一致
requirepass 123456
masterauth 123456
##暫且禁用指令重新命名
##rename-command
##開啟AOF,禁用snapshot
appendonly yes
save 900 1
save 300 10
save 60 10000
##slaveof no one
slave-read-only yes
這是sentinel 叢集管理器sentinel.conf配置
##redis-0
##sentinel執行個體之間的通訊連接埠
port 26379
##指定sentinel使用的連接埠,不能與redis-server運行執行個體的連接埠衝突,1表示至少一台從伺服器發現主伺服器故障就會自動主從切換
sentinel monitor def_master 127.0.0.1 6479 1
##串連redis服務密碼
sentinel auth-pass def_master 123456
##表示如果5s內mymaster沒響應,就認為主伺服器發生故障
sentinel down-after-milliseconds def_master 50000
##表示如果master重新選出來後,其它slave節點能同時並行從新master同步緩衝的台數有多少個,顯然該值越大,所有slave節點完成同步切換的整體速度越快,但如果此時正好有人在訪問這些slave,可能造成讀取失敗,影響面會更廣。最保定的設定為1,只同一時間,只能有一台幹這件事,這樣其它slave還能繼續服務,但是所有slave全部完成緩衝更新同步的進程將變慢。
sentinel parallel-syncs def_master 1
表示如果90秒後,mysater仍沒活過來,則啟動failover(容錯移轉),從剩下的slave中選一個升級為master
sentinel failover-timeout def_master 900000
配置寫好後就開始啟動reids服務,我這是在Windows環境下測試的,在linux下命令有所不同。
輸入cmd命令進入控制台,
開啟redis檔案位置,輸入redis-server.exe redis6479.conf啟動reids主伺服器。
然後開啟從伺服器位置,輸入redis-server.exe redis6480.conf啟動reids從伺服器。
然後啟動sentinel,開啟檔案位置輸入redis-server sentinel.conf --sentinel啟動管理器。
完了之後服務端就開啟成功。
一下是用戶端串連服務端代碼編寫:
Spring提供了Spring data redis這個子項目,本人用的就是Spring data redis
spring的設定檔:
spring-data-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:component-scan base-package="org.tht.service"/>
<cache:annotation-driven></cache:annotation-driven>
<bean id="redisSentinelConfiguration"
class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<!--這裡的def_master就是叢集管理器的名字,我們在用戶端只需串連sentinel,sentinel會幫我們去管理redis伺服器 -->
<property name="def_master ">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="mymaster"></property>
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="26379"/>
</bean>
</set>
</property>
</bean>
<bean id="jeidsConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="password" value="123456"></property>
<constructor-arg ref="redisSentinelConfiguration"/>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jeidsConnectionFactory"/>
<bean
id="cacheManager"
class="org.springframework.data.redis.cache.RedisCacheManager"
c:template-ref="redisTemplate"/>
</beans>
現在我們寫方法:
@Cacheable(value="messageCache",key="#name")
public String getMessage(String name) {
return userService.findByName(name);
}
這是查詢方法,@Cacheable(value="messageCache",key="#name")
這個註解是查詢redis緩衝,value:命名空間,key:返回資料對應的鍵。如果緩衝中沒有這個key就會去查詢資料庫,並將返回的值存入redis,有則直接從緩衝中讀取資料。
//更新緩衝
@CachePut(value="messageCache",key="#name")
public String updateMessage(String name) {
return userService.findByName(name);
}
這個註解是修改redis緩衝@CachePut(value="messageCache",key="#name")
//清空命名空間為messageCache下的所有緩衝
@CacheEvict(value="messageCache",allEntries=true)
public void deleteOperationAuthByPageUrlCache() {
}
//清空命名空間為messageCache下key為name的緩衝
@CacheEvict(value="messageCache",allEntries=true,key="#name")
public void deleteOperationAuthByPageUrlCache() {
}
以上代碼經過本人測試過,沒問題,當主伺服器發生故障時從伺服器會自動升為主伺服器,兩台redis伺服器的資料會同步,這種叢集模式無需擔心伺服器掛掉之後資料的丟失。
在學校redis之前本人也學習了memcached,之說以選擇redis下面會說明原因。
以下是memcached基於用戶端分布式代碼:
Google提供了memcached與Spring整合的組件simple spring memcached,一下是spring-memcache.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
">
<context:component-scan base-package="org.tht.service"/>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<import resource="simplesm-context.xml" />
<!-- 預設一個client -->
<bean name="defaultMemcachedClient" class="com.google.code.ssm.CacheFactory">
<property name="cacheClientFactory">
<bean name="cacheClientFactory" class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl" />
</property>
<property name="addressProvider">
<bean class="com.google.code.ssm.config.DefaultAddressProvider">
<!--伺服器位址,在這裡實現分布式 -->
<property name="address" value="127.0.0.1:11211,192.168.1.227:12677" />
</bean>
</property>
<!-- 一致性hash ~。~ -->
<property name="configuration">
<bean class="com.google.code.ssm.providers.CacheConfiguration">
<property name="consistentHashing" value="true" />
</bean>
</property>
</bean>
<bean class="com.google.code.ssm.Settings">
<property name="order" value="500" />
</bean>
</beans>
一下是方法:
/**
* 當執行getUserById查詢方法時,系統首先會從緩衝中擷取id對應的實體
* 如果實體還沒有被緩衝,則執行查詢方法並將查詢結果放入緩衝中
*/
@ReadThroughSingleCache(namespace = "test")
public CacheBean getUserById(@ParameterValueKeyProvider String userId) throws Exception{
System.out.println("沒有快取命中");
CacheBean cacheBean=new CacheBean();
cacheBean.setUserId(userId);
cacheBean.setUserName("趙六");
return cacheBean;
}
/**
* 當執行delete方法時,系統會刪除緩衝中id對應的實體
*/
@InvalidateSingleCache(namespace="test")
public void delete(@ParameterValueKeyProvider Integer userId){
System.out.println(userId);
}
/**
* 當執行update方法時,系統會更新緩衝中id對應的實體
* 將實體內容更新成@*DataUpdateContent標籤所描述的實體
*/
@UpdateSingleCache(namespace="test")
public void update(@ParameterValueKeyProvider @ParameterDataUpdateContent CacheBean cacheBean){
System.out.println(cacheBean.getUserName());
}
現在就開始說說redis和memcached的區別:
在此之前你可能在網上查看了很多關於兩者的區別,在此我只說我在用這兩個緩衝的心得與體會。
區別1:memcached的分布式是基於用戶端的(下面會介紹),而redis的分布式是基於服務端的(上面已經寫的很清楚了)
區別2:redis可以根據命名空間刪除該命名空間下的所有key,而memcached必須得指定key(想刪除命名空間下的所有key,只能先將該命名空間下的所有key查出來再進行刪除)
區別3:Redis支援資料的持久化,可以將記憶體中的資料保持在磁碟中,重啟的時候可以再次載入進行使用,而memcached伺服器重啟後所有快取資料都會清空。
以上3個區別是我的切身體會,還有很多區別在這裡就不一一說明了,在網上都可以查到。
本人菜鳥一枚,大神勿噴,以上只是本人學習的一點小體會,也只是懂了點皮毛,也有很多不懂得地方,希望可以和你們一起交流,共同進步。