天天看點

Redis事務詳述

 本文已收錄于專欄

❤️《Redis之大廠必備技能包》❤️

上千人點贊收藏,全套Redis學習資料,大廠必備技能!

目錄

1、簡介

2、指令介紹

2.1 簡介

2.2 MULTI(開啟事務)

2.3 EXEC(執行事務)

2.4 DISCARD(取消事務)

2.5 WATCH(監視)

2.6 UNWATCH

3、Jedis 使用事務

Redis類似大多數成熟的資料庫系統一樣,提供了事務機制。Redis的事務機制非常簡單,它沒有嚴格的事務模型,無法像關系型資料庫一樣保證操作的原子性。

Redis事務最大的作用是保證多個指令的串行執行,它可以借助于Redis單線程讀寫的特性,保證Redis事務中的指令不會被事務外的指令打攪,不過要注意它不是原子性的。

完整事務案例:

Redis事務詳述
Redis事務詳述

使用Redis事務,一個最需要注意的問題是,指令多,網絡開銷高;是以我們一定要結合管道pipeline一起使用,這樣可以将多次網絡io操作壓縮成單次。

Redis事務相關的指令有五個,分别是MULTI、EXEC、DISCARD、WATCH、UNWATCH

Redis事務詳述
Redis事務詳述
Redis事務詳述

通過模拟一個簡單的餘額增加的例子,使用Jedis用戶端來使用Redis的事務。

1.package com.lizba.redis.tx;
 
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
 
import java.math.BigDecimal;
import java.util.List;
 
/**
 * <p>
 *      Redis事務demo
 * </p>
 *
 * @Author: Liziba
 * @Date: 2021/9/9 23:53
 */
public class TransactionDemo {
 
    private Jedis client;
 
    public TransactionDemo(Jedis client) {
        this.client = client;
    }
 
    /**
     * 添加餘額
     *
     * @param userId    使用者id
     * @param amt       添加餘額
     * @return
     */
    public BigDecimal addBalance(String userId, BigDecimal amt) {
        String key = this.keyFormat(userId);
        // 初始使用者餘額為0
        client.setnx(key, "0");
        while (true) {
            client.watch(key);
            BigDecimal balance = new BigDecimal(client.get(key)).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal amount = balance.add(amt);
            Transaction tx = client.multi();
            tx.set(key, amount.toPlainString());
            List<Object> exec = tx.exec();
            // 傳回值不為空則證明Redis事務成功
            if (exec != null) {
                break;
            }
        }
        return new BigDecimal(client.get(key)).setScale(2, BigDecimal.ROUND_HALF_UP);
    }
 
    /**
     * 擷取總金額
     *
     * @param userId 使用者id
     * @return
     */
    public BigDecimal getAmount(String userId) {
        String amt = client.get(keyFormat(userId));
        return new BigDecimal(amt);
    }
 
    /**
     * Redis key
     * @param userId 使用者id
     * @return
     */
    private String keyFormat(String userId) {
        return String.format("balance:%s",userId);
    }
 
}      
Redis事務詳述
Redis事務詳述