Rumah  >  Artikel  >  pangkalan data  >  Apakah dua perangkap yang perlu dielakkan oleh kunci yang diedarkan oleh Redis?

Apakah dua perangkap yang perlu dielakkan oleh kunci yang diedarkan oleh Redis?

WBOY
WBOYke hadapan
2023-05-29 22:52:041222semak imbas

1 Perangkap pertama: masa keluaran kunci yang salah

1.1. Mendapati masalah

Analisis masalah dalam kod berikut:

// 分布式锁服务
public interface RedisLockService {
    // 获取锁
    public boolean getLock(String key);
    // 释放锁
    public boolean releaseLock(String key);
}

// 业务服务
public class BizService {

    @Resource
    private RedisLockService redisLockService;

    public void bizMethod(String bizId) {
        try {
            // 获取锁
            if(redisLockService.getLock(bizId)) {
                // 业务重复校验
                if(!bizValidate(bizId)) {
                    throw new BizException(ErrorBizCode.REPEATED);
                }
                // 执行业务
                return doBusiness();
            }
            // 获取锁失败
            throw new BizException(ErrorBizCode.GET_LOCK_ERROR);
        } finally {
            // 释放锁
            redisLockService.releaseLock(bizId);
        }
    }
}

Kod di atas nampaknya sebenarnya, ia menyembunyikan masalah besar. Masalahnya ialah apabila melepaskan kunci, tiada pengesahan sama ada benang semasa telah memperoleh kunci:

  • Benang 1 dan utas 2 mengakses kaedah perniagaan pada masa yang sama

  • benang 2 Berjaya memperoleh kunci dan memulakan pemprosesan perniagaan

  • Benang 1 tidak memperoleh kunci, tetapi berjaya melepaskan kunci

  • Pada masa ini, utas 3 cuba memperoleh Kunci berjaya, tetapi perniagaan utas 2 belum diproses, jadi utas 3 tidak akan menyebabkan pengecualian pertindihan perniagaan

  • akhirnya menyebabkan utas 2 dan utas 3 berulang kali melaksanakan perniagaan

1.2 Selesaikan masalah

Penyelesaian adalah membenarkan kunci dilepaskan hanya selepas mengesahkan bahawa perolehan kunci berjaya:

public class BizService {

    @Resource
    private RedisLockService redisLockService;

    public void bizMethod(String bizId) {
        boolean getLockSuccess = false;
        try {
            // 尝试获取锁
            getLockSuccess = redisLockService.getLock(bizId);
            // 获取锁成功
            if(getLockSuccess) {
                // 业务重复校验
                if(!bizValidate(bizId)) {
                    throw new BizException(ErrorBizCode.REPEATED);
                }
                // 执行业务
                return doBusiness();
            }
            // 获取锁失败
            throw new BizException(ErrorBizCode.GET_LOCK_ERROR);
        } finally {
            // 获取锁成功才允许释放锁
            if(getLockSuccess) {
                redisLockService.releaseLock(bizId);
            }
        }
    }
}

2 Lubang kedua: masalah ketidaksahihan cache

Tidak. Masalah kedua ialah Redis juga mempunyai mekanisme pembersihan memori, yang mungkin menyebabkan kunci yang diedarkan gagal .

2.1 Mekanisme pembersihan tamat tempoh

(1) Pemadaman biasa

Redis kerap menyemak kunci mana yang telah tamat tempoh dan memadamnya jika didapati telah tamat tempoh

(2) Pemadaman malas

Jika terdapat terlalu banyak kunci, pemadaman biasa akan menggunakan banyak sumber, jadi strategi pemadaman malas diperkenalkan

Jika Redis mendapati bahawa kunci telah tamat tempoh semasa mengaksesnya, Pemadaman langsung

2.2 Mekanisme kitar semula memori

Apabila memori tidak mencukupi, Redis akan memilih beberapa elemen untuk pemadaman:

tiada enviction

melarang pengusiran data, baru Operasi tulis akan melaporkan ralat

volatile-lru

Pilih data yang paling kurang digunakan baru-baru ini daripada set data dengan masa tamat tempoh untuk dihapuskan

volatile-ttl

Pilih data yang akan tamat tempoh daripada set data dengan masa tamat tempoh ditetapkan untuk dihapuskan

volatile-random

Pilih mana-mana data untuk dihapuskan daripada set data dengan set masa tamat tempoh

kekunci semua- lru

Pilih data yang paling kurang digunakan baru-baru ini daripada set data untuk dihapuskan

allkeys-random

Pilih mana-mana data daripada set data untuk dihapuskan

Terdapat sekurang-kurangnya dua Senario yang menyebabkan kegagalan kunci teragih:

  • Senario 1: Redis mempunyai ingatan yang tidak mencukupi untuk kitar semula memori dan menggunakan strategi kitar semula allkeys-lru atau allkeys-random menyebabkan kegagalan kunci

  • Senario 2: Benang memperoleh kunci yang diedarkan dengan jayanya, tetapi masa pemprosesan terlalu lama. Pada masa ini, kunci tamat tempoh dan dikosongkan dengan kerap, menyebabkan urutan lain berjaya memperoleh kunci dan melaksanakan perniagaan berulang kali

2.3 Penguncian optimistik

Penyelesaian umum adalah untuk melindungi pada lapisan pangkalan data Sebagai contoh, perniagaan potongan inventori menggunakan penguncian optimistik pada lapisan pangkalan data.

rreeee

Atas ialah kandungan terperinci Apakah dua perangkap yang perlu dielakkan oleh kunci yang diedarkan oleh Redis?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam