In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces Go combined with Redis how to achieve distributed locks, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let Xiaobian take you to understand.
Single Redis instance scenario
If you are familiar with Redis commands, you may immediately want to use Redis's set if not exists operation to implement it, and now the standard way of implementation is the string of commands SET resource_name my_random_value NX PX 30000, where:
Resource_name indicates the resource to be locked
NX indicates that if it does not exist, set the
PX 30000 indicates that the expiration time is 30000 milliseconds, or 30 seconds.
The value of my_random_value must be unique to all clients, and cannot be the same for all recipients (competitors) of the same key.
The value of value must be a random number mainly in order to release the lock more securely. When releasing the lock, use the script to tell Redis that only key exists and the stored value is the same as the value I specified to tell me that the deletion is successful. This can be achieved through the following Lua scripts:
If redis.call ("get", KEYS [1]) = ARGV [1] then return redis.call ("del", KEYS [1]) else return 0end
For example, client An acquires a resource lock, but is then blocked by another operation. When client A finishes running other operations and releases the lock, the original lock has already timed out and is automatically released by Redis, and in the meantime, the resource lock is acquired again by client B.
The Lua script is used because judgment and deletion are two operations, so it is possible that An expires and automatically releases the lock as soon as it is judged, then B acquires the lock, and then A calls Del, resulting in the release of B's lock.
Add unlock sample package mainimport ("context"errors"fmt"github.com/brianvoe/gofakeit/v6"github.com/go-redis/redis/v8"sync"time") var client * redis.Clientconst unlockScript = `if redis.call ("get", KEYS [1]) = ARGV [1] then return redis.call ("del") }) 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 ()}
Let's first look at the lottery () function, which simulates a lottery operation. When entering the function, we first use SET resource_name my_random_value NX PX 30000 to lock, and here we use UUID as a random value. If the operation fails, we return directly and let the user try again. If the unlock logic is successfully executed in defer, the unlock logic is to execute the lua script mentioned earlier, and then carry out business processing.
We executed two goroutine concurrent calls to the lottery () function in the main () function, and one of the operations failed directly because the lock could not be obtained.
Summary
Generate random values
Use SET resource_name my_random_value NX PX 30000 to add locks
If locking fails, return directly
Defer adds unlocking logic to ensure that it will be executed when the function exits
Execute business logic
Multi-Redis instance scenario
In the case of a single instance, if the instance fails, all requests will fail because they cannot get the lock, so we need multiple Redis instances distributed on different machines and get the locks of most of the nodes in order to lock successfully. This is the RedLock algorithm. It is also based on the above single-instance algorithm, but we need to acquire locks on multiple Redis instances at the same time.
Add unlock sample package mainimport ("context"errors"fmt"github.com/brianvoe/gofakeit/v6"github.com/go-redis/redis/v8"sync"time") var clients [] * redis.Clientconst unlockScript = `if redis.call ("get", KEYS [1]) = ARGV [1] then return redis.call ("del") KEYS [1]) else return 0end`func lottery (ctx context.Context) error {/ / lock myRandomValue: = gofakeit.UUID () resourceName: = "resource_name" var wg sync.WaitGroup wg.Add (len (clients)) / / this is mainly to ensure that it is not locked for too long This will result in less business processing time lockCtx, _: = context.WithTimeout (ctx, time.Millisecond*5) / / client 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
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.