SpringBoot共享单车系统:高并发与分布式锁实践

SpringBoot共享单车系统:高并发与分布式锁实践
1. 项目概述这个基于SpringBoot的共享单车信息系统是一个典型的互联网租赁业务管理平台。我在实际开发中发现这类系统需要同时解决三个核心问题车辆状态实时监控、用户租赁行为管理、后台运营数据分析。系统采用B/S架构前端使用Vue.jsElementUI后端基于SpringBootMyBatis技术栈数据库选用MySQL 8.0。提示共享单车系统的难点不在于基础CRUD实现而在于高并发场景下的车辆状态同步和分布式锁的应用2. 系统架构设计2.1 技术选型分析后端框架选择SpringBoot 2.7.x版本主要考虑因素包括自动配置特性简化了Redis、MySQL等组件的集成内嵌Tomcat容器便于打包部署Actuator端点提供系统健康监控与MyBatis的天然兼容性数据库方案对比MySQL满足事务性操作需求适合用户账户、订单等强一致性数据Redis用作车辆状态缓存采用Hash结构存储单车实时位置和状态Elasticsearch用于历史订单的复杂查询分析2.2 微服务划分系统按功能划分为三个微服务用户服务处理注册/登录/押金等业务车辆服务管理单车状态和位置信息订单服务处理租赁计费和支付服务间通信采用两种方式同步调用使用OpenFeign进行RESTful API调用异步事件通过RabbitMQ发送车辆状态变更事件3. 核心功能实现3.1 车辆状态管理车辆实时位置更新采用Redis GEO数据结构// 更新单车位置 public void updateBikePosition(Long bikeId, BigDecimal lng, BigDecimal lat) { String key bike:location; redisTemplate.opsForGeo().add(key, new Point(lng.doubleValue(), lat.doubleValue()), bikeId.toString()); }状态变更时的分布式锁实现public boolean lockBike(Long bikeId) { String lockKey lock:bike: bikeId; return redisTemplate.opsForValue().setIfAbsent( lockKey, 1, Duration.ofSeconds(30)); }3.2 订单计费逻辑计费规则配置化设计billing: rules: - timeRange: 0-30 unit: MINUTE price: 1.5 - timeRange: 30-60 unit: MINUTE price: 1.0 - timeRange: 60- unit: HOUR price: 15.0分段计费核心算法public BigDecimal calculateFee(Date startTime, Date endTime) { long duration endTime.getTime() - startTime.getTime(); long minutes duration / (60 * 1000); if (minutes 30) { return BASE_PRICE.add(UNIT_PRICE.multiply(new BigDecimal(minutes))); } else if (minutes 60) { return BASE_PRICE.add(EXTEND_PRICE.multiply(new BigDecimal(minutes-30))); } else { long hours (minutes 59) / 60; // 向上取整 return BASE_PRICE.add(HOURLY_PRICE.multiply(new BigDecimal(hours-1))); } }4. 数据库设计要点4.1 主要表结构用户表设计考虑因素CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, phone varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT 登录手机号, password varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT 加密密码, id_card varchar(20) COLLATE utf8mb4_bin DEFAULT NULL COMMENT 身份证号, deposit_status tinyint NOT NULL DEFAULT 0 COMMENT 押金状态, balance decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 账户余额, credit_score int NOT NULL DEFAULT 100 COMMENT 信用分, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY idx_phone (phone) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_bin;订单表分库分表策略按用户ID哈希分库按月分表order_202301, order_202302...使用ShardingSphere实现透明分片4.2 索引优化实践车辆查询的复合索引设计ALTER TABLE bike ADD INDEX idx_status_location (status, city_code, geo_hash);注意geo_hash是将经纬度编码为字符串的空间索引方案前6位可表示约1km精度范围5. 典型问题解决方案5.1 并发开锁问题场景多个用户同时扫码同一辆单车时使用Redis分布式锁确保原子性采用乐观锁防止超卖UPDATE bike SET status USING WHERE id #{bikeId} AND status FREE5.2 轨迹存储优化车辆轨迹存储方案对比方案写入性能查询性能存储成本MySQL单条记录低高高MySQL批量压缩中中中MongoDB文档存储高高低时序数据库极高极高低最终采用InfluxDB存储轨迹数据Measurement(name bike_track) public class BikeTrack { Column(name bike_id, tag true) private Long bikeId; Column(name location) private String geoHash; Column(name time) private Instant time; }6. 部署架构6.1 生产环境配置服务器规格建议API服务器4核8G × 3最少2台保证高可用Redis集群6节点3主3从16G内存MySQL集群主从复制读写分离监控组件Prometheus Grafana6.2 性能压测数据关键接口TPS指标接口平均响应时间最大QPS单车扫码78ms1200位置上报35ms2500订单创建112ms800优化手段车辆状态查询走Redis缓存订单创建异步化处理采用Hystrix熔断保护核心服务7. 安全防护措施7.1 常见攻击防护短信轰炸防御同一手机号60秒内只能发送1次验证码每日上限10次图形验证码二次校验余额盗刷预防Transactional public void deductBalance(Long userId, BigDecimal amount) { // 先查询后校验 BigDecimal balance userMapper.selectBalance(userId); if (balance.compareTo(amount) 0) { throw new BusinessException(余额不足); } // 带条件更新 int rows userMapper.updateBalance( userId, amount.negate()); if (rows 0) { throw new ConcurrentUpdateException(); } }7.2 数据加密方案敏感字段加密存储// 身份证号加密 public String encryptIdCard(String idCard) { return AESUtil.encrypt(idCard, SECRET_KEY); } // 数据库字段处理器 MappedTypes(String.class) public class EncryptTypeHandler extends BaseTypeHandlerString { Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) { ps.setString(i, encrypt(parameter)); } // ...其他方法实现 }8. 扩展功能设计8.1 智能调度算法车辆调度核心逻辑基于历史订单数据预测热点区域使用K-means聚类分析车辆分布调度优先级计算公式priority 0.6*需求缺口 0.3*停车位剩余 - 0.1*运输距离8.2 故障预测模型基于车辆传感器数据的决策树模型from sklearn.tree import DecisionTreeClassifier # 特征工程 features [vibration_score, gps_error_count, unlock_failure_rate, battery_health] # 模型训练 clf DecisionTreeClassifier() clf.fit(X_train, y_train) # 保存PMML模型 from sklearn2pmml import sklearn2pmml sklearn2pmml(clf, bike_fault.pmml)9. 开发经验总结在实际开发中有几个关键点需要特别注意车辆状态同步的最终一致性采用先更新缓存异步落库策略使用CDC工具监听MySQL binlog补偿丢失的更新设置状态变更MQ消息的TTL防止堆积分库分表后的查询优化建立宽表应对复杂报表查询使用ES实现跨分片搜索避免不带分片键的条件查询压力测试要模拟真实场景早晚高峰的集中用车模式节假日特殊流量波动区域性活动导致的局部热点这个系统从技术角度已经相对成熟但商业运营中还需要考虑区域化政策、车辆折损率等非技术因素。我在项目后期增加了运维监控看板和自动化报警机制这对线上问题排查帮助很大。

最新新闻

日新闻

周新闻

月新闻