Redis ialah sistem caching data dalam memori sumber terbuka yang boleh menyimpan dan membaca data. Dalam persekitaran yang diedarkan, apabila berbilang aplikasi beroperasi pada sumber yang sama pada masa yang sama, masalah dengan data kotor dan ketidakkonsistenan data mungkin berlaku. Untuk menyelesaikan masalah ini, kami boleh memperkenalkan kunci teragih untuk memastikan ketekalan data.
Artikel ini membantu pembaca memahami cara menggunakan Redis untuk melaksanakan kunci teragih dengan memperkenalkan senario aplikasi, prinsip dan kaedah pelaksanaan kunci edaran Redis.
1. Senario aplikasi
Dalam sistem yang diedarkan, aplikasi mungkin perlu mengendalikan berbilang sumber pada masa yang sama. Jadi bagaimana untuk memastikan bahawa operasi aplikasi ini pada sumber adalah selamat untuk benang? Pada masa ini, kunci yang diedarkan perlu diperkenalkan.
Kunci teragih boleh digunakan untuk menyelesaikan masalah berikut:
(1) Elakkan berbilang pelanggan daripada mengubah suai sumber yang sama pada masa yang sama, mengakibatkan ketidakkonsistenan data.
(2) Halang klien daripada membuat berbilang pengubahsuaian kepada sumber yang sama disebabkan oleh kelewatan rangkaian dan isu lain.
(3) Halang pelanggan daripada menduduki sumber terlalu lama, menyebabkan pelanggan lain tidak dapat mengakses sumber seperti biasa.
2. Prinsip
Kunci diedarkan Redis terutamanya dilaksanakan melalui arahan setnx. Perintah setnx ialah operasi atom dalam Redis, yang memastikan bahawa dalam operasi serentak berbilang pelanggan, hanya satu pelanggan boleh berjaya menetapkan pasangan nilai kunci kepada Redis.
Seterusnya, mari kita lihat pelaksanaan khusus kunci yang diedarkan Redis.
3. Kaedah pelaksanaan
(1) Mendapatkan kunci
Dalam proses memperoleh kunci, kita perlu menggunakan perintah setnx untuk menetapkan pasangan nilai kunci . Jika tetapan itu berjaya, ini bermakna kita telah memperoleh kunci Jika tetapan tidak berjaya, kita perlu menunggu untuk tempoh masa dan cuba mendapatkan kunci itu semula.
Pertama, kami memperoleh kunci melalui blok kod berikut:
boolean lock = jedis.setnx(key, value) == 1;
Antaranya, kunci dan nilai masing-masing mewakili nama dan nilai kunci, dan jedis mewakili klien Redis.
Jika nama kunci tidak wujud dalam Redis, maka nilai pulangan kod di atas ialah 1, menunjukkan bahawa tetapan berjaya dan kunci diperoleh. Jika nama kunci sudah wujud dalam Redis, nilai pulangan kod di atas ialah 0, menunjukkan bahawa tetapan gagal dan pemerolehan kunci gagal.
(2) Lepaskan kunci
Semasa proses melepaskan kunci, kita perlu menggunakan arahan del untuk memadamkan pasangan nilai kunci dalam Redis.
Mula-mula, kami melepaskan kunci melalui blok kod berikut:
long result = jedis.del(key);
Antaranya, kunci mewakili nama kunci, dan jedis mewakili klien Redis.
Jika pasangan nilai kunci dalam Redis berjaya dipadamkan, nilai pulangan kod di atas ialah 1, menunjukkan bahawa kunci berjaya dilepaskan. Jika pasangan nilai kunci tidak wujud dalam Redis, nilai pulangan kod di atas ialah 0, menunjukkan bahawa pelepasan kunci gagal.
(3) Tetapkan masa tamat tempoh kunci
Untuk mengelakkan kunci daripada diduduki sepanjang masa, kita perlu menetapkan masa tamat tempoh kunci. Apabila pemegang kunci tidak melepaskan kunci dalam tempoh masa tertentu, Redis akan memadamkan kunci secara automatik untuk mengelakkan kunci daripada diduduki selama-lamanya.
Pertama, kita perlu menetapkan masa tamat tempoh kunci melalui blok kod berikut:
jedis.expire(key, timeout);
Antaranya, kunci mewakili nama kunci dan tamat masa mewakili masa tamat tempoh kunci, dalam beberapa saat.
Untuk mengelakkan pemadaman kunci pelanggan lain secara tidak sengaja, anda perlu menentukan sama ada nilai kunci itu konsisten dengan nilai yang anda tetapkan apabila anda memperolehnya.
String value = jedis.get(key); if (StringUtils.isNotBlank(value) && value.equals(uuid)) { jedis.del(key); }
Antaranya, uuid mewakili pengecam unik pelanggan untuk mendapatkan kunci.
(4) Elakkan kunci pelanggan lain daripada dipadam secara tidak sengaja
Selepas menggunakan kunci, kita perlu melepaskan kunci dengan betul, jika tidak kunci pelanggan lain akan dipadamkan secara tidak sengaja.
Oleh itu, untuk mengelakkan pemadaman kunci pelanggan lain secara tidak sengaja, kami perlu menambah pengecam unik pada kod.
Pertama, dalam proses memperoleh kunci, kita perlu menjana pengecam unik untuk pelanggan, seperti yang ditunjukkan di bawah:
String uuid = UUID.randomUUID().toString();
Kemudian, dalam proses memperoleh kunci dan melepaskan kunci, kita perlu Tentukan sama ada nilai yang sepadan dengan kunci adalah sama dengan uuid untuk menentukan sama ada kunci diperoleh oleh klien semasa Dalam proses memperoleh dan melepaskan kunci, uuid perlu ditetapkan sebagai nilai kepada nilai yang sepadan dengan kunci.
Kod khusus adalah seperti berikut:
boolean lock = jedis.setnx(key, uuid) == 1; if (lock) { jedis.expire(key, timeout); } // 释放锁 String value = jedis.get(key); if (StringUtils.isNotBlank(value) && value.equals(uuid)) { jedis.del(key); }
(5) Contoh penggunaan yang salah
Dalam proses menggunakan kunci yang diedarkan, jika kita menghadapi situasi berikut, maka Akan menyebabkan kebuntuan:
// 获取锁 jedis.setnx(key, value); // 不释放锁
Oleh itu, apabila menggunakan kunci, anda mesti memberi perhatian untuk melepaskan kunci dengan betul, jika tidak, ia akan membawa akibat yang tidak dapat diramalkan kepada sistem.
(6) Kelas pelaksanaan
Akhir sekali, mari kita lihat cara merangkum kod di atas ke dalam kelas kunci yang diedarkan Redis.
import redis.clients.jedis.Jedis; import java.util.UUID; public class RedisLock { private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; private Jedis jedis; public RedisLock(Jedis jedis) { this.jedis = jedis; } /** * 尝试获取分布式锁 * @param key 锁 * @param requestId 请求标识 * @param expireTime 超期时间(秒) * @return 是否获取成功 */ public boolean tryGetDistributedLock(String key, String requestId, int expireTime) { String result = jedis.set(key, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); return LOCK_SUCCESS.equals(result); } /** * 释放分布式锁 * @param key 锁 * @param requestId 请求标识 * @return 是否释放成功 */ public boolean releaseDistributedLock(String key, String requestId) { String value = jedis.get(key); if (value != null && value.equals(requestId)) { jedis.del(key); return true; } return false; } /** * 获取请求标识 * @return 请求标识 */ public static String getRequestId() { return UUID.randomUUID().toString(); } }
Pada ketika ini, kami telah menyelesaikan pelaksanaan kunci yang diedarkan Redis.
4. Ringkasan
Artikel ini membantu pembaca memahami cara menggunakan Redis untuk melaksanakan kunci teragih dengan memperkenalkan senario aplikasi, prinsip dan kaedah pelaksanaan kunci edaran Redis. Memandangkan pelaksanaan kunci teragih agak rumit, kita perlu memberi perhatian kepada beberapa butiran, seperti menentukan sama ada nilai kunci itu konsisten dengan nilai yang ditetapkan semasa memperolehnya, dan menetapkan uuid sebagai nilai kepada kunci semasa proses memperoleh. dan melepaskan kunci Nilai yang sepadan ialah sederhana. Hanya dengan menggunakan kunci teragih dengan betul boleh memastikan ketekalan dan kebolehpercayaan data dalam sistem teragih.
Atas ialah kandungan terperinci Kaedah pelaksanaan kunci yang diedarkan Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!