分布式锁的演进与讲解

This commit is contained in:
qiurunze123 2018-11-11 10:48:03 +08:00
parent 5a8573ba8e
commit a07f9a4cba
28 changed files with 1395 additions and 611 deletions

File diff suppressed because it is too large Load Diff

View File

@ -136,3 +136,16 @@ redis的数量不是库存,他的作用仅仅只是为了阻挡多余的请求
测试(test) 测试(test)
线上(prod) 线上(prod)
在环境部署中为了防止人工修改的弊端! spring.profiles.active=@activatedProperties@ 在环境部署中为了防止人工修改的弊端! spring.profiles.active=@activatedProperties@
### redis 分布式锁实现方法
我用了四种方法 分别指出了不同版本的缺陷以及演进的过程 orderclosetask
v1---->>版本没有操作,在分布式系统中会造成同一时间,资源浪费而且很容易出现并发问题
V2--->>版本加了分布式redis锁在访问核心方法前加入redis锁可以阻塞其他线程访问,可以
很好的处理并发问题,但是缺陷就是如果机器突然宕机,或者线路波动等,就会造成死锁,一直
不释放等问题
V3版本-->>很好的解决了这个问题v2的问题就是加入时间对比如果当前时间已经大与释放锁的时间
说明已经可以释放这个锁重新在获取锁setget方法可以把之前的锁去掉在重新获取,旧值在于之前的
值比较如果无变化说明这个期间没有人获取或者操作这个redis锁则可以重新获取
V4---->>采用成熟的框架redisson,封装好的方法则可以直接处理但是waittime记住要这只为0

View File

@ -40,7 +40,7 @@
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" /> <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" /> <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.12.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.12.RELEASE" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" /> <orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.17" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.8.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" /> <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" /> <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" />
@ -51,7 +51,6 @@
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" /> <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" /> <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" /> <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.12.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.12.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.12.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.12.RELEASE" level="project" />
@ -93,6 +92,26 @@
<orderEntry type="library" name="Maven: org.springframework.retry:spring-retry:1.2.1.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework.retry:spring-retry:1.2.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.amqp:spring-amqp:1.7.4.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework.amqp:spring-amqp:1.7.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.12.RELEASE" level="project" /> <orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.12.RELEASE" level="project" />
<orderEntry type="library" name="Maven: joda-time:joda-time:2.3" level="project" />
<orderEntry type="library" name="Maven: org.redisson:redisson:2.14.0" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver-dns:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-dns:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.30.Final" level="project" />
<orderEntry type="library" name="Maven: javax.cache:cache-api:1.0.0" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor:reactor-stream:2.0.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:2.0.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.reactivex.rxjava2:rxjava:2.1.13" level="project" />
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.8.10" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.8.17" level="project" />
<orderEntry type="library" name="Maven: org.jodd:jodd-bean:3.7.1" level="project" />
<orderEntry type="library" name="Maven: org.jodd:jodd-core:3.7.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.2" level="project" /> <orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.2" level="project" />
</component> </component>
</module> </module>

11
pom.xml
View File

@ -117,6 +117,17 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId> <artifactId>spring-boot-starter-amqp</artifactId>
</dependency> </dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.14.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -2,8 +2,10 @@ package com.geekq.miaosha;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableScheduling
public class GeekQMainApplication { public class GeekQMainApplication {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {

View File

@ -0,0 +1,23 @@
package com.geekq.miaosha.common;
public class Constanst {
public static String CLOSE_ORDER_INFO_TASK_LOCK = "CLOSE_ORDER_INFO_KEY";
public enum orderStaus{
ORDER_NOT_PAY("新建未支付");
orderStaus(String name){
this.name=name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -4,6 +4,8 @@ import com.geekq.miaosha.domain.MiaoshaOrder;
import com.geekq.miaosha.domain.OrderInfo; import com.geekq.miaosha.domain.OrderInfo;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper @Mapper
public interface OrderDao { public interface OrderDao {
@ -21,5 +23,9 @@ public interface OrderDao {
@Select("select * from order_info where id = #{orderId}") @Select("select * from order_info where id = #{orderId}")
public OrderInfo getOrderById(@Param("orderId")long orderId); public OrderInfo getOrderById(@Param("orderId")long orderId);
@Select("select * from order_info where status=#{status} and create_Date<=#{createDate}")
public List<OrderInfo> selectOrderStatusByCreateTime(@Param("status")Integer status, @Param("createDate") String createDate);
@Select("update order_info set status=0 where id=#{id}")
public int closeOrderByOrderInfo();
} }

View File

@ -0,0 +1,14 @@
package com.geekq.miaosha.redis;
import java.util.concurrent.TimeUnit;
public interface DistributedLocker {
void lock(String lockKey);
void unlock(String lockKey);
void lock(String lockKey, int timeout);
void lock(String lockKey, TimeUnit unit , int timeout);
}

View File

@ -1,22 +1,64 @@
package com.geekq.miaosha.redis; package com.geekq.miaosha.redis;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis; import redis.clients.jedis.*;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service @Service
@Slf4j
public class RedisService { public class RedisService {
@Autowired @Autowired
JedisPool jedisPool; JedisPool jedisPool;
/**
* 设置失效时间
* @param key
* @param value
* @return
*/
public Long setnx(String key ,String value){
Jedis jedis =null;
Long result = null;
try {
jedis = jedisPool.getResource();
result = jedis.setnx(key,value);
}catch (Exception e){
log.error("expire key:{} error",key,e);
jedisPool.returnResource(jedis);
return result;
}
jedisPool.returnResource(jedis);
return result;
}
/**
* 设置key的有效期单位是秒
* @param key
* @param exTime
* @return
*/
public Long expire(String key,int exTime){
Jedis jedis = null;
Long result = null;
try {
jedis = jedisPool.getResource();
result = jedis.expire(key,exTime);
} catch (Exception e) {
log.error("expire key:{} error",key,e);
jedisPool.returnBrokenResource(jedis);
return result;
}
jedisPool.returnResource(jedis);
return result;
}
/** /**
* 获取当个对象 * 获取当个对象
* */ * */
@ -34,6 +76,36 @@ public class RedisService {
} }
} }
public String get(String key){
Jedis jedis = null;
String result = null;
try {
jedis = jedisPool.getResource();
result = jedis.get(key);
} catch (Exception e) {
log.error("expire key:{} error",key,e);
jedisPool.returnBrokenResource(jedis);
return result;
}
jedisPool.returnResource(jedis);
return result;
}
public String getset(String key,String value){
Jedis jedis = null;
String result = null;
try {
jedis = jedisPool.getResource();
result = jedis.getSet(key,value);
} catch (Exception e) {
log.error("expire key:{} error",key,e);
jedisPool.returnBrokenResource(jedis);
return result;
}
jedisPool.returnResource(jedis);
return result;
}
/** /**
* 设置对象 * 设置对象
* */ * */
@ -120,6 +192,22 @@ public class RedisService {
} }
} }
public Long del(String key){
Jedis jedis = null;
Long result = null;
try {
jedis = jedisPool.getResource();
result = jedis.del(key);
} catch (Exception e) {
log.error("del key:{} error",key,e);
jedisPool.returnBrokenResource(jedis);
return result;
}
jedisPool.returnResource(jedis);
return result;
}
public boolean delete(KeyPrefix prefix) { public boolean delete(KeyPrefix prefix) {
if(prefix == null) { if(prefix == null) {
return false; return false;

View File

@ -0,0 +1,42 @@
package com.geekq.miaosha.redis;
import java.util.concurrent.TimeUnit;
/**
* redis分布式锁帮助类
*
*/
public class RedissLockUtil {
private static DistributedLocker redissLock;
public static void setLocker(DistributedLocker locker) {
redissLock = locker;
}
public static void lock(String lockKey) {
redissLock.lock(lockKey);
}
public static void unlock(String lockKey) {
redissLock.unlock(lockKey);
}
/**
* 带超时的锁
* @param lockKey
* @param timeout 超时时间 单位
*/
public static void lock(String lockKey, int timeout) {
redissLock.lock(lockKey, timeout);
}
/**
* 带超时的锁
* @param lockKey
* @param unit 时间单位
* @param timeout 超时时间
*/
public static void lock(String lockKey, TimeUnit unit , int timeout) {
redissLock.lock(lockKey, unit, timeout);
}
}

View File

@ -0,0 +1,76 @@
package com.geekq.miaosha.redis;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {
@Autowired
private RedissonProperties redssionProperties;
/**
* 哨兵模式自动装配
* @return
*/
@Bean
@ConditionalOnProperty(name="redisson.master-name")
RedissonClient redissonSentinel() {
Config config = new Config();
SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redssionProperties.getSentinelAddresses())
.setMasterName(redssionProperties.getMasterName())
.setTimeout(redssionProperties.getTimeout())
.setMasterConnectionPoolSize(redssionProperties.getMasterConnectionPoolSize())
.setSlaveConnectionPoolSize(redssionProperties.getSlaveConnectionPoolSize());
if(StringUtils.isNotBlank(redssionProperties.getPassword())) {
serverConfig.setPassword(redssionProperties.getPassword());
}
return Redisson.create(config);
}
/**
* 单机模式自动装配
* @return
*/
@Bean
@ConditionalOnProperty(name="redisson.address")
RedissonClient redissonSingle() {
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redssionProperties.getAddress())
.setTimeout(redssionProperties.getTimeout())
.setConnectionPoolSize(redssionProperties.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize());
if(StringUtils.isNotBlank(redssionProperties.getPassword())) {
serverConfig.setPassword(redssionProperties.getPassword());
}
return Redisson.create(config);
}
/**
* 装配locker类并将实例注入到RedissLockUtil中
* @return
*/
@Bean
DistributedLocker distributedLocker(RedissonClient redissonSingle) {
RedissonDistributedLocker locker = new RedissonDistributedLocker();
locker.setRedissonClient(redissonSingle);
RedissLockUtil.setLocker(locker);
return locker;
}
}

View File

@ -0,0 +1,39 @@
package com.geekq.miaosha.redis;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class RedissonDistributedLocker implements DistributedLocker {
private RedissonClient redissonClient;
@Override
public void lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
}
@Override
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
@Override
public void lock(String lockKey, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
}
@Override
public void lock(String lockKey, TimeUnit unit ,int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
}
public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
}

View File

@ -0,0 +1,98 @@
package com.geekq.miaosha.redis;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {
private int timeout = 3000;
private String address;
private String password;
private int connectionPoolSize = 64;
private int connectionMinimumIdleSize=10;
private int slaveConnectionPoolSize = 250;
private int masterConnectionPoolSize = 250;
private String[] sentinelAddresses;
private String masterName;
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getSlaveConnectionPoolSize() {
return slaveConnectionPoolSize;
}
public void setSlaveConnectionPoolSize(int slaveConnectionPoolSize) {
this.slaveConnectionPoolSize = slaveConnectionPoolSize;
}
public int getMasterConnectionPoolSize() {
return masterConnectionPoolSize;
}
public void setMasterConnectionPoolSize(int masterConnectionPoolSize) {
this.masterConnectionPoolSize = masterConnectionPoolSize;
}
public String[] getSentinelAddresses() {
return sentinelAddresses;
}
public void setSentinelAddresses(String sentinelAddresses) {
this.sentinelAddresses = sentinelAddresses.split(",");
}
public String getMasterName() {
return masterName;
}
public void setMasterName(String masterName) {
this.masterName = masterName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getConnectionPoolSize() {
return connectionPoolSize;
}
public void setConnectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
}
public int getConnectionMinimumIdleSize() {
return connectionMinimumIdleSize;
}
public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) {
this.connectionMinimumIdleSize = connectionMinimumIdleSize;
}
}

View File

@ -0,0 +1,146 @@
package com.geekq.miaosha.redis;
import org.redisson.api.*;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
/**
* redisson操作类
*/
@Service("redissonService")
public class RedissonService {
@Autowired
private RedissonClient redissonClient;
public void getRedissonClient() throws IOException {
Config config = redissonClient.getConfig();
System.out.println(config.toJSON().toString());
}
/**`
* 获取字符串对象
*
* @param objectName
* @return
*/
public <T> RBucket<T> getRBucket(String objectName) {
RBucket<T> bucket = redissonClient.getBucket(objectName);
return bucket;
}
/**
* 获取Map对象
*
* @param objectName
* @return
*/
public <K, V> RMap<K, V> getRMap(String objectName) {
RMap<K, V> map = redissonClient.getMap(objectName);
return map;
}
/**
* 获取有序集合
*
* @param objectName
* @return
*/
public <V> RSortedSet<V> getRSortedSet(String objectName) {
RSortedSet<V> sortedSet = redissonClient.getSortedSet(objectName);
return sortedSet;
}
/**
* 获取集合
*
* @param objectName
* @return
*/
public <V> RSet<V> getRSet(String objectName) {
RSet<V> rSet = redissonClient.getSet(objectName);
return rSet;
}
/**
* 获取列表
*
* @param objectName
* @return
*/
public <V> RList<V> getRList(String objectName) {
RList<V> rList = redissonClient.getList(objectName);
return rList;
}
/**
* 获取队列
*
* @param objectName
* @return
*/
public <V> RQueue<V> getRQueue(String objectName) {
RQueue<V> rQueue = redissonClient.getQueue(objectName);
return rQueue;
}
/**
* 获取双端队列
*
* @param objectName
* @return
*/
public <V> RDeque<V> getRDeque(String objectName) {
RDeque<V> rDeque = redissonClient.getDeque(objectName);
return rDeque;
}
/**
* 获取锁
*
* @param objectName
* @return
*/
public RLock getRLock(String objectName) {
RLock rLock = redissonClient.getLock(objectName);
return rLock;
}
/**
* 获取读取锁
*
* @param objectName
* @return
*/
public RReadWriteLock getRWLock(String objectName) {
RReadWriteLock rwlock = redissonClient.getReadWriteLock(objectName);
return rwlock;
}
/**
* 获取原子数
*
* @param objectName
* @return
*/
public RAtomicLong getRAtomicLong(String objectName) {
RAtomicLong rAtomicLong = redissonClient.getAtomicLong(objectName);
return rAtomicLong;
}
/**
* 获取记数锁
*
* @param objectName
* @return
*/
public RCountDownLatch getRCountDownLatch(String objectName) {
RCountDownLatch rCountDownLatch = redissonClient.getCountDownLatch(objectName);
return rCountDownLatch;
}
}

View File

@ -6,12 +6,17 @@ import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.domain.OrderInfo; import com.geekq.miaosha.domain.OrderInfo;
import com.geekq.miaosha.redis.OrderKey; import com.geekq.miaosha.redis.OrderKey;
import com.geekq.miaosha.redis.RedisService; import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.utils.DateTimeUtils;
import com.geekq.miaosha.vo.GoodsVo; import com.geekq.miaosha.vo.GoodsVo;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.Date; import java.util.Date;
import java.util.List;
import static com.geekq.miaosha.common.Constanst.orderStaus.ORDER_NOT_PAY;
@Service @Service
public class OrderService { public class OrderService {
@ -52,6 +57,13 @@ public class OrderService {
return orderInfo; return orderInfo;
} }
public void closeOrder(int hour){
Date closeDateTime = DateUtils.addHours(new Date(),-hour);
List<OrderInfo> orderInfoList = orderDao.selectOrderStatusByCreateTime(Integer.valueOf(ORDER_NOT_PAY.ordinal()), DateTimeUtils.dateToStr(closeDateTime));
for (OrderInfo orderInfo:orderInfoList){
System.out.println("orderinfo infomation "+orderInfo.getGoodsName());
}
}
} }

View File

@ -0,0 +1,114 @@
package com.geekq.miaosha.timeTask;
import com.geekq.miaosha.dao.OrderDao;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.redis.RedissonService;
import com.geekq.miaosha.service.OrderService;
import jodd.util.PropertiesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import static com.geekq.miaosha.common.Constanst.CLOSE_ORDER_INFO_TASK_LOCK;
@Component
@Slf4j
public class OrderCloseTask {
@Autowired
private OrderDao orderDao ;
@Autowired
private RedisService redisService;
@Autowired
private OrderService orderService;
@Autowired
private RedissonService redissonService;
// @Scheduled(cron = "0/1 * * * * ?")
private void closeOrderTaskv1(){
int hour = 2;
orderService.closeOrder(hour);
log.info("关闭订单定时任务结束");
}
// @Scheduled(cron = "0/1 * * * * ?")
// public void closeOrderTaskV2(){
// log.info("关闭订单定时任务启动");
// long lockTime = 5000;
// Long setnxResult = redisService.setnx(CLOSE_ORDER_INFO_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTime));
// //代表获取了锁
// if(setnxResult !=null && setnxResult ==1){
// closeOrder(CLOSE_ORDER_INFO_TASK_LOCK);
// }else {
// log.info("没有获得分布式锁:{}",CLOSE_ORDER_INFO_TASK_LOCK);
// }
// log.info("关闭订单定时任务结束");
// }
// @Scheduled(cron = "0/1 * * * * ?")
// public void closeOrderTaskV3(){
// log.info("关闭订单定时任务启动");
// long lockTime = 5000;
// Long setnxResult = redisService.setnx(CLOSE_ORDER_INFO_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTime));
// //代表获取了锁
// if(setnxResult !=null && setnxResult ==1){
// closeOrder(CLOSE_ORDER_INFO_TASK_LOCK);
// }else {
// log.info("没有获得分布式锁:{}",CLOSE_ORDER_INFO_TASK_LOCK);
// String lockValueStr = redisService.get(CLOSE_ORDER_INFO_TASK_LOCK);
// if(lockValueStr!=null&&System.currentTimeMillis() > Long.parseLong(lockValueStr)){
// //把之前的释放在新加入锁
// String getSetResult = redisService.getset(CLOSE_ORDER_INFO_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTime));
//
// if(getSetResult == null || (getSetResult != null && StringUtils.equals(lockValueStr,getSetResult))){
// closeOrder(CLOSE_ORDER_INFO_TASK_LOCK);
// }else {
// log.info("没有获取到分布式锁:{}",CLOSE_ORDER_INFO_TASK_LOCK);
// }
// }else {
// log.info("没有获取到分布式锁:{}",CLOSE_ORDER_INFO_TASK_LOCK);
// }
// }
// log.info("关闭订单定时任务结束");
// }
@Scheduled(cron="0 */1 * * * ?")
public void closeOrderTaskV4(){
RLock lock = redissonService.getRLock(CLOSE_ORDER_INFO_TASK_LOCK);
boolean getLock = false;
try {
if(getLock = lock.tryLock(0,50, TimeUnit.SECONDS)){
log.info("Redisson获取到分布式锁:{},ThreadName:{}",CLOSE_ORDER_INFO_TASK_LOCK,Thread.currentThread().getName());
int hour = 2;
// iOrderService.closeOrder(hour);
}else{
log.info("Redisson没有获取到分布式锁:{},ThreadName:{}",CLOSE_ORDER_INFO_TASK_LOCK,Thread.currentThread().getName());
}
} catch (InterruptedException e) {
log.error("Redisson分布式锁获取异常",e);
} finally {
if(!getLock){
return;
}
lock.unlock();
log.info("Redisson分布式锁释放锁");
}
}
private void closeOrder(String lockName){
redisService.expire(lockName,5);
log.info("获取{},当前线程名称!" ,lockName,Thread.currentThread().getName());
int hour = 2;
orderService.closeOrder(hour);
redisService.del(CLOSE_ORDER_INFO_TASK_LOCK);
log.info("===============================");
}
}

View File

@ -0,0 +1,61 @@
package com.geekq.miaosha.utils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.util.Date;
/**
* Created by geely
*/
public class DateTimeUtils {
//joda-time
//str->Date
//Date->str
public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static Date strToDate(String dateTimeStr,String formatStr){
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr);
DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
return dateTime.toDate();
}
public static String dateToStr(Date date,String formatStr){
if(date == null){
return StringUtils.EMPTY;
}
DateTime dateTime = new DateTime(date);
return dateTime.toString(formatStr);
}
public static Date strToDate(String dateTimeStr){
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(STANDARD_FORMAT);
DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
return dateTime.toDate();
}
public static String dateToStr(Date date){
if(date == null){
return StringUtils.EMPTY;
}
DateTime dateTime = new DateTime(date);
return dateTime.toString(STANDARD_FORMAT);
}
public static void main(String[] args) {
System.out.println(DateTimeUtils.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss"));
System.out.println(DateTimeUtils.strToDate("2010-01-01 11:11:11","yyyy-MM-dd HH:mm:ss"));
}
}

View File

@ -44,13 +44,17 @@ spring.resources.chain.gzipped=true
spring.resources.chain.html-application-cache=true spring.resources.chain.html-application-cache=true
spring.resources.static-locations=classpath:/static/ spring.resources.static-locations=classpath:/static/
#redis #redis
redis.host=192.168.1.116 redis.host=localhost
redis.port=6379 redis.port=6379
redis.timeout=100 redis.timeout=100
redis.password=123456 redis.password=123456
redis.poolMaxTotal=1000 redis.poolMaxTotal=1000
redis.poolMaxIdle=500 redis.poolMaxIdle=500
redis.poolMaxWait=500 redis.poolMaxWait=500
# redisson lock
redisson.address=redis://localhost:6379
redisson.password=123456
#rabbitmq #rabbitmq
spring.rabbitmq.host=localhost spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672 spring.rabbitmq.port=5672

View File

@ -44,13 +44,17 @@ spring.resources.chain.gzipped=true
spring.resources.chain.html-application-cache=true spring.resources.chain.html-application-cache=true
spring.resources.static-locations=classpath:/static/ spring.resources.static-locations=classpath:/static/
#redis #redis
redis.host=192.168.1.116 redis.host=localhost
redis.port=6379 redis.port=6379
redis.timeout=100 redis.timeout=100
redis.password=123456 redis.password=123456
redis.poolMaxTotal=1000 redis.poolMaxTotal=1000
redis.poolMaxIdle=500 redis.poolMaxIdle=500
redis.poolMaxWait=500 redis.poolMaxWait=500
# redisson lock
redisson.address=redis://localhost:6379
redisson.password=123456
#rabbitmq #rabbitmq
spring.rabbitmq.host=localhost spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672 spring.rabbitmq.port=5672

View File

@ -1,5 +0,0 @@
#Generated by Apache Maven
#Sat Oct 27 23:31:07 CST 2018
version=0.0.1-SNAPSHOT
groupId=com.geekq
artifactId=miaosha

View File

@ -1,66 +0,0 @@
com/geekq/miaosha/domain/MiaoshaUser.class
com/geekq/miaosha/controller/RateLimiterController.class
com/geekq/miaosha/redis/MiaoshaKey.class
com/geekq/miaosha/common/ServerResponse.class
com/geekq/miaosha/service/MiaoShaUserService.class
com/geekq/miaosha/rabbitmq/MQReceiver.class
com/geekq/miaosha/controller/OrderController.class
com/geekq/miaosha/config/WebConfig.class
com/geekq/miaosha/mybatis/controller/MessageController.class
com/geekq/miaosha/dao/UserMapper.class
com/geekq/miaosha/service/IUserService.class
com/geekq/miaosha/exception/GlobleExceptionandler.class
com/geekq/miaosha/rabbitmq/MiaoshaMessage.class
com/geekq/miaosha/access/UserContext.class
com/geekq/miaosha/result/Result.class
com/geekq/miaosha/controller/DemoController.class
com/geekq/miaosha/vo/GoodsDetailVo.class
com/geekq/miaosha/service/GoodsService.class
com/geekq/miaosha/DemoTask$2.class
com/geekq/miaosha/redis/RedisService.class
com/geekq/miaosha/dao/DruidConfig.class
com/geekq/miaosha/controller/LoginController.class
com/geekq/miaosha/redis/OrderKey.class
com/geekq/miaosha/domain/Goods.class
com/geekq/miaosha/config/UserArgumentResolver.class
com/geekq/miaosha/redis/MiaoShaUserKey.class
com/geekq/miaosha/controller/MiaoshaController.class
com/geekq/miaosha/vo/OrderDetailVo.class
com/geekq/miaosha/validator/IsMobileValidator.class
com/geekq/miaosha/dao/OrderDao.class
com/geekq/miaosha/vo/LoginVo.class
com/geekq/miaosha/DemoTask$1.class
com/geekq/miaosha/domain/MiaoshaOrder.class
com/geekq/miaosha/access/AccessInterceptor.class
com/geekq/miaosha/domain/MiaoshaGoods.class
com/geekq/miaosha/domain/OrderInfo.class
com/geekq/miaosha/validator/IsMobile.class
com/geekq/miaosha/rabbitmq/MQSender.class
com/geekq/miaosha/dao/GoodsDao.class
com/geekq/miaosha/controller/UserController.class
com/geekq/miaosha/controller/GoodsController.class
com/geekq/miaosha/domain/User.class
com/geekq/miaosha/Md5Utils/MD5Utils.class
com/geekq/miaosha/redis/Userkey.class
com/geekq/miaosha/service/UserService.class
com/geekq/miaosha/GeekQMainApplication.class
com/geekq/miaosha/utils/ValidatorUtil.class
com/geekq/miaosha/result/CodeMsg.class
com/geekq/miaosha/redis/RedisPoolFactory.class
com/geekq/miaosha/access/AccessKey.class
com/geekq/miaosha/vo/GoodsVo.class
com/geekq/miaosha/dao/MiaoShaUserDao.class
com/geekq/miaosha/redis/KeyPrefix.class
com/geekq/miaosha/redis/GoodsKey.class
com/geekq/miaosha/access/AccessLimit.class
com/geekq/miaosha/service/MiaoshaService.class
com/geekq/miaosha/rabbitmq/MQConfig.class
com/geekq/miaosha/exception/GlobleException.class
com/geekq/miaosha/DemoTask.class
com/geekq/miaosha/redis/BasePrefix.class
com/geekq/miaosha/service/OrderService.class
com/geekq/miaosha/common/ResponseCode.class
com/geekq/miaosha/dao/UserDao.class
com/geekq/miaosha/Test.class
com/geekq/miaosha/redis/RedisConfig.class
com/geekq/miaosha/utils/UUIDUtil.class

View File

@ -1,64 +0,0 @@
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/rabbitmq/MQSender.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/validator/IsMobileValidator.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/common/ServerResponse.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/domain/User.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/OrderController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/DemoController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/dao/OrderDao.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/service/MiaoShaUserService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/RateLimiterController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/domain/MiaoshaUser.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/OrderKey.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/vo/GoodsDetailVo.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/service/UserService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/dao/GoodsDao.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/exception/GlobleExceptionandler.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/exception/GlobleException.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/MiaoShaUserKey.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/result/Result.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/Userkey.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/access/UserContext.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/RedisPoolFactory.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/result/CodeMsg.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/Md5Utils/MD5Utils.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/domain/MiaoshaGoods.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/vo/LoginVo.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/access/AccessInterceptor.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/GeekQMainApplication.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/service/GoodsService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/GoodsKey.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/utils/ValidatorUtil.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/dao/MiaoShaUserDao.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/service/MiaoshaService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/service/OrderService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/access/AccessLimit.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/access/AccessKey.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/domain/Goods.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/config/UserArgumentResolver.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/MiaoshaKey.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/domain/MiaoshaOrder.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/UserController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/LoginController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/dao/DruidConfig.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/vo/GoodsVo.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/Test.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/KeyPrefix.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/common/ResponseCode.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/RedisService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/mybatis/controller/MessageController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/utils/UUIDUtil.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/domain/OrderInfo.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/validator/IsMobile.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/vo/OrderDetailVo.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/rabbitmq/MQConfig.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/dao/UserMapper.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/BasePrefix.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/service/IUserService.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/config/WebConfig.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/redis/RedisConfig.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/rabbitmq/MiaoshaMessage.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/rabbitmq/MQReceiver.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/controller/GoodsController.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/dao/UserDao.java
/home/qiurunze/下载/miaosha_1/src/main/java/com/geekq/miaosha/DemoTask.java

Binary file not shown.

Binary file not shown.