“秒杀”,生产环境中的秒杀系统

        设计一个生产环境中的秒杀系统需要考虑多个方面,包括数据库操作、分布式锁、限流、熔断等。下面是一个较为完整的示例,使用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);
    }
}
```

 

总结

以上是一个较为完整的生产环境中的秒杀系统设计,包括了数据库操作、分布式锁、限流和熔断等关键功能。你可以根据实际需求进一步优化和扩展。希望这个示例对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值