In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces how to use Go+Redis to achieve distributed locks, the article is very detailed, has a certain reference value, interested friends must read it!
Why do you need distributed locks?
The user places an order
Lock the uid to prevent duplicate orders.
Inventory deduction
Lock up the inventory to prevent overselling.
Balance deduction
Lock the account to prevent concurrent operations.
When sharing the same resource in a distributed system, distributed locks are often needed to ensure the consistency of changed resources.
Distributed locks need to have characteristics
Exclusiveness
The basic characteristics of the lock and can only be held by the first holder.
Anti-deadlock
Once a deadlock occurs in critical resources in high concurrency scenarios, it is very difficult to troubleshoot, which can usually be avoided by setting the timeout to automatically release the lock when the timeout expires.
Reentrant
The lock holder supports reentrant to prevent the lock from being released during the timeout when the lock holder reenters again.
High performance and high availability
The lock is the key pre-node for the code to run, and once it is not available, the business will report the failure directly. In high concurrency scenarios, high performance and high availability is a basic requirement.
What knowledge points should be mastered first to realize Redis lock
Set command
SET key value [EX seconds] [PX milliseconds] [NX | XX]
EX second: sets the expiration time of the key to second seconds. The SET key value EX second effect is equivalent to SETEX key second value.
PX millisecond: sets the expiration time of the key to millisecond milliseconds. The SET key value PX millisecond effect is equivalent to PSETEX key millisecond value.
NX: set the key only when the key does not exist. The SET key value NX effect is equivalent to SETNX key value.
XX: set the key only if it already exists.
Redis.lua script
Using redis lua script, a series of command operations can be encapsulated into pipline to realize the atomicity of the whole operation.
Analysis of RedisLock Source Code of go-zero distributed Lock
Core/stores/redis/redislock.go
Locking process
-- KEYS [1]: lock key-- ARGV [1]: lock value, random string-- ARGV [2]: expiration time-- determine whether the value held by the lock key is equal to the passed value--. If equality means that the lock is acquired again and the acquisition time is updated. Prevent expiration on reentry-here it is "reentrant lock" if redis.call ("GET", KEYS [1]) = = ARGV [1] then-set redis.call ("SET", KEYS [1], ARGV [1], "PX") ARGV [2]) return "OK" else-if the lock key.value is not equal to the passed value, it means that this is the first time to acquire the lock-- SET key value NX PX timeout: set the value of key when the key does not exist-- "OK" will be returned automatically if the setting is successful. Failed setting returned "NULL Bulk Reply"-Why do you add "NX" here, because you need to prevent other people's locks from overwriting return redis.call ("SET", KEYS [1], ARGV [1], "NX", "PX", ARGV [2]) end
Unlock process
-- release locks-- cannot release other people's locks if redis.call ("GET", KEYS [1]) = = ARGV [1] then-- return "1" return redis.call ("DEL", KEYS [1]) else return 0end after successful execution
Source code parsing
Package redisimport ("math/rand"strconv"sync/atomic"time" red "github.com/go-redis/redis"github.com/tal-tech/go-zero/core/logx") const (letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" lockCommand = `if redis.call ("GET", KEYS [1]) = ARGV [1] then redis.call ("SET", KEYS [1], ARGV [1], "PX" ARGV [2]) return "OK" else return redis.call ("SET", KEYS [1], ARGV [1], "NX", "PX", ARGV [2]) end`delCommand = `if redis.call ("GET", KEYS [1]) = ARGV [1] then return redis.call ("DEL", KEYS [1]) else return 0end` randomLen = 16 / default timeout Prevent deadlock tolerance = 500 / / milliseconds millisPerSecond = 1000) / / A RedisLock is a redis lock.type RedisLock struct {/ / redis client store * Redis / / timeout seconds uint32 / / lock key key string / / lock value Prevent locks from being acquired by id string} func init () {rand.Seed (time.Now (). UnixNano ())} / / NewRedisLock returns a RedisLock.func NewRedisLock (store * Redis, key string) * RedisLock {return & RedisLock {store: store, key: key, / / when acquiring locks Lock values are generated through random strings / / in fact go-zero provides a more efficient way to generate random strings / / see core/stringx/random.go:Randn id: randomStr (randomLen),}} / / Acquire acquires the lock.// locking func (rl * RedisLock) Acquire () (bool Error) {/ / get expiration time seconds: = atomic.LoadUint32 (& rl.seconds) / / default lock expiration time is 500ms Prevent deadlock resp, err: = rl.store.Eval (lockCommand, [] string {rl.key}, [] string {rl.id, strconv.Itoa (int (seconds) * millisPerSecond + tolerance),}) if err = = red.Nil {return false, nil} else if err! = nil {logx.Errorf ("Error on acquiring lock for% s,% s", rl.key, err.Error () return false Err} else if resp = = nil {return false, nil} reply, ok: = resp. (string) if ok & & reply = = "OK" {return true, nil} logx.Errorf ("Unknown reply when acquiring lock for% s:% v", rl.key, resp) return false, nil} / / Release releases the lock.// release lock func (rl * RedisLock) Release () (bool, error) {resp Err: = rl.store.Eval (delCommand, [] string {rl.key}, [] string {rl.id}) if err! = nil {return false, err} reply, ok: = resp. (int64) if! ok {return false, nil} return reply = = 1 Nil} / / SetExpire sets the expire.// needs to be called before Acquire (). The default is that 500ms automatically releases func (rl * RedisLock) SetExpire (seconds int) {atomic.StoreUint32 (& rl.seconds, uint32 (seconds))} func randomStr (n int) string {b: = make ([] byte). N) for I: = range b {b [I] = letters [rand.Intn (len (letters))]} return string (b)} above are all the contents of the article "how to implement distributed locks with Go+Redis" Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
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.