设计一个生产环境中的秒杀系统需要考虑多个方面,包括数据库操作、分布式锁、限流、熔断等。下面是一个较为完整的示例,使用Spring Boot框架来实现。
1. 项目依赖
首先,我们需要在 `pom.xml` 中添加必要的依赖:
```xml
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Redis for Distributed Lock -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Resilience4j for Circuit Breaker -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
<!-- Rate Limiter -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
```
2. 配置文件
在 `application.properties` 中配置数据库和Redis连接:
```properties
spring.datasource.url=jdbc:mysql://localhost:3306/seckill_db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.redis.host=localhost
spring.redis.port=6379
```
3. 实体类
定义商品实体类:
```java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int stock;
// Getters and Setters
}
```
4. 数据访问层
定义商品的Repository接口:
```java
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository<Product, Long> {
}
```
5. 分布式锁
使用Redis实现分布式锁:
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class DistributedLock {
@Autowired
private StringRedisTemplate stringRedisTemplate;
public boolean lock(String key, String value, long expireTime) {
return stringRedisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
}
public boolean unlock(String key, String value) {
String currentValue = stringRedisTemplate.opsForValue().get(key);
if (currentValue != null && currentValue.equals(value)) {
stringRedisTemplate.delete(key);
return true;
}
return false;
}
}
```
6. 限流
使用Guava的RateLimiter实现限流:
```java
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.stereotype.Component;
@Component
public class RateLimiterService {
private final RateLimiter rateLimiter = RateLimiter.create(10.0); // 每秒最多10个请求
public boolean tryAcquire() {
return rateLimiter.tryAcquire();
}
}
```
7. 服务层
实现秒杀服务:
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SeckillService {
@Autowired
private ProductRepository productRepository;
@Autowired
private DistributedLock distributedLock;
@Autowired
private RateLimiterService rateLimiterService;
@Transactional
public boolean seckill(Long productId, String userId) {
if (!rateLimiterService.tryAcquire()) {
throw new RuntimeException("请求过于频繁,请稍后再试");
}
String lockKey = "seckill:lock:" + productId;
String lockValue = userId;
if (!distributedLock.lock(lockKey, lockValue, 10)) {
throw new RuntimeException("获取锁失败");
}
try {
Product product = productRepository.findById(productId).orElseThrow(() -> new RuntimeException("商品不存在"));
if (product.getStock() > 0) {
product.setStock(product.getStock() - 1);
productRepository.save(product);
return true;
} else {
throw new RuntimeException("库存不足");
}
} finally {
distributedLock.unlock(lockKey, lockValue);
}
}
}
```
8. 控制器
处理秒杀请求:
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/seckill")
public class SeckillController {
@Autowired
private SeckillService seckillService;
@PostMapping("/{productId}")
public String seckill(@PathVariable Long productId, @RequestParam String userId) {
try {
boolean result = seckillService.seckill(productId, userId);
return result ? "秒杀成功" : "秒杀失败";
} catch (Exception e) {
return "秒杀失败: " + e.getMessage();
}
}
}
```
9. 熔断
使用Resilience4j实现熔断:
```java
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/health")
public class HealthController {
@Autowired
private SeckillService seckillService;
@GetMapping("/check")
@CircuitBreaker(name = "seckillCircuitBreaker", fallbackMethod = "fallback")
public String checkHealth() {
// 模拟健康检查
return "系统正常";
}
public String fallback(Exception e) {
return "系统繁忙,请稍后再试";
}
}
```
10. 应用启动类
```java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SeckillApplication {
public static void main(String[] args) {
SpringApplication.run(SeckillApplication.class, args);
}
}
```
总结
以上是一个较为完整的生产环境中的秒杀系统设计,包括了数据库操作、分布式锁、限流和熔断等关键功能。你可以根据实际需求进一步优化和扩展。希望这个示例对你有所帮助!

1371

被折叠的 条评论
为什么被折叠?



