springboot接入cachecloud redis示例实践
最近项目中需要接入 RedisCacheCloud, CacheCloud是一个开源的Redis运维监控云平台,功能十分强大,支持Redis实例自动部署、扩容、碎片管理、统计、监控等功能,特别是支持单机、sentinel、cluster三种模式的自动部署,搭建redis集群一步到位轻松搞定。
java项目中接入CacheCloudredis的方式主要有两种。
第一种就是在CacheCloud上创建好redis实例后将对应的IP,端口直接配置以配置形式应用到项目中,优点是通用性好,原有项目改造成本低,不过万一后期CacheCloud上对redis进行管理扩容,那只能手动把每个项目的redis配置都改一遍了。
第二种CacheCloud上创建好实例后有一个对应的appId,程序调用CacheCloud平台的rest接口通过appId获取redis相关配置,将程序中的redis配置 统一交给CacheCloud平台去管理维护,后期管理和扩容及其方便,不过程序改造成本比较高。
现在采用第二种方式接入,工程采用springboot,redis采用哨兵模式,redis客户端主要用spring-data-redis和redisson, 接入流程如下:
添加配置到pom.xml文件
com.sohu.tv cachecloud-open-client-redis 1.0-SNAPSHOT com.sohu.tv cachecloud-open-client-basic 1.0-SNAPSHOT com.sohu.tv cachecloud-open-common 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-data-redis jedis redis.clients org.redisson redisson 3.9.0
准备配置文件 cacheCloudClient.properties,启动项目时 VM参数追加-Dcachecloud.config=配置文件路径
http_conn_timeout=3000 http_socket_timeout=5000 client_version=1.0-SNAPSHOT domain_url=http://192.168.33.221:8585#cachecloud实际路径 redis_cluster_suffix=/cache/client/redis/cluster/%s.json?clientVersion= redis_sentinel_suffix=/cache/client/redis/sentinel/%s.json?clientVersion= redis_standalone_suffix=/cache/client/redis/standalone/%s.json?clientVersion= cachecloud_report_url=/cachecloud/client/reportData.json
基本思路是先通过cachecloud的restapi接口获取并解析redis节点的配置信息,然后就可以按照传统的访问redis的方式进行初始化,获取RedisTemplate对象。
java代码如下:
importcom.alibaba.fastjson.JSONObject; importcom.sohu.tv.cachecloud.client.basic.heartbeat.ClientStatusEnum; importcom.sohu.tv.cachecloud.client.basic.util.ConstUtils; importcom.sohu.tv.cachecloud.client.basic.util.HttpUtils; importcom.sohu.tv.cachecloud.client.jedis.stat.ClientDataCollectReportExecutor; importlombok.Getter; importlombok.Setter; importorg.apache.commons.lang3.tuple.Pair; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.beans.factory.annotation.Value; importorg.springframework.stereotype.Component; importjavax.annotation.PostConstruct; importjava.util.HashSet; importjava.util.Random; importjava.util.Set; importjava.util.concurrent.TimeUnit; importjava.util.concurrent.locks.Lock; importjava.util.concurrent.locks.ReentrantLock; @Component publicclassRedisProperties{ publicstaticLoggerlogger=LoggerFactory.getLogger(RedisProperties.class); /** *构建锁 */ privatestaticfinalLockLOCK=newReentrantLock(); @Value("${cacheCloud.appId}")//cahcecloud开通redis实例应用id privateIntegerappId; @Getter @Setter privateStringmasterName; @Getter @Setter privateSet>sentinelSet=newHashSet<>(); privateBooleanclientStatIsOpen=true; @Getter @Setter privateStringpassword; privateBooleangetConfigSuccess=false; @PostConstruct publicvoidinit(){ while(true){ try{ LOCK.tryLock(10,TimeUnit.MILLISECONDS); if(!getConfigSuccess){ /** *http请求返回的结果是空的; */ Stringresponse=HttpUtils.doGet(String.format(ConstUtils.REDIS_SENTINEL_URL,appId)); if(response==null||response.isEmpty()){ logger.warn("getresponsefromremoteservererror,appId:{},continue...",appId); continue; } /** *http请求返回的结果是无效的; */ JSONObjectjsonObject=null; try{ jsonObject=JSONObject.parseObject(response); }catch(Exceptione){ logger.error("heartbeaterror,appId:{}.continue...",appId,e); } if(jsonObject==null){ logger.error("getsentinelinfoforappId:{}error.continue...",appId); continue; } intstatus=jsonObject.getIntValue("status"); Stringmessage=jsonObject.getString("message"); /**检查客户端版本**/ if(status==ClientStatusEnum.ERROR.getStatus()){ thrownewIllegalStateException(message); }elseif(status==ClientStatusEnum.WARN.getStatus()){ logger.warn(message); }else{ logger.info(message); } /** *有效的请求:取出masterName和sentinels; */ masterName=jsonObject.getString("masterName"); Stringsentinels=jsonObject.getString("sentinels"); for(StringsentinelStr:sentinels.split("")){ String[]sentinelArr=sentinelStr.split(":"); if(sentinelArr.length==2){ sentinelSet.add(Pair.of(sentinelArr[0],sentinelArr[1])); } } //收集上报数据 if(clientStatIsOpen){ ClientDataCollectReportExecutor.getInstance(); } password=jsonObject.getString("password"); getConfigSuccess=true; return; } }catch(Throwablee){//容错 logger.error("errorinbuild,appId:{}",appId,e); }finally{ LOCK.unlock(); } try{ TimeUnit.MILLISECONDS.sleep(200+newRandom().nextInt(1000));//活锁 }catch(InterruptedExceptione){ logger.error(e.getMessage(),e); } } } }
importcom.shunwang.buss.dispatchPay.provider.config.PropertiesUtil; importorg.apache.commons.lang3.StringUtils; importorg.redisson.Redisson; importorg.redisson.api.RedissonClient; importorg.redisson.config.Config; importorg.redisson.config.ReadMode; importorg.redisson.config.SentinelServersConfig; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.context.annotation.Primary; importorg.springframework.data.redis.connection.RedisConnectionFactory; importorg.springframework.data.redis.connection.RedisNode; importorg.springframework.data.redis.connection.RedisSentinelConfiguration; importorg.springframework.data.redis.connection.jedis.JedisConnectionFactory; importorg.springframework.data.redis.core.RedisTemplate; importorg.springframework.data.redis.serializer.StringRedisSerializer; importredis.clients.jedis.JedisPoolConfig; importjava.net.UnknownHostException; importjava.util.List; importjava.util.Set; importjava.util.stream.Collectors; importstaticjava.util.stream.Collectors.toList; @Configuration publicclassRedisConfig{ /** *JedisPoolConfig连接池 */ @Bean publicJedisPoolConfigjedisPoolConfig(RedisPropertiesproperties){ JedisPoolConfigjedisPoolConfig=newJedisPoolConfig(); //最大空闲数 jedisPoolConfig.setMaxIdle(20); //连接池的最大数据库连接数 jedisPoolConfig.setMaxTotal(20); //最大建立连接等待时间 jedisPoolConfig.setMaxWaitMillis(3000); returnjedisPoolConfig; } /** *配置redis的哨兵 */ @Bean publicRedisSentinelConfigurationsentinelConfiguration(RedisPropertiesproperties){ RedisSentinelConfigurationredisSentinelConfiguration=newRedisSentinelConfiguration(); //配置redis的哨兵sentinel SetredisNodeSet=properties.getSentinelSet().stream() .map(pair->newRedisNode(pair.getLeft(),Integer.parseInt(pair.getRight()))) .collect(Collectors.toSet()); redisSentinelConfiguration.setSentinels(redisNodeSet); redisSentinelConfiguration.setMaster(properties.getMasterName()); returnredisSentinelConfiguration; } /** *配置工厂 */ @Bean publicRedisConnectionFactoryjedisConnectionFactory(JedisPoolConfigjedisPoolConfig,RedisSentinelConfigurationsentinelConfig){ JedisConnectionFactoryjedisConnectionFactory=newJedisConnectionFactory(sentinelConfig,jedisPoolConfig); returnjedisConnectionFactory; } @Bean publicRedisTemplate
到这里我们已经在Spring中生成了RedisTemplate和 RedissonClient对象,无论是基本数据结构操作 还是分布式锁 都已经轻松支持了,具体使用就不展开了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。