How to use redis optimistic lock and pessimistic lock
Concept
Redis is an in-memory key-value storage system that supports a variety of data structures, including strings, hashes, lists, etc. Redis provides two locking mechanisms, namely optimistic locking and pessimistic locking.
Optimistic lock
Optimistic lock is an optimistic concurrency control strategy. It believes that data will not be occupied by other threads in most cases, so every time the data needs to be modified, it does not The lock is acquired and the modification is made directly. In Redis, optimistic locking can be implemented through the WATCH and CAS commands. The WATCH command is used to monitor one or more keys, and the CAS command is used to check and update the value of the key.
For example, if there is a counter with the key name counter, multiple clients need to operate on it. You can use optimistic locking to monitor the counter key before each client operation by executing the WATCH command
WATCH counter current_count = GET counter new_count = current_count + 1 MULTI SET counter new_count EXEC
Then, before the EXEC command is executed, use the GET command to obtain the value of the counter key again and save it. Compare with the previously obtained value. If the values are equal, it means that no other client has modified the counter key during the period. At this time, you can use the CAS command to set the new value to the counter key. If the values are different, it means that other clients have modified the counter key during this period and the operation needs to be performed again.
GET counter
Pessimistic lock
Pessimistic lock is a pessimistic concurrency control strategy. It believes that the data will be occupied by other threads in most cases, so every time the data needs to be modified, it will first Obtain the lock to ensure that no other thread can access the data during modification. In Redis, pessimistic locking can be implemented through the WATCH command, which can monitor one or more keys. If the value of any monitored key changes during transaction execution, the entire transaction will be rolled back.
Still the above example
WATCH counter current_count = GET counter new_count = current_count + 1 MULTI SET counter new_count EXEC
If other clients modify the counter key during the execution of the transaction, the entire transaction will be rolled back and needs to be re-executed.
Although pessimistic locking can ensure the advantage of data consistency, its disadvantage is that it needs to acquire the lock first, which may cause thread blocking, thereby affecting concurrency performance.
Optimistic lock example
Suppose there is an e-commerce platform where users can purchase goods. In order to ensure that the reduction of product inventory is consistent, Redis's optimistic locking mechanism can be used to achieve this.
First, we need to save the inventory information of each product in Redis, using a hash data structure to save it, for example:
Then, in the business logic, when the user purchases a product, The following steps need to be performed:
Use the WATCH command to monitor the product inventory key, such as stock:sku001;
Use the GET command to obtain the current product inventory quantity ;
Check whether the product inventory is sufficient, if not, return an error message directly;
Calculate the new inventory quantity and use the MULTI command to open it A transaction;
Use the HSET command to save the new inventory quantity into Redis;
Execute the transaction if there are other customers during execution If the product inventory is modified on the end, the transaction will be rolled back and needs to be re-executed.
The following is a sample code implemented using Spring Boot:
@Service public class OrderService { private final RedisTemplate<String, Integer> redisTemplate; @Autowired public OrderService(RedisTemplate<String, Integer> redisTemplate) { this.redisTemplate = redisTemplate; } public void placeOrder(String sku, int quantity) { String stockKey = "stock:" + sku; while (true) { // 监视商品库存键,以便在事务开始前检测是否有其他客户端修改了库存 redisTemplate.watch(stockKey); // 获取当前库存数量 int currentStock = redisTemplate.opsForHash().get(stockKey, sku); // 检查库存是否足够 if (currentStock < quantity) { // 库存不足,放弃事务并抛出异常 redisTemplate.unwatch(); throw new RuntimeException("Out of stock"); } // 计算新的库存数量 int newStock = currentStock - quantity; // 开始事务 redisTemplate.multi(); // 更新库存数量 redisTemplate.opsForHash().put(stockKey, sku, newStock); // 提交事务 List<Object> results = redisTemplate.exec(); // 如果事务执行成功,则退出循环 if (results != null) { break; } // 如果事务执行失败,则重试 } } }
In the above code, we use RedisTemplate to operate Redis, where the watch method is used to monitor product inventory key, the opsForHash method is used to obtain and modify the value of product inventory, and the multi and exec methods are used to open and submit transactions.
Pessimistic lock example
In addition to optimistic locking, Redis also supports pessimistic locking, which can be achieved by setting the NX (Not Exist) or XX (Exist) flag. For example, when the NX flag is set to true, if the lock does not exist, OK will be returned and a lock will be created; if the lock already exists, null will be returned, indicating failure to obtain the lock. On the contrary, when the XX flag is set to true, if the lock already exists, OK will be returned, indicating that the lock acquisition is successful; if the lock does not exist, null will be returned, indicating that the lock acquisition failed.
The following is a pessimistic lock example code implemented using Spring Boot:
@Service public class OrderService { private final RedisTemplate<String, String> redisTemplate; @Autowired public OrderService(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } public void placeOrder(String sku, int quantity) { String lockKey = "lock:" + sku; // 尝试获取锁,如果锁已经存在,说明有其他线程正在执行相关操作 Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked"); if (!locked) { // 获取锁失败,抛出异常 throw new RuntimeException("Unable to acquire lock"); } // 设置锁的过期时间,防止锁被一直占用 redisTemplate.expire(lockKey, 10, TimeUnit.SECONDS); try { // 执行订单创建、扣减库存等操作 } finally { // 释放锁 redisTemplate.delete(lockKey); } } }
In the above code, we use the setIfAbsent method to try to acquire the lock. If the lock already exists, it means that other threads are executing For related operations, false will be returned at this time, indicating that the lock acquisition failed; otherwise, true will be returned, indicating that the lock acquisition was successful. We will first acquire the lock, then set the expiration time of the lock and perform corresponding operations, and finally release the lock.
The above is the detailed content of How to use redis optimistic lock and pessimistic lock. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Redis cluster mode deploys Redis instances to multiple servers through sharding, improving scalability and availability. The construction steps are as follows: Create odd Redis instances with different ports; Create 3 sentinel instances, monitor Redis instances and failover; configure sentinel configuration files, add monitoring Redis instance information and failover settings; configure Redis instance configuration files, enable cluster mode and specify the cluster information file path; create nodes.conf file, containing information of each Redis instance; start the cluster, execute the create command to create a cluster and specify the number of replicas; log in to the cluster to execute the CLUSTER INFO command to verify the cluster status; make

How to clear Redis data: Use the FLUSHALL command to clear all key values. Use the FLUSHDB command to clear the key value of the currently selected database. Use SELECT to switch databases, and then use FLUSHDB to clear multiple databases. Use the DEL command to delete a specific key. Use the redis-cli tool to clear the data.

Using the Redis directive requires the following steps: Open the Redis client. Enter the command (verb key value). Provides the required parameters (varies from instruction to instruction). Press Enter to execute the command. Redis returns a response indicating the result of the operation (usually OK or -ERR).

To read a queue from Redis, you need to get the queue name, read the elements using the LPOP command, and process the empty queue. The specific steps are as follows: Get the queue name: name it with the prefix of "queue:" such as "queue:my-queue". Use the LPOP command: Eject the element from the head of the queue and return its value, such as LPOP queue:my-queue. Processing empty queues: If the queue is empty, LPOP returns nil, and you can check whether the queue exists before reading the element.

Using Redis to lock operations requires obtaining the lock through the SETNX command, and then using the EXPIRE command to set the expiration time. The specific steps are: (1) Use the SETNX command to try to set a key-value pair; (2) Use the EXPIRE command to set the expiration time for the lock; (3) Use the DEL command to delete the lock when the lock is no longer needed.

The best way to understand Redis source code is to go step by step: get familiar with the basics of Redis. Select a specific module or function as the starting point. Start with the entry point of the module or function and view the code line by line. View the code through the function call chain. Be familiar with the underlying data structures used by Redis. Identify the algorithm used by Redis.

Redis data loss causes include memory failures, power outages, human errors, and hardware failures. The solutions are: 1. Store data to disk with RDB or AOF persistence; 2. Copy to multiple servers for high availability; 3. HA with Redis Sentinel or Redis Cluster; 4. Create snapshots to back up data; 5. Implement best practices such as persistence, replication, snapshots, monitoring, and security measures.

Use the Redis command line tool (redis-cli) to manage and operate Redis through the following steps: Connect to the server, specify the address and port. Send commands to the server using the command name and parameters. Use the HELP command to view help information for a specific command. Use the QUIT command to exit the command line tool.
