Mesin tunggal berbilang benang: Di Java, kami biasanya menggunakan kunci tempatan seperti kelas ReetrantLock dan kata kunci yang disegerakkan untuk mengawal berbilang benang dalam proses JVM untuk mengakses perkongsian setempat sumber. Jika berbilang proses JVM berkongsi sumber yang sama, tiada cara untuk mencapai akses eksklusif bersama kepada sumber menggunakan kunci tempatan. Oleh itu, kunci yang diedarkan dilahirkan.
Contohnya: Sebanyak 3 salinan perkhidmatan pesanan sistem digunakan, semuanya menyediakan perkhidmatan kepada dunia luar. Pengguna perlu menyemak inventori sebelum membuat pesanan Untuk mengelakkan penjualan berlebihan, kunci diperlukan untuk mencapai akses segerak kepada operasi semakan inventori. Memandangkan perkhidmatan pesanan terletak dalam proses JVM yang berbeza, kunci tempatan tidak akan berfungsi dengan betul dalam kes ini. Kita perlu menggunakan kunci yang diedarkan, supaya walaupun beberapa utas tidak berada dalam proses JVM yang sama, mereka boleh mendapatkan kunci yang sama, dengan itu mencapai akses eksklusif bersama kepada sumber yang dikongsi.
Kunci teragih paling asas perlu dipenuhi:
Pengecualian bersama: pada bila-bila masa, kunci hanya boleh dipegang oleh satu utas Tahan;> SETNX lockKey uniqueValueSETNX
(integer) 1SETNX
> SETNX lockKey uniqueValue
(integer) 1> DEL lockKey
terus Padamkan kekunci yang sepadan melalui arahan DEL
Untuk mengelakkan pemadaman kunci lain secara tidak sengaja, kami mengesyorkan di sini Gunakan skrip Lua untuk menilai dengan nilai (nilai unik) yang sepadan dengan kunci.Ini adalah pelaksanaan kunci teragih Redis yang paling mudah Kaedah pelaksanaannya agak mudah dan prestasinya sangat cekap. Walau bagaimanapun, terdapat beberapa masalah dengan melaksanakan penguncian teragih dengan cara ini. Contohnya, jika aplikasi menghadapi beberapa masalah, seperti logik untuk melepaskan kunci tiba-tiba ditutup, kunci mungkin tidak dilepaskan dan sumber yang dikongsi tidak lagi boleh diakses oleh urutan/proses lain.
Skrip Lua dipilih untuk memastikan keatoman operasi buka kunci. Kerana Redis boleh melaksanakan skrip Lua dengan cara atom, dengan itu memastikan keatoman operasi pelepasan kunci.
// 释放锁时,先比较锁对应的 value 值是否相等,避免锁的误释放 if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end
2. Mengapakah kita perlu menetapkan masa tamat tempoh untuk kunci
Terutamanya untuk mengelakkan kunci daripada dilepaskan
lockKey: nama kunci;
使用方式举例:
// 1.获取指定的分布式锁对象
RLock lock = redisson.getLock("lock");
// 2.拿锁且不设置锁超时时间,具备 Watch Dog 自动续期机制
lock.lock();
// 3.执行业务
...
// 4.释放锁
lock.unlock();
只有未指定锁超时时间,才会使用到 Watch Dog 自动续期机制。
// 手动给锁设置过期时间,不具备 Watch Dog 自动续期机制 lock.lock(10, TimeUnit.SECONDS);
总的来说就是使用Redisson,它带有自动的续期机制
所谓可重入锁指的是在一个线程中可以多次获取同一把锁,比如一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法即可重入 ,而无需重新获得锁。像 Java 中的 synchronized 和 ReentrantLock 都属于可重入锁。
可重入分布式锁的实现核心思路是线程在获取锁的时候判断是否为自己的锁,如果是的话,就不用再重新获取了。为此,我们可以为每个锁关联一个可重入计数器和一个占有它的线程。当可重入计数器大于 0 时,则锁被占有,需要判断占有该锁的线程和请求获取锁的线程是否为同一个。
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan kunci diedarkan Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!