本文目录导读:

我来为您设计一个完整的Java秒杀系统案例,涵盖核心业务逻辑、并发控制和数据库设计。
系统架构设计
graph TB
A[客户端] --> B[负载均衡]
B --> C[Web层]
C --> D[业务层]
D --> E[Redis缓存]
D --> F[MQ消息队列]
D --> G[数据库]
核心代码实现
数据库表设计
-- 秒杀商品表
CREATE TABLE seckill_goods (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
goods_name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
stock_count INT NOT NULL,
seckill_price DECIMAL(10,2) NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
version INT DEFAULT 0,
status TINYINT DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- 秒杀订单表
CREATE TABLE seckill_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
goods_id BIGINT NOT NULL,
order_no VARCHAR(32) UNIQUE NOT NULL,
seckill_price DECIMAL(10,2) NOT NULL,
status TINYINT DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
KEY idx_user_goods(user_id, goods_id)
) ENGINE=InnoDB;
-- 用户表
CREATE TABLE user (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
phone VARCHAR(20),
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
项目依赖配置 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.14</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- RabbitMQ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
</project>
实体类代码
// SeckillGoods.java
@Data
@TableName("seckill_goods")
public class SeckillGoods {
@TableId(type = IdType.AUTO)
private Long id;
private String goodsName;
private BigDecimal price;
private Integer stockCount;
private BigDecimal seckillPrice;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
@Version
private Integer version;
private Integer status;
private Date createTime;
}
// SeckillOrder.java
@Data
@TableName("seckill_order")
public class SeckillOrder {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private Long goodsId;
private String orderNo;
private BigDecimal seckillPrice;
private Integer status;
private Date createTime;
}
Mapper接口和XML
// SeckillGoodsMapper.java
@Mapper
public interface SeckillGoodsMapper extends BaseMapper<SeckillGoods> {
// 乐观锁更新库存
@Update("UPDATE seckill_goods SET stock_count = stock_count - 1, " +
"version = version + 1 WHERE id = #{goodsId} " +
"AND stock_count > 0 AND version = #{version}")
int deductStockWithVersion(@Param("goodsId") Long goodsId,
@Param("version") Integer version);
}
// SeckillOrderMapper.java
@Mapper
public interface SeckillOrderMapper extends BaseMapper<SeckillOrder> {
// 递归查询,防止重复秒杀
@Select("SELECT * FROM seckill_order WHERE user_id = #{userId} " +
"AND goods_id = #{goodsId} LIMIT 1")
SeckillOrder findOrderByUserAndGoods(@Param("userId") Long userId,
@Param("goodsId") Long goodsId);
}
Redis配置类
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// String序列化
StringRedisSerializer stringSerializer = new StringRedisSerializer();
// Jackson序列化
Jackson2JsonRedisSerializer<?> jacksonSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
template.setValueSerializer(jacksonSerializer);
template.setHashValueSerializer(jacksonSerializer);
template.afterPropertiesSet();
return template;
}
// 秒杀库存预缓存
@Bean
public RedisTemplate<String, Integer> stockRedisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Integer> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
消息队列配置
@Configuration
public class RabbitMQConfig {
public static final String SECKILL_QUEUE = "seckillQueue";
public static final String SECKILL_EXCHANGE = "seckillExchange";
public static final String SECKILL_ROUTING_KEY = "seckill";
@Bean
public Queue seckillQueue() {
return new Queue(SECKILL_QUEUE, true);
}
@Bean
public TopicExchange seckillExchange() {
return new TopicExchange(SECKILL_EXCHANGE);
}
@Bean
public Binding binding() {
return BindingBuilder.bind(seckillQueue())
.to(seckillExchange())
.with(SECKILL_ROUTING_KEY);
}
// 消息转换器
@Bean
public Jackson2JsonMessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
}
秒杀服务核心实现
@Service
@Slf4j
public class SeckillService {
@Autowired
private SeckillGoodsMapper seckillGoodsMapper;
@Autowired
private SeckillOrderMapper seckillOrderMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
// 使用ConcurrentHashMap做本地缓存(可选)
private final ConcurrentHashMap<Long, Boolean> localizedSuccessMap =
new ConcurrentHashMap<>();
/**
* 秒杀入口(优化版本)
*/
public SeckillResult seckill(Long userId, Long goodsId) {
// 1. 参数校验
if (userId == null || goodsId == null) {
return SeckillResult.error("参数错误");
}
// 2. 检查秒杀时间段
SeckillGoods goods = seckillGoodsMapper.selectById(goodsId);
if (goods == null || goods.getStatus() != 1) {
return SeckillResult.error("商品不存在或不在秒杀活动中");
}
Date now = new Date();
if (now.before(goods.getStartTime()) || now.after(goods.getEndTime())) {
return SeckillResult.error("不在秒杀时间段内");
}
// 3. 检查是否已秒杀过(Redis布隆过滤器或Set)
String seckillKey = "seckill:user:" + userId + ":goods:" + goodsId;
Boolean alreadySeckilled = redisTemplate.hasKey(seckillKey);
if (Boolean.TRUE.equals(alreadySeckilled)) {
return SeckillResult.error("您已经秒杀过该商品");
}
// 4. Redis预减库存(使用Lua脚本保证原子性)
String stockKey = "seckill:goods:stock:" + goodsId;
Long stock = stringRedisTemplate.opsForValue().decrement(stockKey);
if (stock == null || stock < 0) {
// 库存不足,恢复库存
if (stock != null && stock < 0) {
stringRedisTemplate.opsForValue().increment(stockKey);
}
return SeckillResult.error("商品已被抢完");
}
// 5. 写入成功标识,标记已抢到
redisTemplate.opsForValue().set(seckillKey, "1", 5, TimeUnit.MINUTES);
// 6. 异步发送MQ消息,创建订单
SeckillMessage message = new SeckillMessage();
message.setUserId(userId);
message.setGoodsId(goodsId);
message.setGoodsInfo(goods);
try {
rabbitTemplate.convertAndSend(
RabbitMQConfig.SECKILL_EXCHANGE,
RabbitMQConfig.SECKILL_ROUTING_KEY,
message
);
} catch (Exception e) {
log.error("MQ发送失败,回滚库存", e);
// 回滚Redis库存
stringRedisTemplate.opsForValue().increment(stockKey);
redisTemplate.delete(seckillKey);
return SeckillResult.error("系统繁忙,请重试");
}
// 7. 返回结果
SeckillResult result = SeckillResult.success();
result.setData(true);
return result;
}
/**
* 传统查询秒杀流程(备份方案)
*/
@Transactional
public SeckillResult traditionalSeckill(Long userId, Long goodsId) {
// 校验是否已秒杀
SeckillOrder existingOrder = seckillOrderMapper
.findOrderByUserAndGoods(userId, goodsId);
if (existingOrder != null) {
return SeckillResult.error("您已经抢购过该商品");
}
// 数据库乐观锁扣减库存
SeckillGoods goods = seckillGoodsMapper.selectById(goodsId);
int result = seckillGoodsMapper.deductStockWithVersion(
goodsId, goods.getVersion());
if (result == 0) {
return SeckillResult.error("库存不足");
}
// 创建订单
SeckillOrder order = new SeckillOrder();
order.setUserId(userId);
order.setGoodsId(goodsId);
order.setOrderNo(generateOrderNo());
order.setSeckillPrice(goods.getSeckillPrice());
order.setStatus(0);
seckillOrderMapper.insert(order);
return SeckillResult.success(order);
}
/**
* 生成唯一订单号
*/
private String generateOrderNo() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
return sdf.format(new Date()) +
String.format("%04d", ThreadLocalRandom.current().nextInt(10000)) +
String.format("%04d", (int)(Math.random() * 10000));
}
}
MQ消息消费者
@Component
@Slf4j
public class SeckillMessageConsumer {
@Autowired
private SeckillOrderMapper orderMapper;
@Autowired
private SeckillGoodsMapper goodsMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@RabbitListener(queues = RabbitMQConfig.SECKILL_QUEUE)
public void handlerSeckillMessage(SeckillMessage message) {
log.info("收到秒杀消息: {}", JSON.toJSONString(message));
// 幂等性处理(通过数据库唯一索引或Redis标记)
String key = "seckill:order:" + message.getUserId() + ":" + message.getGoodsId();
Boolean alreadyCreated = redisTemplate.hasKey(key);
if (Boolean.TRUE.equals(alreadyCreated)) {
log.warn("订单已创建,跳过处理");
return;
}
try {
SeckillResult result = createOrder(message);
if (result.isSuccess()) {
// 设置标记,5分钟内重复消息直接跳过
redisTemplate.opsForValue().set(
key, "1", 5, TimeUnit.MINUTES);
log.info("订单创建成功: userId={}, goodsId={}",
message.getUserId(), message.getGoodsId());
} else {
log.warn("订单创建失败: {}", result.getMessage());
}
} catch (Exception e) {
log.error("订单创建异常", e);
// 可以选择重试或记录失败日志
}
}
@Transactional
public SeckillResult createOrder(SeckillMessage message) {
SeckillGoods goods = goodsMapper.selectById(message.getGoodsId());
if (goods == null) {
return SeckillResult.error("商品不存在");
}
// 再次检查是否存在订单
SeckillOrder existing = orderMapper.findOrderByUserAndGoods(
message.getUserId(), message.getGoodsId());
if (existing != null) {
return SeckillResult.error("订单已存在");
}
// 创建订单(数据库层保证唯一性)
SeckillOrder order = new SeckillOrder();
order.setUserId(message.getUserId());
order.setGoodsId(message.getGoodsId());
order.setOrderNo(generateOrderNo());
order.setSeckillPrice(goods.getSeckillPrice());
order.setStatus(0);
try {
orderMapper.insert(order);
return SeckillResult.success(order);
} catch (DuplicateKeyException e) {
log.error("订单重复冲突", e);
return SeckillResult.error("订单已存在");
}
}
}
Redis预加载库存
@Component
public class StockInitializer implements ApplicationRunner {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private SeckillGoodsMapper goodsMapper;
@Override
public void run(ApplicationArguments args) throws Exception {
// 项目启动时加载所有进行中的秒杀商品库存到Redis
List<SeckillGoods> goodsList = goodsMapper.selectList(
new QueryWrapper<SeckillGoods>()
.eq("status", 1)
.gt("end_time", new Date())
);
for (SeckillGoods goods : goodsList) {
String key = "seckill:goods:stock:" + goods.getId();
stringRedisTemplate.opsForValue().set(
key, String.valueOf(goods.getStockCount()));
log.info("预加载商品库存: goodsId={}, stock={}",
goods.getId(), goods.getStockCount());
}
}
}
定时任务恢复库存
@Component
@Slf4j
public class StockRecoveryTask {
@Autowired
private SeckillGoodsMapper goodsMapper;
@Scheduled(cron = "0 0/5 * * * ?") // 每5分钟执行一次
public void recoverAbnormalOrders() {
log.info("开始恢复异常订单的库存");
// 查询超时未支付的订单并恢复库存
// 可以通过关联查询或定时扫描实现
List<SeckillOrder> expiredOrders = getExpiredOrders();
for (SeckillOrder order : expiredOrders) {
// 恢复库存
goodsMapper.increaseStock(order.getGoodsId());
// 更新订单状态为已取消
updateOrderStatus(order, -1);
log.info("恢复订单库存: orderId={}, goodsId={}",
order.getId(), order.getGoodsId());
}
}
private List<SeckillOrder> getExpiredOrders() {
// 查询超时未支付订单(例如5分钟未支付)
return orderMapper.selectList(
new QueryWrapper<SeckillOrder>()
.eq("status", 0)
.lt("create_time", new Date(System.currentTimeMillis() - 5*60*1000))
);
}
}
控制器层
@RestController
@RequestMapping("/api/seckill")
public class SeckillController {
@Autowired
private SeckillService seckillService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 获取秒杀商品列表
*/
@GetMapping("/list")
public ApiResponse<List<SeckillGoods>> getSeckillGoods() {
// 从Redis或数据库查询
return ApiResponse.success(seckillGoodsService.getActiveGoods());
}
/**
* 获取商品详情
*/
@GetMapping("/detail/{goodsId}")
public ApiResponse<SeckillGoods> getDetail(@PathVariable Long goodsId) {
return ApiResponse.success(seckillGoodsService.getById(goodsId));
}
/**
* 秒杀接口
* 使用限流(RateLimiter)控制并发
*/
@PostMapping("/{goodsId}")
@RateLimiter(limits = 100, time = 1, unit = TimeUnit.SECONDS)
public ApiResponse<SeckillResult> seckill(
@PathVariable Long goodsId,
@RequestHeader("userId") Long userId) {
SeckillResult result = seckillService.seckill(userId, goodsId);
return ApiResponse.success(result);
}
/**
* 查询秒杀结果(轮询接口)
*/
@GetMapping("/result/{goodsId}")
public ApiResponse<SeckillResult> querySeckillResult(
@PathVariable Long goodsId,
@RequestHeader("userId") Long userId) {
return ApiResponse.success(seckillService.queryResult(userId, goodsId));
}
}
限流配置
@Aspect
@Component
public class RateLimiterAspect {
private static final ConcurrentHashMap<Method, com.google.common.util.concurrent.RateLimiter>
limiters = new ConcurrentHashMap<>();
@Around("@annotation(rateLimiter)")
public Object around(ProceedingJoinPoint joinPoint,
RateLimiter rateLimiter) throws Throwable {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
com.google.common.util.concurrent.RateLimiter limiter =
limiters.computeIfAbsent(method, m ->
com.google.common.util.concurrent.RateLimiter.create(rateLimiter.limits()));
if (!limiter.tryAcquire()) {
throw new BusinessException("系统繁忙,请稍后再试");
}
return joinPoint.proceed();
}
}
统一返回结果
@Data
public class ApiResponse<T> {
private int code;
private String message;
private T data;
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(200);
response.setMessage("success");
response.setData(data);
return response;
}
public static <T> ApiResponse<T> error(int code, String message) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(code);
response.setMessage(message);
return response;
}
}
性能优化策略
多级缓存架构
| 层级 | 类型 | 失效时间 | |
|---|---|---|---|
| L1 | 本地缓存 | 商品基础信息 | 5分钟 |
| L2 | Redis | 库存数据 | 持久 |
| L3 | 数据库 | 订单数据 | 持久 |
并发控制措施
// 滑动窗口限流
public class SlidingWindowRateLimiter {
private final int maxRequests;
private final Deque<Long> timestamps = new ArrayDeque<>();
public synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
// 清理过期时间戳
while (!timestamps.isEmpty() &&
now - timestamps.peekFirst() > 60000) {
timestamps.pollFirst();
}
if (timestamps.size() < maxRequests) {
timestamps.addLast(now);
return true;
}
return false;
}
}
测试用例
@SpringBootTest
@RunWith(SpringRunner.class)
public class SeckillServiceTest {
@Autowired
private SeckillService seckillService;
@Test
public void testConcurrentSeckill() throws InterruptedException {
int threadCount = 1000;
CountDownLatch latch = new CountDownLatch(threadCount);
AtomicInteger successCount = new AtomicInteger();
AtomicInteger failCount = new AtomicInteger();
ExecutorService executor = Executors.newFixedThreadPool(50);
for (int i = 0; i < threadCount; i++) {
final int userId = i;
executor.submit(() -> {
try {
SeckillResult result = seckillService.seckill(
(long) userId, 1L);
if (result.isSuccess()) {
successCount.incrementAndGet();
} else {
failCount.incrementAndGet();
}
} catch (Exception e) {
failCount.incrementAndGet();
} finally {
latch.countDown();
}
});
}
latch.await(30, TimeUnit.SECONDS);
executor.shutdown();
log.info("成功人数: {}", successCount.get());
log.info("失败人数: {}", failCount.get());
assertEquals(10, successCount.get()); // 假设库存为10
}
}
部署架构建议
- 应用层:独立部署秒杀服务,使用Nginx+多个实例
- 数据层:MySQL主从复制,Redis集群
- 中间件:RabbitMQ集群部署
- 监控:使用Prometheus+Grafana监控系统
这个案例涵盖了秒杀系统的核心要点:库存预减、异步削峰、防重复提交、限流降级等关键技术,实际生产中还需要增加更完善的监控、告警和容灾机制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播