1. Ticket-Craze-Redis ``` User places order → MySQL deducts inventory (UPDATE skus SET stock = stock - 1) → If successful → redirect to payment → Payment success → write order + order_items → Payment failure → MySQL adds inventory back ``` ##### Core Requirement: Improve performance without overselling ### Step 1: Problem Emerges (High Concurrency Scenario) 10,000 people grab the same product → row lock queuing MySQL CPU spikes, response slows, even overselling At this point introduce: Pessimistic lock (MySQL SELECT ... FOR UPDATE) Why needed: Prevent concurrent reads of the same inventory value - Cost: Long lock wait time, low throughput - Transition: This shows MySQL is not suitable for high concurrency scenarios, we need a faster solution ### Step 2: Introduce Redis (Solve High Concurrency & Lock Contention) ``` User places order → Redis deducts inventory (DECR) → If successful → initiate payment → Kafka / async or Node.js write back to MySQL ``` ##### Why is Redis inventory deduction fast? | Feature | Meaning | Benefit | |---|---|---| |**Memory storage**|All data in memory|Operation speed is hundreds of times faster than disk database| |**Single-threaded model**|All commands execute sequentially|No multi-thread competition issues| ##### Atomicity: Why Use Lua Scripts? Because sometimes we need to do two operations: check if inventory is sufficient, deduct inventory If you write two Redis commands: ``` if redis.call("get", "stock:123") > 0 then redis.call("decr", "stock:123") return 1 else return 0 end ``` Under high concurrency this may cause problems: Two people almost simultaneously execute the first line, both see "inventory > 0", both proceed to deduct, resulting in inventory being deducted to negative (overselling). Redis allows you to write Lua scripts, so Redis will execute it all at once: ``` if redis.call("get", "stock:123") > 0 then redis.call("decr", "stock:123") return 1 else return 0 end ``` - This entire logic is completed in one step inside Redis, others cannot interrupt. - Why needed: Check + deduct must be atomic > Redis doesn't replace MySQL, but adds a layer of _cache/rate limiting_ ##### **New Problem:** - What if Redis crashes? Data loss? - How do multiple Redis nodes guarantee consistency? ### Step 3: What If Redis Crashes? > Because Redis is an in-memory database, data may not have been written to disk yet. Causes problem: Overselling Redis has already deducted inventory (-1), but the async write to MySQL hasn't executed yet. Redis crashes and restarts, data is lost → At this point Redis and MySQL inventory are inconsistent! ``` - User places order → Redis `DECR stock:123`, inventory goes from 10 → 9 - Redis returns success, user enters "payment" flow ✅ - But at this point: MySQL hasn't been updated by async task yet - Redis suddenly crashes (e.g., downtime, no persistence, RDB/AOF not written yet) 💥 - After Redis restarts, inventory returns to 10 (memory lost) - Next user places order → Redis thinks inventory still has 10, allows purchase again ➡ Actual MySQL is still 10 → **Ultimately MySQL layer may have stock < 0 (overselling)** ``` At this point need to use: - Master-slave sync (Master-Slave) -> crash problem - Or distributed lock (e.g., RedLock) -> concurrent operation problem to coordinate data consistency across these nodes. | Solution | Description | Pros & Cons | |---|---|---| |**Master-Slave Sync (Master–Slave)**|Write operations only execute on master node, slave nodes only handle reads, implementing read-write separation.|✅ **Pros**: Simple architecture, improved read performance; ⚠️ **Cons**: Master-slave replication delay exists, master node failure may cause brief data loss or reading stale data.| |**Distributed Lock (RedLock)**|Simultaneously acquire locks on multiple independent Redis nodes, only succeeds when majority of nodes succeed.|✅ **Pros**: High fault tolerance, prevents single point of failure; ⚠️ **Cons**: Complex implementation, performance degradation (multi-node communication), not suitable for extremely high-frequency flash sales.| |**Redis Cluster**|Official sharding cluster solution, automatically distributes keys to different nodes, supports auto-routing and high availability.|✅ **Pros**: Excellent performance, strong scalability, automatic disaster recovery; ⚠️ **Cons**: Key routing constrained by hash slot, cross-key operations and transactions limited.| |**Single Node Hotspot Protection**|Fix **hotspot products or keys** on a single Redis node for centralized processing, reducing distributed consistency issues.|✅ **Pros**: Simple logic, avoids hotspot key distribution imbalance; ⚠️ **Cons**: Hotspot node may still become bottleneck, needs rate limiting or local cache coordination.| |**Sharding**|Split key space by hash or consistent hash strategy across multiple Redis instances, client or proxy layer responsible for routing.|✅ **Pros**: Horizontally scalable, distributes single node pressure, significantly improves throughput; ⚠️ **Cons**: Complex implementation and maintenance, cross-shard operations difficult, expansion/re-sharding requires data migration and may cause brief inconsistency.| ##### Master-Slave Overselling Due to Delay ``` Scenario: Overselling due to delay User A places order → Master deducts inventory (stock: 1 → 0) → But Slave hasn't synced yet (still shows stock=1) Meanwhile, User B queries inventory → Reads from Slave (because system does read-write separation) → Sees inventory still has 1, so also places order User B's order request goes to Master → Master executes deduction again → At this point may become negative (overselling) This is inventory inconsistency caused by master-slave replication delay. ``` ##### How to Reduce Delay Risk | Method | Approach | Cost | | ------------------ | -------------------------------- | ------- | | **Force read from master (no read-write separation)** | For critical business like flash sales, only read from master node data | Master node pressure increases | | **Semi-synchronous replication (WAIT command)** | Master waits for at least N Slaves to confirm write before returning success | Performance degradation | | **Hotspot data centralized on single machine** | Fix flash sale inventory on one Redis node for processing, no sharding | Reduces complexity | | **Async consistency compensation** | Scheduled reconciliation, rollback oversold orders | Increases complex logic | ### Next Chapter Ticket-Craze: Kafka - https://hackmd.io/@chaodotcom/BJCkJAikWl