一肠缔、緩存
我們知道使用緩存夏跷,可以提高查詢效率,那什么情況下需要使用緩存呢明未?通常而言槽华,使用緩存需滿足以下兩個條件:
(1)查詢頻率較高的數(shù)據(jù)。
(2)修改頻率較低的數(shù)據(jù)趟妥。
對于第一點猫态,在我們開發(fā)過程中,如果查詢業(yè)務(wù)比較多,需要頻繁的連接數(shù)據(jù)庫亲雪,這會對數(shù)據(jù)庫的性能帶來極大的損耗勇凭;這個時候可以考慮對這部分數(shù)據(jù)添加緩存。
對于第二點义辕,如果我們業(yè)務(wù)中虾标,需要頻繁的修改某個數(shù)據(jù),這個時候是不適合給它添加緩存的灌砖,因為每次修改了數(shù)據(jù)璧函,都需要去更新緩存。
綜合上面兩點基显,我們需要給導(dǎo)航菜單蘸吓、廣告位投放的內(nèi)容添加緩存。
[if !supportLists]1.2?????????[endif]緩存邏輯實現(xiàn)
[if !supportLists]1.2.1???????[endif]第一部分:添加緩存
需求:在REST接口中撩幽,給導(dǎo)航菜單库继、首頁大廣告位內(nèi)容添加緩存。緩存邏輯在ego-rest工程中實現(xiàn)窜醉。
[if !vml]
[endif]
[if !supportLists]1.2.1.1????[endif]第一步:添加redis的jar依賴
<dependency>
??? <groupId>redis.clients</groupId>
??? <artifactId>jedis</artifactId>
</dependency>
[if !supportLists]1.2.1.2???? [endif]第二步:Spring整合Redis集群
在src路徑下宪萄,添加spring-jedis.xml配置文件,整合redis酱虎。
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
??? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"
??? xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:tx="http://www.springframework.org/schema/tx"
??? xmlns:aop="http://www.springframework.org/schema/aop"
??? xsi:schemaLocation="
???????
? http://www.springframework.org/schema/beans
???????
? http://www.springframework.org/schema/beans/spring-beans.xsd
???????
? http://www.springframework.org/schema/mvc
???????
? http://www.springframework.org/schema/mvc/spring-mvc.xsd
??????
? ? http://www.springframework.org/schema/aop
??? ? ? http://www.springframework.org/schema/aop/spring-aop.xsd
??? ? ? http://www.springframework.org/schema/tx
?????
? ?? http://www.springframework.org/schema/tx/spring-tx.xsd
???????
? http://www.springframework.org/schema/context
?? ?????http://www.springframework.org/schema/context/spring-context.xsd">
????? <!-- 連接池配置 -->
??? <beanid="jedisPoolConfig"class="redis.clients.jedis.JedisPoolConfig">
??????? <!-- 最大連接數(shù) -->
??????? <propertyname="maxTotal"value="30"/>
??????? <!-- 最大空閑連接數(shù) -->
??????? <propertyname="maxIdle"value="10"/>
??????? <!-- 每次釋放連接的最大數(shù)目 -->
??????? <propertyname="numTestsPerEvictionRun"value="1024"/>
??????? <!-- 釋放連接的掃描間隔(毫秒) -->
??????? <propertyname="timeBetweenEvictionRunsMillis"value="30000"/>
??????? <!-- 連接最小空閑時間 -->
??????? <propertyname="minEvictableIdleTimeMillis"value="1800000"/>
??????? <!-- 連接空閑多久后釋放, 當(dāng)空閑時間>該值 且 空閑連接>最大空閑連接數(shù) 時直接釋放 -->
??????? <propertyname="softMinEvictableIdleTimeMillis"value="10000"/>
??????? <!-- 獲取連接時的最大等待毫秒數(shù),小于零:阻塞不確定的時間,默認-1 -->
??????? <propertyname="maxWaitMillis"value="1500"/>
??????? <!-- 在獲取連接的時候檢查有效性, 默認false
? -->
??????? <propertyname="testOnBorrow"value="true"/>
??????? <!-- 在空閑時檢查有效性, 默認false
? -->
??????? <propertyname="testWhileIdle"value="true"/>
??????? <!-- 連接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true -->
??????? <propertyname="blockWhenExhausted"value="false"/>
??? </bean>?
??? <beanid="jedisCluster"class="redis.clients.jedis.JedisCluster">
??????? <constructor-argindex="0">
???????????? <set>
???????????????? <beanclass="redis.clients.jedis.HostAndPort">
???????????????????? <constructor-argindex="0"value="192.168.23.12"></constructor-arg>
???????????????????? <constructor-argindex="1"value="7001"></constructor-arg>
???????????????? </bean>
???????????????? <beanclass="redis.clients.jedis.HostAndPort">
???????????????????? <constructor-argindex="0"value="192.168.23.12"></constructor-arg>
???????????????????? <constructor-argindex="1"value="7002"></constructor-arg>
???????????????? </bean>
???????????????? <beanclass="redis.clients.jedis.HostAndPort">
???????????????????? <constructor-argindex="0"value="192.168.23.12"></constructor-arg>
???????????????????? <constructor-argindex="1"value="7003"></constructor-arg>
???????????????? </bean>
???????????????? <beanclass="redis.clients.jedis.HostAndPort">
???????????????????? <constructor-argindex="0"value="192.168.23.12"></constructor-arg>
???????????????????? <constructor-argindex="1"value="7004"></constructor-arg>
???????????????? </bean>
???????????????? <beanclass="redis.clients.jedis.HostAndPort">
???????????????????? <constructor-argindex="0"value="192.168.23.12"></constructor-arg>
???????????????????? <constructor-argindex="1"value="7005"></constructor-arg>
???????????????? </bean>
???????????????? <beanclass="redis.clients.jedis.HostAndPort">
???????????????????? <constructor-argindex="0"value="192.168.23.12"></constructor-arg>
???????????????????? <constructor-argindex="1"value="7006"></constructor-arg>
???????????????? </bean>
???????????? </set>
??????? </constructor-arg>
??????? <constructor-argindex="1"ref="jedisPoolConfig"></constructor-arg>
??? </bean>
</beans>
[if !supportLists]1.2.1.3???? [endif]第三步:修改ContentServiceImpl類
@Service
public class ContentServiceImpl implements ContentService{
??? private String EGO_CONTENT = "EGO_CONTENT";
??? @Autowired
??? private JedisCluster jedisCluster;
??? @Autowired
??? private ContentMapper mapper;
??? /*
??? ?*緩存邏輯
??? ?*???
? (1)首先查找緩存雨膨。
??? ?*???
? (2)如果緩存有數(shù)據(jù),則直接返回數(shù)據(jù)读串,不需要查詢數(shù)據(jù)庫
??? ?*???
? (3)如果緩存中沒有數(shù)據(jù)聊记,則查詢數(shù)據(jù)庫。并且將數(shù)據(jù)放入緩存中恢暖。
??? ?*???
??? ?*???
? (4)緩存不能影響正常的業(yè)務(wù)執(zhí)行排监,即當(dāng)前緩存無法使用,則直接查詢數(shù)據(jù)庫
??? ?*
??? ?*確定選用哪一個數(shù)據(jù)結(jié)構(gòu)類型(string杰捂,list舆床,set,hash)
??? ?*選用數(shù)據(jù)結(jié)構(gòu)類型的時候嫁佳,有一個原則:能用hash盡量使用hash挨队。原因:減少key的數(shù)量,在尋址的時候速度更快蒿往。
??? ?*
??? ?* {key:{field:value}}??
??? ?*我們這里使用hash數(shù)據(jù)結(jié)構(gòu)類型盛垦,key定義成一個常量EGO_CONTENT?? field就使用類型分類的id,value使用內(nèi)容列表的json格式瓤漏。
??? ?*
??? ?*注意:hash結(jié)構(gòu)只能存儲string格式的數(shù)據(jù)
??? ?*
??? ?*/
??? @Override
??? public EgoResult getContentByCatId(Long catId) {
?????? Listlist = null;
?????? try {
?????????? //1腾夯、查找緩存
?????????? StringjsonData = jedisCluster.hget(EGO_CONTENT, catId+"");
?????????? if(null!=jsonData && !"".equals(jsonData)){
????????????? //緩存里面有數(shù)據(jù)颊埃,則直接返回數(shù)據(jù)即可
????????????? list= JsonUtils.jsonToList(jsonData, Content.class);
?????????? }else{
????????????? //如果緩存中查不到數(shù)據(jù),則查詢數(shù)據(jù)庫
????????????? MapcolumnMap = new HashMap<>();
????????????? columnMap.put("category_id", catId);
????????????? list = mapper.selectByMap(columnMap);
????????????? //再將數(shù)據(jù)放入緩存中
????????????? jedisCluster.hset(EGO_CONTENT, catId+"", JsonUtils.objectToJson(list));
?????????? }
?????? }catch (Exception e) {
?????????? e.printStackTrace();
?????????? //如果緩存中查不到數(shù)據(jù)蝶俱,則查詢數(shù)據(jù)庫
?????????? MapcolumnMap = new HashMap<>();
?????????? columnMap.put("category_id", catId);
?????????? list = mapper.selectByMap(columnMap);
?????? }
?????? returnEgoResult.ok(list);
??? }
}
[if !supportLists]1.2.1.4???? [endif]第四步:測試
(1)重啟rest工程
(2)訪問portal工程首頁班利。將緩存添加到redis中。
(3)再次訪問portal工程首頁榨呆。查看緩存是否生效罗标。
[if !supportLists]1.2.2???????[endif]第二部分:緩存同步
修改、更新導(dǎo)航菜單积蜻、網(wǎng)站內(nèi)容后馒稍,要同步修改緩存,或者清空對應(yīng)的緩存浅侨。
[if !vml]
[endif]
[if !supportLists]2????????????[endif]搜索系統(tǒng)實現(xiàn)
[if !supportLists]2.1?????????[endif]系統(tǒng)架構(gòu)
在本項目中,我們將搜索業(yè)務(wù)獨立出來证膨,創(chuàng)建搜索子系統(tǒng)如输。這樣做,既能提高系統(tǒng)的拓展能力央勒,也能靈活的對系統(tǒng)進行分布式部署不见。
[if !vml]
[endif]
[if !supportLists]2.2?????????[endif]實現(xiàn)思路
(1)搭建搜索服務(wù)器。
(2)創(chuàng)建搜索系統(tǒng)崔步。
(3)發(fā)布搜索服務(wù)的公共接口稳吮。
(4)在門戶系統(tǒng)調(diào)用該接口,實現(xiàn)搜索井濒。