Rumah  >  Artikel  >  pangkalan data  >  Mari kita bincangkan tentang prinsip kunci teragih dan cara Redis melaksanakan kunci teragih

Mari kita bincangkan tentang prinsip kunci teragih dan cara Redis melaksanakan kunci teragih

藏色散人
藏色散人ke hadapan
2023-01-27 07:30:011140semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang redis, yang terutamanya memperkenalkan kunci teragih? Bagaimanakah Redis melaksanakan kunci teragih? Apakah syarat yang perlu dipenuhi? Mari kita lihat di bawah, semoga dapat membantu rakan-rakan yang memerlukan.

1. Prinsip asas kunci teragih

Kunci teragih: kunci yang boleh dilihat dan saling eksklusif kepada berbilang proses dalam sistem teragih atau mod kelompok.

Syarat yang mengagihkan kunci hendaklah memenuhi:

  • Keterlihatan: Berbilang rangkaian boleh melihat hasil yang sama Nota: Keterlihatan yang dinyatakan di sini bukan keterlihatan memori yang dirujuk dalam pengaturcaraan serentak. Ini bermakna berbilang proses boleh melihat perubahan Pengecualian bersama: Pengecualian bersama ialah syarat paling asas untuk kunci yang diedarkan, membenarkan program untuk melaksanakan secara bersiri
  • Ketersediaan tinggi: program tidak mudah ranap dan ketersediaan tinggi dijamin pada setiap masa
  • Prestasi tinggi: Memandangkan penguncian itu sendiri mengurangkan prestasi, kunci yang diedarkan sendiri memerlukan prestasi penguncian yang lebih tinggi dan prestasi pelepasan kunci
  • Keselamatan: Keselamatan juga merupakan sebahagian daripada program Pautan penting
Terdapat tiga kunci teragih biasa:

    Mysql: mysql sendiri mempunyai mekanisme kunci , tetapi disebabkan oleh prestasi purata mysql itu sendiri, apabila menggunakan kunci yang diedarkan, ia sebenarnya agak jarang menggunakan mysql sebagai kunci teragih
  • Redis: redis ialah kunci teragih yang sangat biasa dengan cara penggunaan ini, kini pembangunan peringkat perusahaan pada asasnya menggunakan redis atau zookeeper sebagai kunci teragih . Menggunakan kaedah setnx, jika kunci berjaya dimasukkan, ia bermakna kunci diperolehi Jika seseorang memasukkan berjaya, dan orang lain gagal memasukkan, ia bermakna kunci tidak boleh diperolehi, gunakan set logik ini kunci teragih
  • Zookeeper: Zookeeper juga merupakan penyelesaian yang lebih baik untuk melaksanakan kunci teragih dalam pembangunan peringkat perusahaan

Mari kita bincangkan tentang prinsip kunci teragih dan cara Redis melaksanakan kunci teragih2. Melaksanakan kunci teragih berdasarkan Redis

Dua kaedah asas perlu dilaksanakan semasa melaksanakan kunci teragih:

    Peroleh kunci:
  • Pengecualian bersama: pastikan hanya satu utas boleh memperoleh kunci
    • Tidak menyekat: cuba sekali, kembalikan benar jika berjaya, palsu jika gagal
  • Keluarkan kunci:
  • Keluaran manual
    • Keluaran tamat masa: Tambahkan tamat masa apabila memperoleh kunci
Prinsip kunci teragih berdasarkan Redis:

SET resource_name my_random_value NX PX 30000
resource_name: nama sumber, kunci yang berbeza boleh dibezakan mengikut perniagaan yang berbeza
  • my_random_value: rawak nilai, nilai rawak setiap utas adalah berbeza, digunakan untuk pengesahan apabila melepaskan kunci
  • NX: Tetapan berjaya apabila kunci tidak wujud dan tetapan tidak berjaya apabila kunci wujud
  • PX: masa tamat tempoh automatik, jika keabnormalan berlaku, kunci boleh tamat tempoh
  • Menggunakan atomicity NX, apabila beberapa utas serentak, hanya satu utas boleh ditetapkan dengan jayanya tetapan berjaya. Tentukan antara muka ILock

2. Melaksanakan kunci teragih berdasarkan Redis - RedisLock

Masalah pemadaman kunci secara tidak sengaja
public interface ILock extends AutoCloseable {
    /**
     * 尝试获取锁
     *
     * @param timeoutSec 锁持有的超时时间,过期后自动释放
     * @return true代表获取锁成功;false代表获取锁失败
     */
    boolean tryLock(long timeoutSec);

    /**
     * 释放锁
     * @return
     */
    void unLock();
}

Perihalan masalah:

public class SimpleRedisLock {
    private final StringRedisTemplate stringRedisTemplate;
    private final String name;

    public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }

    private static final String KEY_PREFIX = "lock:";

    @Override
    public boolean tryLock(long timeoutSec) {
        //获取线程标识
        String threadId = Thread.currentThread().getId();
        //获取锁
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

    @Override
    public void unLock() {
        //通过del删除锁
        stringRedisTemplate.delete(KEY_PREFIX + name);
    }

    @Override
    public void close() {
        unLock();
    }
}
Benang 1 yang memegang kunci disekat di dalam kunci Pada masa ini, kunci dilepaskan secara automatik pada masa ini, utas 2 cuba diperolehi kunci, dan kemudian utas 1 bertindak balas semasa pelaksanaan utas 2 yang memegang kunci Datang ke sini, teruskan pelaksanaan, dan capai logik kunci pemadaman Pada masa ini, kunci yang sepatutnya dimiliki oleh utas 2 ini kes terpadam kunci secara tidak sengaja.

Penyelesaian:

Apabila menyimpan kunci, letakkan pengecam benang anda sendiri Apabila memadamkan kunci, tentukan sama ada pengecam kunci semasa ialah anda disimpan. Jika ia dimasukkan, ia akan dipadamkan.

Versi 2: Selesaikan masalah pemadaman kunci secara tidak sengaja

Masalah atomicity pelepasan kunci

Analisis masalah:

public class SimpleRedisLock {
    private final StringRedisTemplate stringRedisTemplate;
    private final String name;

    public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }

    private static final String KEY_PREFIX = "lock:";
    private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";

    @Override
    public boolean tryLock(long timeoutSec) {
        //获取线程标识
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        //获取锁
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

    @Override
    public void unLock() {
        // 获取线程标示
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁中的标示
        String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
        // 判断标示是否一致
        if(threadId.equals(id)) {
            // 释放锁
            stringRedisTemplate.delete(KEY_PREFIX + name);
        }
    }

    @Override
    public void close() {
        unLock();
    }
}
Kod di atas untuk melepaskan kunci masih mempunyai masalah memadam kunci secara tidak sengaja Apabila benang 1 memperoleh ID benang dalam kunci dan menentukan bahawa ia adalah kunci sendiri berdasarkan ID, kunci dilepaskan secara automatik apabila ia tamat tempoh. Kebetulan benang 2 cuba mendapatkan kunci dan mendapatkan kunci , pada masa ini benang 1 masih menjalankan operasi melepaskan kunci, yang membawa kepada kunci yang dipegang oleh benang 2 dipadamkan secara tidak sengaja.

Alasannya ialah proses pelepasan kunci yang dilaksanakan oleh kod java bukanlah operasi atom dan mempunyai masalah keselamatan benang.

Penyelesaian:

Redis menyediakan fungsi skrip Lua Menulis berbilang arahan Redis dalam satu skrip boleh memastikan atomicity pelaksanaan berbilang arahan.

Versi 3: Panggil skrip Lua untuk mengubah kunci yang diedarkan

Pembelajaran yang disyorkan: "

Tutorial Video Redis

"

Atas ialah kandungan terperinci Mari kita bincangkan tentang prinsip kunci teragih dan cara Redis melaksanakan kunci teragih. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

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