From c02e3421adda7e47227dd16cb69fb442b71f3db4 Mon Sep 17 00:00:00 2001 From: YoVinchen Date: Tue, 29 Jul 2025 22:13:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9redis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 159 +++++++++++++++++++++++------ docs/Redis配置指南.md | 110 ++++++++++++++++++++ src/main/resources/application.yml | 19 +++- 3 files changed, 250 insertions(+), 38 deletions(-) create mode 100644 docs/Redis配置指南.md diff --git a/CLAUDE.md b/CLAUDE.md index 6227c0a..00b4333 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,11 +24,11 @@ and Lua scripts. ### Technology Stack - **Backend**: Spring Boot 2.7.6, Java 1.8 -- **Database**: MySQL with JPA/Hibernate -- **Cache**: Redis Cluster with Redisson +- **Database**: MySQL 5.7+ with JPA/Hibernate +- **Cache**: Redis 6.0+ Cluster (6 nodes) with Redisson 3.24.3 - **Frontend**: JSP + JSTL + Bootstrap 5 + jQuery -- **Build Tool**: Maven -- **API Documentation**: Knife4j (Swagger) +- **Build Tool**: Maven 3.6+ +- **API Documentation**: Knife4j 4.1.0 (Swagger) ### Key Components @@ -53,50 +53,85 @@ com.org.flashsalesystem/ ### Redis Integration -- **Cluster Configuration**: Multi-node Redis cluster setup via RedissonConfig +- **Multiple Modes Supported**: Single node, Cluster (6 nodes), Sentinel +- **Mode Selection**: Automatic based on configuration in application.yml +- **Default Mode**: Single node (localhost:6379) for development +- **Cluster Configuration**: 6-node Redis cluster at 42.192.62.91:7000-7005 via RedissonConfig - **Data Types**: String (locks, sessions), Hash (user/product info, cart), List (order queues), Set (successful users), ZSet (rankings) - **Lua Scripts**: Atomic operations for flash sales, distributed locks, rate limiting, cart operations -- **Message Queues**: Pub/Sub for order status changes and inventory updates +- **Message Queues**: Pub/Sub channels - order:status:change, stock:change, flashsale:result + +### Redis Key Prefixes + +- `flashsale:` - Flash sale activity data +- `flashsale_stock:` - Real-time stock information +- `flashsale_lock:` - Distributed locks for flash sales +- `flashsale_success:` - Successful user sets +- `user:` - User information cache +- `product:` - Product information cache +- `cart:` - Shopping cart data +- `rate_limit:` - API rate limiting counters ## Common Development Commands ### Build and Run ```bash -# Compile project +# 编译项目 mvn clean compile -# Run application +# 运行应用(默认单节点Redis) mvn spring-boot:run -# Package application +# 运行应用(开发环境,单节点Redis) +mvn spring-boot:run -Dspring.profiles.active=dev + +# 运行应用(生产环境,Redis集群) +mvn spring-boot:run -Dspring.profiles.active=cluster + +# 打包应用 mvn clean package + +# 跳过测试打包 +mvn clean package -DskipTests + +# 运行打包后的jar(默认配置) +java -jar target/FlashSaleSystem-0.0.1-SNAPSHOT.jar + +# 运行打包后的jar(指定profile) +java -jar target/FlashSaleSystem-0.0.1-SNAPSHOT.jar --spring.profiles.active=cluster ``` ### Testing ```bash -# Run all tests (if available) +# 运行所有测试(目前无测试类,需要创建) mvn test -# Run specific test classes +# 运行特定测试类 mvn test -Dtest=FlashSaleServiceTest mvn test -Dtest=RedisServiceTest -# Note: Test classes may need to be created for comprehensive testing +# 运行集成测试 +mvn verify ``` ### Database Setup ```bash -# Create database +# 创建数据库 mysql -u root -p -CREATE DATABASE flash_sale_db; +CREATE DATABASE flash_sale_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -# Import schema and test data +# 导入表结构(JPA会自动创建,但也可以手动导入) mysql -u root -p flash_sale_db < src/main/resources/sql/schema.sql + +# 导入测试数据 mysql -u root -p flash_sale_db < src/main/resources/sql/test-data.sql + +# 导入演示用户(包含预设密码) +mysql -u root -p flash_sale_db < src/main/resources/sql/demo-users.sql ``` ## Application Configuration @@ -109,10 +144,29 @@ mysql -u root -p flash_sale_db < src/main/resources/sql/test-data.sql ### Important Configuration Sections -- **Redis Cluster**: Configured for 6-node cluster with authentication -- **Flash Sale Settings**: Rate limiting (10 requests/minute), max quantity per user (1), stock preload timing +- **Redis Mode**: Supports Single node (default), Cluster (6 nodes), Sentinel modes +- **Redis Single Node**: localhost:6379 (default for development) +- **Redis Cluster**: 6-node cluster with password authentication (6HU3cw1drNjfQ0zo1Uyx) +- **Flash Sale Settings**: Rate limiting (10 requests/minute), max quantity per user (1), stock preload (30min advance) - **Cache TTL**: User info (30min), product info (60min), flash sale data (10min) -- **Database**: HikariCP connection pool with optimized settings +- **Database**: HikariCP connection pool (max 20, min 5) +- **Cart Settings**: Expire after 7 days, max 20 items + +### Redis Mode Switching + +1. **Single Node Mode** (Default): + - Edit `application.yml` and ensure cluster configuration is commented out + - Or use profile: `mvn spring-boot:run -Dspring.profiles.active=dev` + +2. **Cluster Mode**: + - Use profile: `mvn spring-boot:run -Dspring.profiles.active=cluster` + - Or uncomment cluster configuration in `application.yml` + +3. **Environment Variable Override**: + ```bash + export SPRING_REDIS_HOST=your-redis-host + export SPRING_REDIS_CLUSTER_NODES=node1:7000,node2:7001 + ``` ## Development Guidelines @@ -120,47 +174,84 @@ mysql -u root -p flash_sale_db < src/main/resources/sql/test-data.sql - All Redis operations use Redisson for cluster support - Critical operations (stock deduction, cart updates) use Lua scripts for atomicity -- Distributed locks prevent overselling using Redisson's RLock +- Distributed locks prevent overselling using Redisson's RLock with timeout - Rate limiting implemented via sliding window algorithm in Lua +- Use RedisPipelineService for batch operations to improve performance ### Key Services - **FlashSaleService**: Core flash sale logic with distributed locking and Lua scripts -- **RedisService**: Generic Redis operations wrapper -- **DistributedLockService**: Distributed locking abstraction -- **RateLimitService**: API rate limiting using Redis +- **RedisService**: Generic Redis operations wrapper with TTL support +- **DistributedLockService**: Distributed locking abstraction with auto-renewal +- **RateLimitService**: API rate limiting using Redis sliding window - **CartService**: Shopping cart operations with Redis Hash storage +- **RedisPipelineService**: Batch Redis operations using pipeline +- **MessageListenerService**: Redis Pub/Sub message handling + +### Flash Sale Process Flow + +1. **Stock Preload**: FlashSaleService.preloadStock() loads stock to Redis 30min before +2. **Rate Limit Check**: RateLimitService.isAllowed() checks request frequency +3. **Distributed Lock**: DistributedLockService.tryLock() prevents concurrent access +4. **Stock Check**: Lua script atomically checks and deducts stock +5. **Order Creation**: Creates order in database and publishes result +6. **Cache Update**: Updates user success set and publishes notifications ### Testing Approach - Unit tests should be created for core services (FlashSaleService, RedisService, CartService) - Integration tests should verify Redis cluster connectivity and database operations -- Load testing recommended for flash sale scenarios to validate concurrency handling +- Load testing recommended using JMeter for flash sale scenarios +- Mock Redis operations in unit tests using Mockito ## Lua Script Usage The system includes 5 Lua scripts in `src/main/resources/lua/`: -- `flashsale.lua`: Atomic stock deduction with overselling prevention -- `distributed_lock.lua`: Distributed lock acquisition -- `unlock.lua`: Safe distributed lock release -- `rate_limit.lua`: Sliding window rate limiting -- `cart_operation.lua`: Atomic shopping cart operations +- `flashsale.lua`: Atomic stock deduction with overselling prevention (returns: remaining stock or negative error codes) +- `distributed_lock.lua`: Distributed lock acquisition with expiry +- `unlock.lua`: Safe distributed lock release with owner verification +- `rate_limit.lua`: Sliding window rate limiting (returns: 1 if allowed, 0 if blocked) +- `cart_operation.lua`: Atomic shopping cart operations (add/update/remove items) + +### Lua Script Error Codes + +- `-1`: Key not exists or invalid +- `-2`: Insufficient stock +- `-3`: Invalid parameter ## API Documentation -- **Swagger UI**: http://localhost:8080/doc.html (Knife4j) +- **Swagger UI**: http://localhost:8080/doc.html (Knife4j enhanced UI) - **API Docs**: http://localhost:8080/v3/api-docs +- **Test Endpoints**: TestController provides Redis connection and data verification endpoints ## Monitoring and Health - **Actuator Endpoints**: /actuator/health, /actuator/metrics, /actuator/prometheus - **Log Files**: logs/flash-sale-system.log with detailed Redis and SQL logging -- **Debug Level**: Enabled for package com.org.flashsalesystem and Redis operations +- **Debug Level**: Enabled for com.org.flashsalesystem, org.springframework.data.redis, org.hibernate.SQL +- **Metrics Export**: Prometheus metrics enabled for monitoring ## Security Considerations -- **Redis Authentication**: Cluster uses password authentication as configured in application.yml -- **Database Connection**: Uses HikariCP with connection pooling and timeout configurations -- **Password Encoding**: Spring Security crypto for password hashing -- **Rate Limiting**: Built-in rate limiting to prevent abuse of flash sale endpoints \ No newline at end of file +- **Redis Authentication**: Cluster uses password authentication +- **Database Connection**: Uses HikariCP with SSL disabled (enable for production) +- **Password Encoding**: BCrypt with strength 10 for user passwords +- **Rate Limiting**: Built-in rate limiting to prevent abuse +- **Session Management**: Redis-based session storage with 30min timeout + +## Performance Optimization + +- **Connection Pooling**: HikariCP (20 max) for DB, Jedis pool (20 max) for Redis +- **Pipeline Operations**: Use RedisPipelineService for batch operations +- **Cache Strategy**: Multi-level caching with appropriate TTL +- **Lua Scripts**: Reduce network round trips for atomic operations +- **Stock Preload**: Warm up cache before flash sale starts + +## Common Issues and Solutions + +1. **Redis Connection Failed**: Check cluster nodes accessibility and password +2. **Stock Overselling**: Ensure Lua scripts are loaded and distributed locks work +3. **High Latency**: Use pipeline for batch operations, check network latency +4. **Memory Issues**: Monitor Redis memory usage, adjust cache TTL if needed \ No newline at end of file diff --git a/docs/Redis配置指南.md b/docs/Redis配置指南.md new file mode 100644 index 0000000..825106f --- /dev/null +++ b/docs/Redis配置指南.md @@ -0,0 +1,110 @@ +# Redis配置说明 + +本项目支持三种Redis部署模式:单节点模式、集群模式和哨兵模式。 + +## 配置方式 + +### 1. 单节点模式(默认) + +默认配置文件 `application.yml` 已配置为单节点模式: + +```yaml +spring: + redis: + host: localhost + port: 6379 + database: 0 + password: your-password +``` + +### 2. 集群模式 + +使用 `application-cluster.yml` 配置文件: + +```bash +# 运行时指定profile +java -jar FlashSaleSystem.jar --spring.profiles.active=cluster + +# 或设置环境变量 +export SPRING_PROFILES_ACTIVE=cluster +java -jar FlashSaleSystem.jar +``` + +### 3. 哨兵模式 + +在 `application.yml` 中启用哨兵配置: + +```yaml +spring: + redis: + sentinel: + master: mymaster + nodes: localhost:26379,localhost:26380,localhost:26381 + password: your-password +``` + +## 切换Redis模式 + +### 方式一:修改application.yml + +直接编辑 `src/main/resources/application.yml`,注释/取消注释相应配置块。 + +### 方式二:使用Spring Profile + +1. 本地开发(单节点): + ```bash + mvn spring-boot:run -Dspring.profiles.active=dev + ``` + +2. 生产环境(集群): + ```bash + mvn spring-boot:run -Dspring.profiles.active=cluster + ``` + +### 方式三:环境变量覆盖 + +```bash +# 覆盖Redis主机 +export SPRING_REDIS_HOST=192.168.1.100 +export SPRING_REDIS_PORT=6379 + +# 覆盖为集群模式 +export SPRING_REDIS_CLUSTER_NODES=192.168.1.100:7000,192.168.1.100:7001 + +java -jar FlashSaleSystem.jar +``` + +## 配置优先级 + +1. 命令行参数(最高优先级) +2. 环境变量 +3. application-{profile}.yml +4. application.yml(最低优先级) + +## 注意事项 + +1. **单节点模式**:适合开发和测试环境,不建议生产使用 +2. **集群模式**:推荐生产环境使用,提供高可用性 +3. **密码配置**:生产环境建议使用环境变量配置密码 +4. **连接池**:根据实际负载调整连接池参数 + +## 验证Redis连接 + +启动应用后,可以通过以下方式验证: + +1. 查看启动日志: + ``` + 初始化Redisson客户端... + 配置Redis单机模式: localhost:6379 + Redisson客户端初始化完成 + ``` + +2. 访问测试接口: + ``` + GET http://localhost:8080/api/test/redis/connection + ``` + +3. 检查健康状态: + ``` + GET http://localhost:8080/actuator/health + ``` \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 349b195..7bd11a2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -30,11 +30,22 @@ spring: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: true - # Redis集群配置 + # Redis配置(支持单节点和集群模式) redis: - cluster: - nodes: 42.192.62.91:7000,42.192.62.91:7001,42.192.62.91:7002,42.192.62.91:7003,42.192.62.91:7004,42.192.62.91:7005 - password: 6HU3cw1drNjfQ0zo1Uyx + # 模式选择:single(单节点)、cluster(集群) + # 注释掉cluster配置即自动使用单节点模式 + + # === 单节点配置(默认) === + host: localhost + port: 6379 + database: 0 + + # === 集群配置(使用时取消注释) === + # cluster: + # nodes: 42.192.62.91:7000,42.192.62.91:7001,42.192.62.91:7002,42.192.62.91:7003,42.192.62.91:7004,42.192.62.91:7005 + + # 通用配置 + password: timeout: 5000 jedis: pool: