Redis集群和緩存

1铛楣、安裝redis

安裝的前提條件:
需要安裝gcc:yum install gcc-c++
1弱左、下載redis的源碼包。
2棘钞、把源碼包上傳到linux服務(wù)器
3缠借、解壓源碼包:tar -zxvf redis-3.0.0.tar.gz
4、Make
5宜猜、Make install:[root@bogon redis-3.0.0]# make install PREFIX=/usr/local/redis

2烈炭、啟動(dòng)redis

1、前端啟動(dòng)模式
/usr/local/redis/bin/redis-server
默認(rèn)是前端啟動(dòng)模式宝恶,端口是6379

2符隙、后端啟動(dòng)
1)從redis的源碼目錄中復(fù)制redis.conf到redis的安裝目錄。
2)修改配置文件


image.png

3)[root@bogon bin]# ./redis-server redis.conf

3垫毙、Redis常用命令

127.0.0.1:6379> set a 10
OK
127.0.0.1:6379> get a
"10"

4霹疫、集群結(jié)構(gòu)

集群中有三個(gè)節(jié)點(diǎn)的集群,每個(gè)節(jié)點(diǎn)有一主一備综芥。需要6臺(tái)虛擬機(jī)丽蝎。
搭建一個(gè)偽分布式的集群,使用6個(gè)redis實(shí)例來模擬。

1屠阻、搭建集群需要的環(huán)境
搭建集群需要使用到官方提供的ruby腳本红省。需要安裝ruby的環(huán)境。
安裝ruby
yum install ruby
yum install rubygems

redis集群管理工具redis-trib.rb
[root@bogon ~]# cd redis-3.0.0
[root@bogon redis-3.0.0]# cd src
[root@bogon src]# ll *.rb
-rwxrwxr-x. 1 root root 48141 Apr 1 07:01 redis-trib.rb

腳本需要的ruby包:


image.png

需要上傳到linux服務(wù)国觉。
安裝ruby的包:
[root@bogon ~]# gem install redis-3.0.0.gem

2吧恃、集群的搭建
第一步:創(chuàng)建6個(gè)redis實(shí)例,端口號(hào)從7001~7006
第二步:修改redis的配置文件
1麻诀、修改端口號(hào)

image.png

2痕寓、打開cluster-enable前面的注釋。
image.png

第三步:把創(chuàng)建集群的ruby腳本redis-trib.rb復(fù)制到redis-cluster目錄下蝇闭。
第四步:?jiǎn)?dòng)6個(gè)redis實(shí)例
第五步:創(chuàng)建集群呻率。
[root@bogon redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.25.153:7001 192.168.25.153:7002 192.168.25.153:7003 192.168.25.153:7004 192.168.25.153:7005 192.168.25.153:7006

3、集群測(cè)試
[root@bogon redis-cluster]# redis01/redis-cli -h 192.168.25.153 -p 7002 -c
192.168.25.153:7002> set a 100
-> Redirected to slot [15495] located at 192.168.25.153:7003
OK

5呻引、Jedis客戶端

需要把jedis的jar包添加到工程中礼仗,如果是maven需要添加jar包的坐標(biāo)。

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.2</version>
        </dependency>

1逻悠、單機(jī)版

     /**
     * redis單機(jī)版測(cè)試
     */
    @Test
    public void testJedisSingle(){
        Jedis jedis = new Jedis("10.10.1.146",6379);
        jedis.set("name","abc");
        String name = jedis.get("name");
        System.out.println(name);
        jedis.close();
    }
    /**
     * redis連接池測(cè)試
     */
    @Test
    public void testJedisPool(){
        JedisPool pool = new JedisPool("10.10.1.146",6379);
        Jedis jedis = pool.getResource();
        jedis.set("age","100");
        String age = jedis.get("age");
        System.out.println(age);
        jedis.close();
        pool.close();
    }

2元践、集群版

    /**
     * redis集群測(cè)試(自帶連接池)
     */
    @Test
    public void testJedisCluster(){
        //添加節(jié)點(diǎn)
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("10.10.1.146",7001));
        nodes.add(new HostAndPort("10.10.1.146",7002));
        nodes.add(new HostAndPort("10.10.1.146",7003));
        nodes.add(new HostAndPort("10.10.1.146",7004));
        nodes.add(new HostAndPort("10.10.1.146",7005));
        nodes.add(new HostAndPort("10.10.1.146",7006));

        JedisCluster jedisCluster = new JedisCluster(nodes);
        jedisCluster.set("key1","redis cluster");
        String str = jedisCluster.get("key1");
        System.out.println(str);
        jedisCluster.close();
    }

3、jedis整合spring(單機(jī)版)

    <!--redis連接池配置-->
    <bean name="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大連接數(shù) -->
        <property name="maxTotal" value="30" />
        <!-- 最大空閑連接數(shù) -->
        <property name="maxIdle" value="10" />
        <!-- 每次釋放連接的最大數(shù)目 -->
        <property name="numTestsPerEvictionRun" value="1024" />
        <!-- 釋放連接的掃描間隔(毫秒) -->
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <!-- 連接最小空閑時(shí)間 -->
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <!-- 連接空閑多久后釋放, 當(dāng)空閑時(shí)間>該值 且 空閑連接>最大空閑連接數(shù) 時(shí)直接釋放 -->
        <property name="softMinEvictableIdleTimeMillis" value="10000" />
        <!-- 獲取連接時(shí)的最大等待毫秒數(shù),小于零:阻塞不確定的時(shí)間,默認(rèn)-1 -->
        <property name="maxWaitMillis" value="1500" />
        <!-- 在獲取連接的時(shí)候檢查有效性, 默認(rèn)false -->
        <property name="testOnBorrow" value="true" />
        <!-- 在空閑時(shí)檢查有效性, 默認(rèn)false -->
        <property name="testWhileIdle" value="true" />
        <!-- 連接耗盡時(shí)是否阻塞, false報(bào)異常,ture阻塞直到超時(shí), 默認(rèn)true -->
        <property name="blockWhenExhausted" value="false" />
    </bean>

    <!--redis單機(jī)版配置-->
    <bean id="redisClient" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
        <constructor-arg name="port" value="6379"></constructor-arg>
        <constructor-arg name="poolConfig" ref="redisPoolConfig"></constructor-arg>
    </bean>
    /**
     * redis整合spring單機(jī)版測(cè)試
     */
    @Test
    public void testSpringJedisSingle(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
        JedisPool pool = (JedisPool) applicationContext.getBean("redisClient");
        Jedis jedis = pool.getResource();
        String name = jedis.get("name");
        System.out.println(name);
        jedis.close();
        pool.close();
    }

4蹂风、jedis整合spring(集群版)

    <!--redis連接池配置-->
    <bean name="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大連接數(shù) -->
        <property name="maxTotal" value="30" />
        <!-- 最大空閑連接數(shù) -->
        <property name="maxIdle" value="10" />
        <!-- 每次釋放連接的最大數(shù)目 -->
        <property name="numTestsPerEvictionRun" value="1024" />
        <!-- 釋放連接的掃描間隔(毫秒) -->
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <!-- 連接最小空閑時(shí)間 -->
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <!-- 連接空閑多久后釋放, 當(dāng)空閑時(shí)間>該值 且 空閑連接>最大空閑連接數(shù) 時(shí)直接釋放 -->
        <property name="softMinEvictableIdleTimeMillis" value="10000" />
        <!-- 獲取連接時(shí)的最大等待毫秒數(shù),小于零:阻塞不確定的時(shí)間,默認(rèn)-1 -->
        <property name="maxWaitMillis" value="1500" />
        <!-- 在獲取連接的時(shí)候檢查有效性, 默認(rèn)false -->
        <property name="testOnBorrow" value="true" />
        <!-- 在空閑時(shí)檢查有效性, 默認(rèn)false -->
        <property name="testWhileIdle" value="true" />
        <!-- 連接耗盡時(shí)是否阻塞, false報(bào)異常,ture阻塞直到超時(shí), 默認(rèn)true -->
        <property name="blockWhenExhausted" value="false" />
    </bean>

    <!--redis集群版配置-->
    <bean name="redisClient" class="redis.clients.jedis.JedisCluster">
        <constructor-arg name="nodes">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
                    <constructor-arg name="port" value="7001"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
                    <constructor-arg name="port" value="7002"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="10.10.1.146"></constructor-arg>
                    <constructor-arg name="port" value="7006"></constructor-arg>
                </bean>
            </set>
        </constructor-arg>
        <constructor-arg name="poolConfig" ref="redisPoolConfig"></constructor-arg>
    </bean>
    /**
     * redis整合spring集群版測(cè)試
     */
    @Test
    public void testSpringJedisCluster(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
        JedisCluster jedisCluster = (JedisCluster) applicationContext.getBean("redisClient");
        String str = jedisCluster.get("key1");
        System.out.println(str);
        jedisCluster.close();
    }

6卢厂、把緩存添加到業(yè)務(wù)邏輯(把業(yè)務(wù)邏輯查詢到的數(shù)據(jù)放入redis數(shù)據(jù)庫)

注意:緩存的添加不能影響正常的業(yè)務(wù)邏輯乾蓬。

    public List<TbContent> getContentList(long contentCid) {
        //從緩存中取內(nèi)容
        try {
            String result = jedisClient.hget(INDEX_CONTENT_REDIS_KEY, contentCid + "");
            if (!StringUtils.isBlank(result)) {
                //把字符串轉(zhuǎn)換成list
                List<TbContent> resultList = JsonUtils.jsonToList(result, TbContent.class);
                return resultList;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        //業(yè)務(wù)邏輯:根據(jù)內(nèi)容分類id在mysql數(shù)據(jù)庫中查詢內(nèi)容列表
        TbContentExample example = new TbContentExample();
        Criteria criteria = example.createCriteria();
        criteria.andCategoryIdEqualTo(contentCid);
        List<TbContent> list = contentMapper.selectByExample(example);
        
        //向緩存中添加內(nèi)容
        try {
            //把list轉(zhuǎn)換成字符串
            String cacheString = JsonUtils.objectToJson(list);
            jedisClient.hset(INDEX_CONTENT_REDIS_KEY, contentCid + "", cacheString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return list;
    }

7惠啄、緩存同步

解決方案:在taotao-rest工程中發(fā)布一個(gè)服務(wù)。當(dāng)后臺(tái)管理系統(tǒng)修改內(nèi)容后任内,調(diào)用此服務(wù)撵渡,同步緩存。
當(dāng)后臺(tái)管理系統(tǒng)死嗦,修改內(nèi)容之后需要通知redis把修改的內(nèi)容對(duì)應(yīng)的分類id的key刪除趋距。
Service層:

public class RedisServiceImpl implements RedisService {

    @Autowired
    private JedisClient jedisClient;
    
    @Value("${INDEX_CONTENT_REDIS_KEY}")
    private String INDEX_CONTENT_REDIS_KEY;
    
    public TaotaoResult syncContent(long contentCid) {
        try {
            jedisClient.hdel(INDEX_CONTENT_REDIS_KEY, contentCid + "");
        } catch (Exception e) {
            e.printStackTrace();
            return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
        }
        return TaotaoResult.ok();
    }
}

Controller層:

@Controller
@RequestMapping("/cache/sync")
public class RedisController {

    @Autowired
    private RedisService redisService;
    
    @RequestMapping("/content/{contentCid}")
    public TaotaoResult contentCacheSync(@PathVariable Long contentCid) {
        TaotaoResult result = redisService.syncContent(contentCid);
        return result;
    }
}

同步緩存服務(wù)的調(diào)用(使用HttpClient調(diào)用http://localhost:8080//cache/sync/content/{contentCid}):

image.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市越除,隨后出現(xiàn)的幾起案子节腐,更是在濱河造成了極大的恐慌,老刑警劉巖摘盆,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翼雀,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡孩擂,警方通過查閱死者的電腦和手機(jī)狼渊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來类垦,“玉大人狈邑,你說我怎么就攤上這事城须。” “怎么了米苹?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵糕伐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我驱入,道長(zhǎng)赤炒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任亏较,我火速辦了婚禮莺褒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘雪情。我一直安慰自己遵岩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布巡通。 她就那樣靜靜地躺著尘执,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宴凉。 梳的紋絲不亂的頭發(fā)上誊锭,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音弥锄,去河邊找鬼丧靡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛籽暇,可吹牛的內(nèi)容都是我干的温治。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼戒悠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼熬荆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绸狐,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤卤恳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后寒矿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體突琳,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年劫窒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了本今。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖冠息,靈堂內(nèi)的尸體忽然破棺而出挪凑,到底是詐尸還是另有隱情,我是刑警寧澤逛艰,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布躏碳,位于F島的核電站,受9級(jí)特大地震影響散怖,放射性物質(zhì)發(fā)生泄漏菇绵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一镇眷、第九天 我趴在偏房一處隱蔽的房頂上張望咬最。 院中可真熱鬧,春花似錦欠动、人聲如沸永乌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翅雏。三九已至,卻和暖如春人芽,著一層夾襖步出監(jiān)牢的瞬間望几,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工萤厅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留橄抹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓祈坠,卻偏偏與公主長(zhǎng)得像害碾,于是被迫代替她去往敵國(guó)和親矢劲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赦拘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容