一,redis如何实现锁的,wms csms两个项目到底用的哪一种方式?

1.1 wms 与springboot无关

wms JedisCluster 所属jar 

1.2 csms 属于springboot依赖

csms RedisTemplate 所属jar 

compile('org.springframework.boot:spring-boot-starter-redis')

还有跟下面这个依赖有区别吗

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>

二,具体如何实现,怎么连接配置信息的,有什么区别

2.1wms

通过RedisProperties加载配置信息,在通过属性配置实例化redis集群客户端JedisCluster,方法由客户端提供,底层实现

而csms中工具类方法,全部是springboot封装类RedisTemplate执行的,底层实现

集群配置

spring:  redis:clusterNodes:- 10.108.6.90:6179- 10.108.6.90:6279- 10.108.6.90:6379- 10.108.6.90:6479- 10.108.6.90:6579- 10.108.6.90:6679password: Allways_123expireSeconds: 120commandTimeout: 10000 #redis操作的超时时间pool:#最大连接数maxActive: 5000#最大空闲连接数maxIdle: 30#最小空闲连接数minIdle: 5#获取连接最大等待时间 ms #default -1maxWait: 10000#最大尝试连接数maxAttempts: 1

属性类

@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {private int expireSeconds;private List<String> clusterNodes = new ArrayList<String>();private String password;private int commandTimeout;private Map<String,Integer> pool = new HashMap<>();public int getExpireSeconds() {return expireSeconds;}public void setExpireSeconds(int expireSeconds) {this.expireSeconds = expireSeconds;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public int getCommandTimeout() {return commandTimeout;}public void setCommandTimeout(int commandTimeout) {this.commandTimeout = commandTimeout;}public Map<String, Integer> getPool() {return pool;}public void setPool(Map<String, Integer> pool) {this.pool = pool;}public List<String> getClusterNodes() {return clusterNodes;}public void setClusterNodes(List<String> clusterNodes) {this.clusterNodes = clusterNodes;}
}

配置类

@Configuration
public class JedisClusterConfig {@Autowiredprivate RedisProperties redisProperties;/*** 返回的JedisCluster是单例的,并且可以直接注入到其他类中去使用* @return*/@Beanpublic JedisCluster getJedisCluster() {Set<HostAndPort> nodes = new HashSet<>();List<String> clusterNodes = redisProperties.getClusterNodes();for (String ipPort : clusterNodes) {String[] ipPortPair = ipPort.split(":");nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));}GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();poolConfig.setMaxTotal(redisProperties.getPool().get("maxActive"));//最大连接数poolConfig.setMaxIdle(redisProperties.getPool().get("maxIdle"));//最大空闲连接数poolConfig.setMinIdle(redisProperties.getPool().get("minIdle"));//最小空闲连接数poolConfig.setMaxWaitMillis(redisProperties.getPool().get("maxWait").longValue());//连接最大等待时间return new JedisCluster(nodes,redisProperties.getCommandTimeout(),redisProperties.getCommandTimeout(),redisProperties.getPool().get("maxAttempts"),redisProperties.getPassword() ,poolConfig);//需要密码连接的创建对象方式}
}

工具类

@Component
public class RedisUtils {public static String                   REDIS_RECEIVE = "receive_";private static String redisCode = "utf-8";public static String                     REDIS_OURINV = "outinv_synchronized";private static final Long RELEASE_SUCCESS = 1L;public final static Logger logger = LogManager.getLogger(RedisUtils.class);@Autowiredprivate JedisCluster jedisCluster;/*** 设置缓存** @param key   缓存key* @param value 缓存value*/public void set(String key, String value) {jedisCluster.set(key, value);}/*** 设置缓存,并且自己指定过期时间** @param key* @param value* @param expireTime 过期时间*/public void setWithExpireTime(String key, String value, int expireTime) {jedisCluster.setex(key, expireTime, value);}/*** 设置失效时间** @param key* @param expireTime*/public void expire(String key, int expireTime) {jedisCluster.setex(key, expireTime, jedisCluster.get(key));}/*** 获取指定key的缓存** @param key*/public String get(String key) {String value = jedisCluster.get(key);return value;}//解决redis异常public String getThrowRedis(String key) {try {get(key);} catch (Exception e) {return null;}return get(key);}/*** 设置缓存对象** @param key        缓存key* @param obj        缓存value* @param expireTime 过期时间*/public <T> void setObject(String key, T obj, int expireTime) {jedisCluster.setex(key, expireTime, JSON.toJSONString(obj));}/*** 获取指定key的缓存** @param key---JSON.parseObject(value, User.class);*/public String getObject(String key) {return jedisCluster.get(key);}/*** 判断当前key值 是否存在** @param key*/public boolean hasKey(String key) {return jedisCluster.exists(key);}/*** 删除指定key的缓存** @param key*/public void delete(String key) {jedisCluster.del(key);}/*** <pre>* 上锁* </pre>** @param key*/public synchronized void lock(String key) {if (StringUtils.isBlank(key)) {return;}this.set(key, new Date().toString());}/*** <pre>* 上锁* </pre>** @param key*/public synchronized void lockWithExpireTime(String key, int seconds) {if (StringUtils.isBlank(key)) {return;}jedisCluster.setex(key, seconds, new Date().toString());}/*** <pre>* 判断key是否被锁住了* </pre>** @param key* @return*/public synchronized Boolean isLock(String key) {if (StringUtils.isBlank(key)) {return false;}String stringDate = this.get(key);if (StringUtils.isBlank(stringDate)) {return false;}return true;}/*** <pre>* 解锁* </pre>** @param key*/public synchronized void unLock(String key) {if (StringUtils.isBlank(key)) {return;}this.delete(key);}/*** <pre>* 递增* </pre>** @param key* @param by* @return*/public Long incr(String key, Long by) {//默认原子操作if (by == null) {by = 1l;}return jedisCluster.incrBy(key, by);}/*** <pre>** </pre>** @param key* @param value* @param liveTime*/public void set(String key, Object value, Long liveTime) {try {jedisCluster.setex(key.getBytes(redisCode), liveTime.intValue(), value.toString().getBytes(redisCode));} catch (UnsupportedEncodingException e) {e.printStackTrace();}}/*** <pre>* 批量删除keys* </pre>** @param keys*/public void delKeys(String[] keys) {if(keys != null) {for (String key : keys) {Long del = jedisCluster.del(key);System.out.println(del);}}}public void unlockValue(String keys, String value) {String lockValue = jedisCluster.get(keys);if (lockValue.equals(value)){jedisCluster.del(keys);}}public String[] keys(String pattern){TreeSet<String> keys = new TreeSet<>();Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes();for(String k : clusterNodes.keySet()){logger.debug("Getting keys from: {}", k);JedisPool jp = clusterNodes.get(k);Jedis connection = jp.getResource();try {keys.addAll(connection.keys(pattern));} catch(Exception e){logger.error("Getting keys error: {}", e);} finally{logger.debug("Connection closed.");connection.close();//用完一定要close这个链接!!!}}return keys.toArray(new String[] {});}/*** 设置缓存* @param key 缓存key* @param value 缓存value*/public Long setnx(String key, String value) {return jedisCluster.setnx(key, value);}/*** <pre>* 上锁* </pre>** @param key*/public synchronized boolean locknx(String key){if(StringUtils.isBlank(key)){return false;}Long result = this.setnx(key, new Date().toString());if(result.equals(0L)){//如果返回0 则该key已经存在return false;}return true;}/*** <pre>* 上锁* </pre>** @param key*/public synchronized boolean locknx(String key, String value){if(StringUtils.isBlank(key)){return false;}Long result = this.setnx(key, value);if(result.equals(0L)){//如果返回0 则该key已经存在return false;}this.expire(key, 60*3);//设置失效时间3分钟return true;}public synchronized boolean lock(String lockKey,String requestId,int expireTime) {String result=jedisCluster.set(lockKey, requestId, "NX", "PX", expireTime);if("OK".equals(result)) {return true;}return false;}public synchronized boolean releaseLock(String lockKey,String requestId) {String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";Object result = jedisCluster.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));if (RELEASE_SUCCESS.equals(result)) {return true;}return false;}
}

2.2csms

而csms中工具类方法,全部是springboot封装类RedisTemplate执行的,具体执行方法又是由RedisConnection这个类完成

读取配置文件信息,还需要定义properties属性类吗,不可以从autoconfigtion中定义的直接读取吗,就算从这读取了,读取原理是什么,怎么用的?

单机配置

redis:database: 0host: 10.108.2.202port: 6379password: allways_123pool:#最大连接数max-active: 5000#获取连接最大等待时间 ms #default -1max-wait: 10000#最大空闲连接数max-idle: 30#最小空闲连接数min-idle: 5timeout: 0

工具类

package com.anji.allways.base.redis;import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;import javax.annotation.Resource;import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.SerializationUtils;/*** <pre>* RedisUtils* </pre>** @author wanglong* @version $Id: RedisUtils.java, v 0.1 2018年3月16日 上午9:40:56 wanglong Exp $*/
@Configuration
public class RedisUtils {@Resourceprivate RedisTemplate<String, String> redisTemplate;private static String                 redisCode = "utf-8";/*** 默认过期时长,单位:秒*/public static final long DEFAULT_EXPIRE = 60 * 3;/*** @param keys*            k* @return l*/public long del(final String... keys) {return redisTemplate.execute(new RedisCallback<Long>() {public Long doInRedis(RedisConnection connection) throws DataAccessException {long result = 0;for (int i = 0; i < keys.length; i++) {try {result += connection.del(keys[i].getBytes(redisCode));} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return result;}});}/*** @since 1.0* @param key*            k* @param value*            v* @param liveTime*/public void set(final byte[] key, final byte[] value, final long liveTime) {redisTemplate.execute(new RedisCallback<Long>() {public Long doInRedis(RedisConnection connection) throws DataAccessException {connection.set(key, value);if (liveTime > 0) {connection.expire(key, liveTime);}return 1L;}});}/*** @since 1.0* @param key*            k* @param value*            v* @param liveTime*/public void set(String key, String value, long liveTime) {try {this.set(key.getBytes(redisCode), value.getBytes(redisCode), liveTime);} catch (UnsupportedEncodingException e) {e.printStackTrace();}}/*** @param key*            k* @param value*            v*/public void set(String key, String value) {this.set(key, value, 0L);}/*** @param key*            k* @param value*            v*/public void set(byte[] key, byte[] value) {this.set(key, value, 0L);}/*** @param key*            l* @return s*/public String get(final String key) {return redisTemplate.execute(new RedisCallback<String>() {public String doInRedis(RedisConnection connection) throws DataAccessException {try {byte[] data = connection.get(key.getBytes(redisCode));if (data != null) {return new String(data, redisCode);}} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}});}/*** @param pattern*            p* @return set*/public Set<String> keys(String pattern) {return redisTemplate.keys(pattern);}/*** @param key*            k* @return b*/public boolean exists(final String key) {return redisTemplate.execute(new RedisCallback<Boolean>() {public Boolean doInRedis(RedisConnection connection) throws DataAccessException {try {return connection.exists(key.getBytes(redisCode));} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}return false;}});}/*** @return s*/public String flushDB() {return flush();}public String flush() {return redisTemplate.execute(new RedisCallback<String>() {public String doInRedis(RedisConnection connection) throws DataAccessException {connection.flushDb();return "ok";}});}/*** @return l*/public long dbSize() {return dbs();}public long dbs() {return redisTemplate.execute(new RedisCallback<Long>() {public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.dbSize();}});}/*** @return s*/public String ping() {return pingRedis();}public String pingRedis() {return redisTemplate.execute(new RedisCallback<String>() {public String doInRedis(RedisConnection connection) throws DataAccessException {return connection.ping();}});}/*** @since 1.0* @param key*            k* @return*/public Object getObject(final String key) {return SerializationUtils.deserialize(redisTemplate.execute(new RedisCallback<byte[]>() {public byte[] doInRedis(RedisConnection connection) throws DataAccessException {try {return connection.get(key.getBytes(redisCode));} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}byte[] str = null;return str;}}));}/*** 将 key 的值设为 value ,当且仅当 key 不存在。 <br>* 若给定的 key 已经存在,则 SETNX 不做任何动作。* @param key* @param value* @return 设置成功,返回 1 。 设置失败,返回 0 。*/public boolean setNX(final String key, final String value) {Object obj = null;try {obj = redisTemplate.execute(new RedisCallback<Object>() {@Overridepublic Object doInRedis(RedisConnection connection) throws DataAccessException {StringRedisSerializer serializer = new StringRedisSerializer();Boolean success = connection.setNX(serializer.serialize(key), serializer.serialize(value));connection.close();return success;}});} catch (Exception e) {e.printStackTrace();}return obj != null ? (Boolean) obj : false;}/*** 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。<br>* 当 key 存在但不是字符串类型时,返回一个错误。* @param key* @param value* @return 返回给定 key 的旧值。 当 key 没有旧值时,也即是, key 不存在时,返回 null 。*/public String getSet(final String key, final String value) {Object obj = null;try {obj = redisTemplate.execute(new RedisCallback<Object>() {@Overridepublic Object doInRedis(RedisConnection connection) throws DataAccessException {StringRedisSerializer serializer = new StringRedisSerializer();byte[] ret = connection.getSet(serializer.serialize(key), serializer.serialize(value));connection.close();return serializer.deserialize(ret);}});} catch (Exception e) {e.printStackTrace();}return obj != null ? (String) obj : null;}/*** 递增* @param key* @param by* @return value*/public Long incr(String key,Long by) {//默认原子操作if(by == null) {by = 1l;}return redisTemplate.opsForValue().increment(key, by);}/*** 递增* @param key* @param by* @return value*/public Long decr(String key,Long by) {return redisTemplate.opsForValue().increment(key, -by);}/*** <pre>* 上锁* </pre>** @param key*/public synchronized void lock(String key){if(StringUtils.isBlank(key)){return;}this.set(key, new Date().toString());}/*** <pre>* 判断key是否被锁住了* </pre>** @param key* @return*/public synchronized Boolean isLock(String key){if(StringUtils.isBlank(key)){return false;}String stringDate = this.get(key);if(StringUtils.isBlank(stringDate)){return false;}return true;}/*** <pre>* 解锁* </pre>** @param key*/public synchronized void unLock(String key){if(StringUtils.isBlank(key)){return;}this.del(key);}/*** <pre>* 上锁 NX 加三分钟过期时间* ,上锁成功返回true,失败false* </pre>** @param key*/public synchronized boolean locknx(String key){if(StringUtils.isBlank(key)){return false;}boolean setNX = this.setNX(key, new Date().toString());//设置过期时间,三分钟this.redisTemplate.expire(key,DEFAULT_EXPIRE,TimeUnit.SECONDS);return setNX;}/*** 设置缓存,并且自己指定过期时间(废弃)* @param key* @param value* @param expireTime(秒)*/public void setWithExpireTime(String key, String value, int expireTime) {this.setNX(key, value);this.redisTemplate.expire(key,expireTime,TimeUnit.SECONDS);}/*** 判断当前key值 是否存在** @param key*/   public boolean hasKey(String key) {String stringDate = this.get(key);if(StringUtils.isBlank(stringDate)){return false;}return true;}/*** 刷新缓存时间* @param key* @param expireTime*/public void expire(String key, int expireTime){this.setNX(key, this.get(key));this.redisTemplate.expire(key,expireTime,TimeUnit.SECONDS);}}

reids实现分布式锁两种方式,单机,集群相关推荐

  1. 还不会使用分布式锁?教你三种分布式锁实现的方式

    摘要:在单进程的系统中,当存在多个线程可以同时改变某个变量时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量,而同步本质上通过锁来实现. 本文分享自华为云社区<还不 ...

  2. 开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型...

    开启子进程的两种方式 # # # 方式一: # from multiprocessing import Process # import time # # def task(x): # print(' ...

  3. 思科新版EI CCIE 企业网软定义中的VxLAN分布式网关两种部署方式

    思科新版EI CCIE 企业网软定义中的VxLAN分布式网关两种部署方式VXLAN集中式网关部署的不足:第一,同一二层网关下跨子网的数据中心三层流量都需要经过集中三层网关转发.第二,由于采用了集中三层 ...

  4. 浅析“分布式锁”的实现方式丨C++后端开发丨底层原理

    线程锁.进程锁以及分布式锁相关视频讲解:详解线程锁.进程锁以及分布式锁 如何高效学习使用redis相关视频讲解:10年大厂程序员是如何高效学习使用redis Linux服务器开发高级架构学习视频:C/ ...

  5. 根据官网文档看Spark Streaming对接Kafka的两种方式, 以及如何实现Exactly Once语义

    注: 本文算是本人的学习记录, 中间可能有些知识点并不成熟, 不能保证正确性. 只能算是对官网文档作了个翻译和解读, 随时有可能回来更新和纠错 上一篇文章讨论了Spark Streaming的WAL( ...

  6. sock 文件方式控制宿主机_nginx与php-fpm通信的两种方式

    简述 在linux中,nginx服务器和php-fpm可以通过tcp socket和unix socket两种方式实现. unix socket是一种终端,可以使同一台操作系统上的两个或多个进程进行数 ...

  7. Spring加载properties文件的两种方式

    2019独角兽企业重金招聘Python工程师标准>>> 在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取pro ...

  8. mysql不停止重启服务器_不停止MySQL服务增加从库的两种方式

    现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...

  9. python: 多线程实现的两种方式及让多条命令并发执行

    一 概念介绍 Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法:另一种是创建一个threading. ...

  10. mysql增加从库_不停止MySQL服务增加从库的两种方式 (装载)

    现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...

最新文章

  1. Linux 探索之旅 | 第五部分第五课:循环往复,Shell 开路
  2. 基于 WebSocket 的 MQTT 移动推送方案
  3. $ npm install时候报出:npm ERR! Unexpected token in JSON at position 10841
  4. ActiveMQ简述
  5. 【miscellaneous】语音识别工具箱综述和产品介绍
  6. java基础源码 (2)--StringBuilder类
  7. 【Android病毒分析报告】- 手机支付毒王“银行悍匪”的前世今生
  8. 云桌面终端CT3200,硬件与信号连接
  9. 飞鹅WiFi打印机配置,php调用接口
  10. 世界杯ing~这不来个实时数据可视化?(结尾附源码)
  11. 一.pandas的导入读取
  12. asp.net core 防止机密信息外泄GitHub
  13. 输入法中表情和小图标的应用
  14. 微服务架构设计总结实践篇,10 步搭建微服务
  15. 基于SSM社区网格化小区管理系统设计
  16. Python3 解决编码问题: UnicodeEncodeError: 'gbk' codec can't encode character '\xa9' in position
  17. android 全屏广告,手机端全屏广告展示问题
  18. matlab 将子文件下同名称文件移植到同一文件夹下并按序排列重命名n.bmp,n=1,2,3...
  19. 你好法语A1语法单元汇总(unité 4)
  20. python入门指南 许半仙txt百度云-《漩涡》TXT全本 百度云网盘下载 by就不告诉你...

热门文章

  1. Linux下l2tp客户端xl2tpd安装配置的具体操作
  2. I.MX6 CAAM
  3. 抓住“智慧城市”的机遇
  4. 基于SpringMVC国际化资源配置方式
  5. OpenCV】透视变换 Perspective Transformation(续)
  6. 戴尔软件部门第一弹 收购备份公司AppAssure
  7. uboot引导内核全过程
  8. Wireshark实战分析之ICMP协议(二)
  9. X86-64和ARM64用户栈的结构 (1) ---背景介绍
  10. Ubuntu的LTS 18.04 安装FRR