MySQL性能优化 Java实现高并发电影票选座系统 Redis缓存+事务控制

MySQL性能优化

索引优化
为高频查询字段(如电影ID、场次时间、座位状态)添加复合索引,避免全表扫描。例如:

ALTER TABLE seats ADD INDEX idx_movie_showtime_status (movie_id, showtime, status);

分库分表
按电影ID或时间范围水平分表,减少单表数据量。采用Sharding-JDBC实现路由:

// Sharding配置示例
spring.shardingsphere.datasource.names=ds0,ds1
spring.shardingsphere.sharding.tables.seats.actual-data-nodes=ds$->{0..1}.seats_$->{0..15}

SQL优化
使用批量插入代替循环单条插入,减少网络IO:

String sql = "INSERT INTO seats (movie_id, row, col, status) VALUES (?,?,?,?)";
jdbcTemplate.batchUpdate(sql, seatList);


Redis缓存设计

热点数据缓存
使用Hash结构存储场次座位状态,Key格式:movie:{movieId}:showtime:{time}

// 写入缓存
redisTemplate.opsForHash().putAll("movie:1:showtime:19:00", seatStatusMap);

// 读取缓存
Map<Object, Object> seats = redisTemplate.opsForHash().entries("movie:1:showtime:19:00");

分布式锁
采用Redisson实现选座互斥锁,防止超卖:

RLock lock = redissonClient.getLock("seat_lock:" + seatId);
try {
    lock.lock(5, TimeUnit.SECONDS);
    // 处理选座逻辑
} finally {
    lock.unlock();
}


事务控制方案

MySQL事务隔离
使用SELECT...FOR UPDATE悲观锁确保数据一致性:

BEGIN;
SELECT status FROM seats WHERE id=1001 FOR UPDATE;
UPDATE seats SET status='locked' WHERE id=1001;
COMMIT;

Redis+Lua原子操作
通过Lua脚本保证缓存操作的原子性:

local key = KEYS[1]
local seat = ARGV[1]
if redis.call('HGET', key, seat) == 'available' then
    return redis.call('HSET', key, seat, 'locked')
end
return 0


高并发架构设计

异步处理
引入RabbitMQ削峰填谷,将选座请求异步化:

@RabbitListener(queues = "seat.queue")
public void processSeatRequest(SeatMessage message) {
    // 异步处理订单
}

读写分离
通过MyCAT实现主从分离,查询走从库:

# MyCAT配置
schema name="cinema" checkSQLschema="false" sqlMaxLimit="100">
    <table name="seats" primaryKey="id" type="global" dataNode="dn1,dn2"/>
</schema>

限流措施
使用Guava RateLimiter控制接口流量:

RateLimiter limiter = RateLimiter.create(1000); // QPS=1000
if (limiter.tryAcquire()) {
    // 处理请求
}


监控与降级

Prometheus监控
暴露关键指标如MySQL查询延迟、Redis命中率:

@Bean
MeterRegistryCustomizer<PrometheusMeterRegistry> metricsCommonTags() {
    return registry -> registry.config().commonTags("application", "seat-service");
}

熔断降级
通过Hystrix保护数据库访问:

@HystrixCommand(fallbackMethod = "getSeatInfoFallback")
public Seat getSeatInfo(Long id) {
    return seatMapper.selectById(id);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值