Cara melaksanakan kunci teragih dalam Go digabungkan dengan Redis
Senario contoh Redis Tunggal
Jika anda biasa dengan arahan Redis, anda boleh segera memikirkan untuk menggunakan set Redis jika tidak wujud operasi untuk melaksanakannya, dan ia kini standard Pelaksanaannya ialah siri arahan SET resource_name my_random_value NX PX 30000, di mana:
resource_name mewakili sumber yang akan dikunci
NX mewakili jika ia tidak wujud Kemudian tetapkan
PX 30000 untuk menunjukkan masa tamat tempoh ialah 30000 milisaat, iaitu 30 saat
my_random_value mestilah unik di kalangan semua pelanggan , semua pemeroleh (pesaing) kunci yang sama tidak boleh mempunyai nilai yang sama.
Nilai nilai mestilah nombor rawak terutamanya untuk melepaskan kunci dengan lebih selamat Apabila melepaskan kunci, gunakan skrip untuk memberitahu Redis: hanya kunci yang wujud dan nilai yang disimpan sama seperti nilai yang saya nyatakan Barulah saya boleh diberitahu bahawa pemadaman itu berjaya. Ini boleh dicapai melalui skrip Lua berikut:
if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end
Contohnya: Klien A memperoleh kunci sumber, tetapi disekat dengan serta-merta oleh operasi lain Apabila Klien A mahu melepaskan kunci selepas menjalankan operasi lain, ia bertukar bahawa Kunci telah tamat masa dan telah dikeluarkan secara automatik oleh Redis, dan dalam tempoh ini kunci sumber telah diperoleh semula oleh klien B.
Skrip Lua digunakan kerana penghakiman dan pemadaman adalah dua operasi, jadi ada kemungkinan A akan melepaskan kunci secara automatik selepas ia tamat tempoh sebaik sahaja ia menilainya, dan kemudian B memperoleh kunci itu, dan kemudian A memanggil Del, menyebabkan B ke Kunci dilepaskan.
Contoh mengunci dan membuka kunci
package main import ( "context" "errors" "fmt" "github.com/brianvoe/gofakeit/v6" "github.com/go-redis/redis/v8" "sync" "time" ) var client *redis.Client const unlockScript = ` if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end` func lottery(ctx context.Context) error { // 加锁 myRandomValue := gofakeit.UUID() resourceName := "resource_name" ok, err := client.SetNX(ctx, resourceName, myRandomValue, time.Second*30).Result() if err != nil { return err } if !ok { return errors.New("系统繁忙,请重试") } // 解锁 defer func() { script := redis.NewScript(unlockScript) script.Run(ctx, client, []string{resourceName}, myRandomValue) }() // 业务处理 time.Sleep(time.Second) return nil } func main() { client = redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", }) var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() ctx, _ := context.WithTimeout(context.Background(), time.Second*3) err := lottery(ctx) if err != nil { fmt.Println(err) } }() go func() { defer wg.Done() ctx, _ := context.WithTimeout(context.Background(), time.Second*3) err := lottery(ctx) if err != nil { fmt.Println(err) } }() wg.Wait() }
Mari kita lihat dahulu fungsi loteri(), yang menyerupai operasi loteri Apabila memasuki fungsi, mula-mula gunakan SET resource_name my_random_value NX PX 30000 untuk mengunci, di sini gunakan UUID sebagai nilai Rawak Jika operasi gagal, ia akan kembali secara langsung dan membolehkan pengguna mencuba lagi Jika logik buka kunci berjaya dilaksanakan dalam penangguhan, logik buka kunci adalah untuk melaksanakan skrip Lua yang disebutkan di atas dan kemudian melakukan pemprosesan perniagaan.
Kami melaksanakan dua goroutine dalam fungsi main() untuk memanggil fungsi lottery() secara serentak Salah satu operasi akan gagal secara langsung kerana kunci tidak boleh diperolehi.
Ringkasan
Jana nilai rawak
Gunakan SET resource_name my_random_value NX PX 30000 untuk mengunci
<🎜 🎜> Jika kunci gagal, kembali terus ke - tunda untuk menambah logik buka kunci untuk memastikan
- akan dilaksanakan apabila fungsi keluar Logik perniagaan
- Senario contoh Redis Berbilang
Dalam kes satu contoh, jika tika ini hang, semua permintaan akan gagal kerana kunci tidak boleh diperolehi, jadi kami Anda memerlukan berbilang kejadian Redis yang diedarkan pada mesin yang berbeza, dan anda perlu mendapatkan kunci kebanyakan nod untuk berjaya mengunci Ini ialah algoritma RedLock. Kita perlu memperoleh kunci pada berbilang kejadian Redis pada masa yang sama, tetapi ia sebenarnya berdasarkan algoritma kejadian tunggal.
Contoh Tambah dan Buka Kunci
package main import ( "context" "errors" "fmt" "github.com/brianvoe/gofakeit/v6" "github.com/go-redis/redis/v8" "sync" "time" ) var clients []*redis.Client const unlockScript = ` if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end` func lottery(ctx context.Context) error { // 加锁 myRandomValue := gofakeit.UUID() resourceName := "resource_name" var wg sync.WaitGroup wg.Add(len(clients)) // 这里主要是确保不要加锁太久,这样会导致业务处理的时间变少 lockCtx, _ := context.WithTimeout(ctx, time.Millisecond*5) // 成功获得锁的Redis实例的客户端 successClients := make(chan *redis.Client, len(clients)) for _, client := range clients { go func(client *redis.Client) { defer wg.Done() ok, err := client.SetNX(lockCtx, resourceName, myRandomValue, time.Second*30).Result() if err != nil { return } if !ok { return } successClients <- client }(client) } wg.Wait() // 等待所有获取锁操作完成 close(successClients) // 解锁,不管加锁是否成功,最后都要把已经获得的锁给释放掉 defer func() { script := redis.NewScript(unlockScript) for client := range successClients { go func(client *redis.Client) { script.Run(ctx, client, []string{resourceName}, myRandomValue) }(client) } }() // 如果成功加锁得客户端少于客户端数量的一半+1,表示加锁失败 if len(successClients) < len(clients)/2+1 { return errors.New("系统繁忙,请重试") } // 业务处理 time.Sleep(time.Second) return nil } func main() { clients = append(clients, redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", DB: 0, }), redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", DB: 1, }), redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", DB: 2, }), redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", DB: 3, }), redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", DB: 4, })) var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() ctx, _ := context.WithTimeout(context.Background(), time.Second*3) err := lottery(ctx) if err != nil { fmt.Println(err) } }() go func() { defer wg.Done() ctx, _ := context.WithTimeout(context.Background(), time.Second*3) err := lottery(ctx) if err != nil { fmt.Println(err) } }() wg.Wait() time.Sleep(time.Second) }
Dalam kod di atas, kami menggunakan pangkalan data berbilang Redis untuk mensimulasikan berbilang kejadian induk Redis Secara amnya, kami akan memilih 5 kejadian Redis contoh harus Mereka diedarkan pada mesin yang berbeza untuk mengelakkan kegagalan serentak.
Dalam logik penguncian, kami terutamanya melaksanakan SET resource_name my_random_value NX PX 30000 pada setiap kejadian Redis untuk mendapatkan kunci, dan kemudian meletakkan klien yang berjaya mendapatkan kunci ke dalam saluran (mungkin terdapat isu konkurensi apabila menggunakan slice di sini) . Pada masa yang sama, gunakan sync.WaitGroup untuk menunggu operasi pemerolehan kunci tamat.Kemudian tambah tangguh untuk melepaskan logik kunci Logik pelepas kunci adalah sangat mudah, cuma lepaskan kunci yang berjaya diperolehi.
Akhir sekali, nilai sama ada bilangan kunci yang berjaya diperoleh adalah lebih daripada separuh Jika lebih daripada separuh kunci tidak diperoleh, ini bermakna penguncian gagal.
Jika penguncian berjaya, langkah seterusnya ialah melakukan pemprosesan perniagaan.
Ringkasan
- Jana nilai rawak
- dan hantar ke setiap contoh Redis menggunakan
- Kunci
SET resource_name my_random_value NX PX 30000
Tunggu sehingga semua operasi pemerolehan kunci selesai - tangguh menambah logik buka kunci untuk memastikan ia akan dilaksanakan apabila fungsi keluar Di sini, tangguh dahulu dan kemudian menilai kerana mungkin untuk mendapatkan Kunci pada beberapa contoh Redis telah diperolehi, tetapi kerana ia tidak melebihi separuh, ia masih akan dinilai sebagai kegagalan kunci Kembali terus ke
- untuk melaksanakan logik perniagaan
Atas ialah kandungan terperinci Cara melaksanakan kunci teragih dalam Go digabungkan dengan Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas





Mod Redis cluster menyebarkan contoh Redis ke pelbagai pelayan melalui sharding, meningkatkan skalabilitas dan ketersediaan. Langkah -langkah pembinaan adalah seperti berikut: Buat contoh Redis ganjil dengan pelabuhan yang berbeza; Buat 3 contoh sentinel, memantau contoh redis dan failover; Konfigurasi fail konfigurasi sentinel, tambahkan pemantauan maklumat contoh dan tetapan failover; Konfigurasi fail konfigurasi contoh Redis, aktifkan mod kluster dan tentukan laluan fail maklumat kluster; Buat fail nodes.conf, yang mengandungi maklumat setiap contoh Redis; Mulakan kluster, laksanakan perintah Buat untuk membuat kluster dan tentukan bilangan replika; Log masuk ke kluster untuk melaksanakan perintah maklumat kluster untuk mengesahkan status kluster; buat

Cara Mengosongkan Data Redis: Gunakan perintah Flushall untuk membersihkan semua nilai utama. Gunakan perintah flushdb untuk membersihkan nilai utama pangkalan data yang dipilih sekarang. Gunakan Pilih untuk menukar pangkalan data, dan kemudian gunakan FlushDB untuk membersihkan pelbagai pangkalan data. Gunakan perintah DEL untuk memadam kunci tertentu. Gunakan alat REDIS-CLI untuk membersihkan data.

Untuk membaca giliran dari Redis, anda perlu mendapatkan nama giliran, membaca unsur -unsur menggunakan arahan LPOP, dan memproses barisan kosong. Langkah-langkah khusus adalah seperti berikut: Dapatkan nama giliran: Namakannya dengan awalan "giliran:" seperti "giliran: my-queue". Gunakan arahan LPOP: Keluarkan elemen dari kepala barisan dan kembalikan nilainya, seperti LPOP Queue: My-Queue. Memproses Baris kosong: Jika barisan kosong, LPOP mengembalikan nihil, dan anda boleh menyemak sama ada barisan wujud sebelum membaca elemen.

Menggunakan Arahan Redis memerlukan langkah -langkah berikut: Buka klien Redis. Masukkan arahan (nilai kunci kata kerja). Menyediakan parameter yang diperlukan (berbeza dari arahan ke arahan). Tekan Enter untuk melaksanakan arahan. Redis mengembalikan tindak balas yang menunjukkan hasil operasi (biasanya OK atau -r).

Menggunakan REDIS untuk mengunci operasi memerlukan mendapatkan kunci melalui arahan SETNX, dan kemudian menggunakan perintah luput untuk menetapkan masa tamat tempoh. Langkah-langkah khusus adalah: (1) Gunakan arahan SETNX untuk cuba menetapkan pasangan nilai utama; (2) Gunakan perintah luput untuk menetapkan masa tamat tempoh untuk kunci; (3) Gunakan perintah DEL untuk memadam kunci apabila kunci tidak lagi diperlukan.

Cara terbaik untuk memahami kod sumber REDIS adalah dengan langkah demi langkah: Dapatkan akrab dengan asas -asas Redis. Pilih modul atau fungsi tertentu sebagai titik permulaan. Mulakan dengan titik masuk modul atau fungsi dan lihat baris kod mengikut baris. Lihat kod melalui rantaian panggilan fungsi. Berhati -hati dengan struktur data asas yang digunakan oleh REDIS. Kenal pasti algoritma yang digunakan oleh Redis.

Kerugian data REDIS termasuk kegagalan memori, gangguan kuasa, kesilapan manusia, dan kegagalan perkakasan. Penyelesaiannya adalah: 1. 2. Salin ke beberapa pelayan untuk ketersediaan tinggi; 3. Ha dengan redis sentinel atau cluster redis; 4. Buat gambar untuk membuat sandaran data; 5. Melaksanakan amalan terbaik seperti kegigihan, replikasi, gambar, pemantauan, dan langkah -langkah keselamatan.

Gunakan alat baris perintah redis (redis-cli) untuk mengurus dan mengendalikan redis melalui langkah-langkah berikut: Sambungkan ke pelayan, tentukan alamat dan port. Hantar arahan ke pelayan menggunakan nama arahan dan parameter. Gunakan arahan bantuan untuk melihat maklumat bantuan untuk arahan tertentu. Gunakan perintah berhenti untuk keluar dari alat baris arahan.
