9 springboot集成redis

redis分兩種呵燕,一種單機(jī) http://www.reibang.com/p/6ac1a3b7745e核行,一種集群 http://www.reibang.com/p/d44aa9a8be2c
首先看spring操作redis的配置枕荞,我項(xiàng)目只用到這些线欲,其他的自行百度。
首先添加依賴包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-redis</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>

然后寫類RedisClient

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisClient {  

    @Autowired
    private RedisTemplate redisTemplate;
      //set值
    public void set(String key, String value) {
        try {
            redisTemplate.opsForValue().set(key,value);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
      //get值
    public String get(String key) {

        try {
            return ""+redisTemplate.opsForValue().get(key);
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }
   //自增1
    public void incr(String key) {
        int num = Integer.parseInt(""+redisTemplate.opsForValue().get(key));
        num=num+1;
        redisTemplate.opsForValue().set(key,num);
    }
   //到期時(shí)間
    public boolean expire(String key, int second) {
        boolean result = redisTemplate.expire(key,second, TimeUnit.SECONDS);
        return result;
    }

   //刪除
    public void del(String key) {
        redisTemplate.delete(key);
    }
   //是否存在key
    public boolean hasKey(String s) {
        Boolean flag =  redisTemplate.hasKey(s);
        return flag;

    }
   //左push
    public boolean lpush(String key, String value){
        boolean flag =false;
        try{
            redisTemplate.boundListOps(key).leftPush(value);
            flag =true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return flag;

    }
    //右push
    public boolean rpush(String key, String value){
        boolean flag =false;
        try{
            redisTemplate.boundListOps(key).rightPush(value);
            flag =true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return flag;

    }
   //添加附近的人
    public boolean geoadd(String key,double longitude,double latitude){
        boolean flag = false;
        try{
            redisTemplate.boundGeoOps("nearPeople").geoAdd(new Point(longitude,latitude),key);
            flag = true;
        }catch (Exception e){
            e.printStackTrace();
        }

        return flag;
    }
   //查詢附近的人
    public List geoQuery(double longitude,double latitude) {
        List  list = null;
        try{
            list = redisTemplate.opsForGeo().geoRadius("nearPeople", new Circle(new Point(longitude, latitude),
                    new Distance(500,Metrics.KILOMETERS)),
                    RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates()).getContent();

        }catch (Exception e){
            e.printStackTrace();
        }

        return list;
    }
}

注意:

我用的是RedisTemplate否过,在這之前我用的是redis.clients.jedis.JedisPool狱从,但是每次操作就第一次,可以叠纹,稍微快速刷新兩次就一直阻塞,代碼

public void set(String key, String value) {
    Jedis jedis = null;
    try {  
        jedis = jedisPool.getResource();  
        jedis.set(key, value);  
    } finally {  
        //返還到連接池  
        jedis.close();  
    }  
}  

具體原因沒弄明白敞葛,好像和最大連接數(shù)有關(guān)誉察,之后發(fā)現(xiàn)不行,才換成RedisTemplate

單機(jī)配置

配置文件application.properties添加

# Redis數(shù)據(jù)庫索引(默認(rèn)為0)
spring.redis.database=0
# Redis服務(wù)器地址
spring.redis.host=172.16.255.231
# Redis服務(wù)器連接端口
spring.redis.port=6379
# Redis服務(wù)器連接密碼(默認(rèn)為空)
spring.redis.password=
# 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
spring.redis.pool.max-active=8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閑連接
spring.redis.pool.max-idle=8
# 連接池中的最小空閑連接
spring.redis.pool.min-idle=1
# 連接超時(shí)時(shí)間(毫秒)
spring.redis.timeout=5000

類Controller中測試

@Controller
@RequestMapping("/hello")
public class HelloController {

@Autowired
private HelloService helloService;
@Autowired
private RedisClient redisClient;
@RequestMapping(value = "/testRedis",method = RequestMethod.GET)
@ResponseBody
public String testRedis(@RequestParam String userId){
    if (redisClient.hasKey(userId)){
        System.out.println("redis中用戶存在");
        return redisClient.get(userId);
    }
    User user = new User();
    user.setId("1");
    user.setUsername("lijia");

    redisClient.set(userId,JSON.toJSONString(user));
    System.out.println("redis中用戶不存在,現(xiàn)在已設(shè)定");
    return JSON.toJSONString(user);
}
}

啟動(dòng)Application惹谐,然后再瀏覽器中輸入 http://localhost:8080/hello/testRedis?userId=1
兩次都能返回結(jié)果持偏,但是一次是從redis中讀取的,一次是直接獲取的


這樣redis單機(jī)環(huán)境就搭建好了氨肌。

集群配置

還是修改application.properties

spring.redis.cluster.nodes=172.16.255.231:7001,172.16.255.231:7002,172.16.255.231:7003,172.16.255.231:7004,172.16.255.231:7005,172.16.255.231:7006

然后讀取這個(gè)配置文件

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class RedisClusterProperties {
    //集群節(jié)點(diǎn)
    private List<String> nodes=new ArrayList<>();
    public List<String> getNodes() {
        return nodes;
    }
    public void setNodes(List<String> nodes) {
        this.nodes = nodes;
    }
}

配置

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@Configuration
@ConditionalOnClass(RedisClusterConfig.class)
@EnableConfigurationProperties(RedisClusterProperties.class)
public class RedisClusterConfig {
    @Resource
    private RedisClusterProperties redisClusterProperties;
    @Bean
    public JedisCluster redisCluster(){
        Set<HostAndPort> nodes = new HashSet<>();
        for (String node:redisClusterProperties.getNodes()){
            String[] parts= StringUtils.split(node,":");
            Assert.state(parts.length==2, "redis node shoule be defined as 'host:port', not '" + Arrays.toString(parts) + "'");
            nodes.add(new HostAndPort(parts[0], Integer.valueOf(parts[1])));
        }  
        return new JedisCluster(nodes);
    }
}

最后還是測試類鸿秆,上面的一樣,但是判斷key方式不一樣

import com.alibaba.fastjson.JSON;
import com.lijia.bean.User;
import com.lijia.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.JedisCluster;

@Controller
@RequestMapping("/hello")
public class HelloController {
    @Autowired
    private HelloService helloService;
    @Autowired
    private JedisCluster jedisCluster;
    @RequestMapping(value = "/testRedis",method = RequestMethod.GET)
    @ResponseBody
    public String testRedis(@RequestParam String userId){
        if (jedisCluster.exists(userId)){
            System.out.println("redis集群中用戶存在");
            return jedisCluster.get(userId);
        }
        User user = new User();
        user.setId("1");
        user.setUsername("lijia");
        jedisCluster.set(userId,JSON.toJSONString(user));
        System.out.println("redis集群中用戶不存在,現(xiàn)在已設(shè)定");
        return JSON.toJSONString(user);
    }

}

啟動(dòng)Application怎囚,然后再瀏覽器中輸入 http://localhost:8080/hello/testRedis?userId=1
兩次都能返回結(jié)果卿叽,但是一次是從redis中讀取的,一次是直接獲取的


這集群算是可以用了恳守。
注意:
今天再用linux中連接redis考婴,發(fā)現(xiàn)連接集群中,需要加上-c催烘,這個(gè)是必須的沥阱,不然set和get報(bào)錯(cuò)。

JedisPool假死

如果用jedisPool去set和get伊群。首先會(huì)有一段jedis = jedisPool.getResource();考杉,
就是當(dāng)連接池耗盡的時(shí)候

BlockWhenExhausted:連接耗盡時(shí)是否阻塞, false報(bào)異常,ture阻塞直到超時(shí), 默認(rèn)true
max-wait:獲取連接時(shí)的最大等待毫秒數(shù)(如果設(shè)置為阻塞時(shí)BlockWhenExhausted),如果超時(shí)就拋異常,小于零:阻塞不確定的時(shí)間, 默認(rèn)-1

由于BlockWhenExhausted默認(rèn)為true,連接耗盡時(shí)會(huì)阻塞到超時(shí)舰始,但是MaxWaitMillis默認(rèn)為-1崇棠,超時(shí)時(shí)間是一個(gè)不確定的時(shí)間,所以就一直阻塞著了蔽午。
設(shè)置redis.pool.max-wait值易茬。

RedisTemplate亂碼現(xiàn)象

使用了RedisTemplate之后,今天測試之后發(fā)現(xiàn)redis找不到key,但是出現(xiàn)了下面這種情況抽莱。


原因是:
spring-data-redis的RedisTemplate<K, V>模板類在操作redis時(shí)默認(rèn)使用JdkSerializationRedisSerializer來進(jìn)行序列化

因?yàn)閟pring操作redis是在jedis客戶端基礎(chǔ)上進(jìn)行的范抓,而jedis客戶端與redis交互的時(shí)候協(xié)議中定義是用byte類型交互,jedis中提供了string類型轉(zhuǎn)為byte[]類型食铐,
但是看到spring-data-redis中RedisTemplate<K, V>在操作的時(shí)候k匕垫,v是泛型的,所以RedisTemplate中有了上面那段代碼虐呻,在沒有特殊定義的情況下象泵,
spring默認(rèn)采用defaultSerializer = new JdkSerializationRedisSerializer();來對key,value進(jìn)行序列化操作斟叼。

把原來的

@Autowired
private RedisTemplate redisTemplate;

修改為:

private RedisTemplate redisTemplate;
@Autowired(required = false)
public void setRedisTemplate(RedisTemplate redisTemplate) {
    RedisSerializer stringSerializer = new StringRedisSerializer();
    redisTemplate.setKeySerializer(stringSerializer);
    redisTemplate.setValueSerializer(stringSerializer);
    redisTemplate.setHashKeySerializer(stringSerializer);
    redisTemplate.setHashValueSerializer(stringSerializer);
    this.redisTemplate = redisTemplate;
}

然后再試試就好了偶惠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朗涩,隨后出現(xiàn)的幾起案子忽孽,更是在濱河造成了極大的恐慌,老刑警劉巖谢床,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兄一,死亡現(xiàn)場離奇詭異,居然都是意外死亡识腿,警方通過查閱死者的電腦和手機(jī)出革,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渡讼,“玉大人骂束,你說我怎么就攤上這事〕审铮” “怎么了栖雾?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長伟众。 經(jīng)常有香客問我析藕,道長,這世上最難降的妖魔是什么凳厢? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任账胧,我火速辦了婚禮,結(jié)果婚禮上先紫,老公的妹妹穿的比我還像新娘治泥。我一直安慰自己,他們只是感情好遮精,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布居夹。 她就那樣靜靜地躺著败潦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪准脂。 梳的紋絲不亂的頭發(fā)上劫扒,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音狸膏,去河邊找鬼沟饥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛湾戳,可吹牛的內(nèi)容都是我干的贤旷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼砾脑,長吁一口氣:“原來是場噩夢啊……” “哼幼驶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起韧衣,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤县遣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后汹族,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡其兴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年顶瞒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片元旬。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡榴徐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匀归,到底是詐尸還是另有隱情坑资,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布穆端,位于F島的核電站袱贮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏体啰。R本人自食惡果不足惜攒巍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荒勇。 院中可真熱鬧柒莉,春花似錦、人聲如沸沽翔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至跨蟹,卻和暖如春雳殊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背喷市。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工相种, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人品姓。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓寝并,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腹备。 傳聞我的和親對象是個(gè)殘疾皇子衬潦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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