源码Demo
https://github.com/wanglei0530/redis_lock.git
项目结构

Pom依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.49</version> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.6.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
|
Yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| server: port: 8000
spring: redis:
database: 1 host: localhost port: 6379 password: jedis: pool: max-idle: 100 max-wait: -1s max-active: 1000
|
RedissionConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| package in.nanopay.redis_lock.config;
import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component;
import java.io.IOException;
@Component @Configuration @Slf4j public class RedissonConfig {
@Autowired private Environment env;
@Bean public RedissonClient getRedisson() throws IOException { String host = env.getProperty("spring.redis.host"); String nodes = env.getProperty("spring.redis.cluster.nodes"); RedissonClient redisson = null; Config config = null; if (StrUtil.isNotBlank(nodes)) { config = cluster(nodes); } else if (StrUtil.isNotBlank(host)) { config = single(host); } redisson = Redisson.create(config); log.debug("redisson config" + redisson.getConfig().toJSON()); return redisson; }
private Config cluster(String configStr) { String[] nodes = configStr.split(","); for (int i = 0; i < nodes.length; i++) { nodes[i] = "redis://" + nodes[i]; } Config config = new Config(); config.useClusterServers() .setScanInterval(2000) .addNodeAddress(nodes) .setRetryAttempts(3) ; return config; }
private Config single(String configStr) { String port = env.getProperty("spring.redis.port"); String database = env.getProperty("spring.redis.database"); String addr = new StringBuffer("redis://") .append(configStr) .append(":") .append(port) .toString();
Config config = new Config(); config.useSingleServer() .setAddress(addr) .setDatabase(Integer.parseInt(database)) ; return config; } }
|
LockTestController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @GetMapping("/many") public String many(@Param("productId") String productId, @Param("qty") Integer qty) { RLock redissonLock = redissLockUtil.lock(productId, 10); try { int stock = getStock(); if (stock <= 0) { return "没有库存了!"; } int realstock = stock - qty; redisTemplate.opsForValue().set("stock", realstock + ""); log.info(DateUtil.format("--- 剩余库存: " + realstock); return "" + getStock(); } finally { redissonLock.unlock(); } }
private int getStock() { return Integer.parseInt(redisTemplate.opsForValue().get("stock")); }
|
nginx 负载配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| upstream redislock{ server 10.247.34.208:8000; server 10.247.34.208:8001; }
server { listen 80; server_name localhost;
#charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; proxy_pass http://redislock; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
|