中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

創(chuàng)業(yè)如何進行網(wǎng)站建設(shè)路由優(yōu)化大師

創(chuàng)業(yè)如何進行網(wǎng)站建設(shè),路由優(yōu)化大師,一個可以做網(wǎng)站,荷蘭服務(wù)器租用Redis分布式鎖 Redis 分布式鎖是一種使用 Redis 數(shù)據(jù)庫實現(xiàn)分布式鎖的方式,可以保證在分布式環(huán)境中同一時間只有一個實例可以訪問共享資源。 實現(xiàn)機制 以下是實現(xiàn)其加鎖步驟: 獲取鎖 在 Redis 中,一個相同的key代表一把鎖。是否擁有這把鎖&…

Redis分布式鎖

Redis 分布式鎖是一種使用 Redis 數(shù)據(jù)庫實現(xiàn)分布式鎖的方式,可以保證在分布式環(huán)境中同一時間只有一個實例可以訪問共享資源。

實現(xiàn)機制

以下是實現(xiàn)其加鎖步驟:

在這里插入圖片描述

獲取鎖

在 Redis 中,一個相同的key代表一把鎖。是否擁有這把鎖,需要判斷keyvalue是否是自己設(shè)置的,同時還要判斷鎖是否已經(jīng)過期。

  • 首先通過get命令去獲取鎖,如果獲取不到說明還沒有加鎖
  • 如果還沒有加鎖我們就可以去通過set命令去加鎖,并且需要設(shè)置一個expire過期時間防止成為一個長生不老鎖,那如果業(yè)務(wù)還沒有執(zhí)行完鎖就釋放了怎么辦呢?這個后面會提到續(xù)鎖
  • 如果獲取到了key說明已經(jīng)被其他實例搶到了鎖,加鎖失敗
  • 加鎖失敗還需要根據(jù)一些操作例如超時時間內(nèi)去重試加鎖,直到加鎖成功或者超時

這些操作都需要原子性操作,需要用lua腳本進行封裝

lock.lua
val = redis.call('get', KEYS[1])
if val == false thenreturn redis.call('set', KEYS[1], ARGV[1], 'EX', ARGV[2])
elseif val == ARGV[1] thenredis.call('expire', KEYS[1], ARGV[2])return 'OK'
elsereturn ''
end

釋放鎖

釋放鎖的時候就是把key刪除,不過刪除的時候需要判斷是不是自己加的鎖

unlock.lua
if redis.call('get', KEYS[1]) == ARGV[1] thenreturn redis.call('del', KEYS[1])
elsereturn 0
end

Go 實現(xiàn)分布式鎖

結(jié)構(gòu)體字段配置

// redis客戶端連接
type Client struct {client  redis.CmdablevarFunc func() stringg       singleflight.Group
}// 鎖的結(jié)構(gòu)體
type Lock struct {client     redis.Cmdablekey        stringvalue      stringexpiration time.Durationunlock     chan struct{}unlockOne  sync.Once
}// NewClient creates a *Client
func NewClient(client redis.Cmdable) *Client {return &Client{client: client,varFunc: func() string {return uuid.New().String()},}
}// 重試策略
type RetryStrategy interface {// Next determines the time interval for Lock// and whether Lock to retryNext() (time.Duration, bool)
}// 周期性重試
type FixedIntervalRetry struct {Interval time.DurationMax      intcnt      int
}

lua 腳本,使用go的embed映射到luaLock string

var (ErrFailedToPreemptLock = errors.New("redis-lock: failed to lock")ErrLockNotHold         = errors.New("redis-lock: lock not hold")ErrLockTimeout         = errors.New("redis-lock: lock timeout")//go:embed lua/unlock.lualuaUnlock string//go:embed lua/refresh.lualuaRefresh string//go:embed lua/lock.lualuaLock string
)

加鎖Lock

加鎖時有兩種方案,一種是比較簡單的( TryLock )嘗試加鎖,只需要傳個過期時間,另一種是比較完善的( Lock )加鎖,會有超時策略等

func newLock(client redis.Cmdable, key string, value string, expiration time.Duration) *Lock {return &Lock{client:     client,key:        key,value:      value,expiration: expiration,unlock:     make(chan struct{}, 1),}
}// TryLock tries to acquire a lock
func (c *Client) TryLock(ctx context.Context,key string,expiration time.Duration) (*Lock, error) {val := c.varFunc()ok, err := c.client.SetNX(ctx, key, val, expiration).Result()if err != nil {return nil, err}if !ok {return nil, ErrFailedToPreemptLock}return newLock(c.client, key, val, expiration), nil
}// Lock tries to acquire a lock with timeout and retry strategy
func (c *Client) Lock(ctx context.Context,key string,expiration time.Duration,timeout time.Duration, retry RetryStrategy) (*Lock, error) {var timer *time.Timerval := c.varFunc()for {lCtx, cancel := context.WithTimeout(ctx, timeout)res, err := c.client.Eval(lCtx, luaLock, []string{key}, val, expiration.Seconds()).Result()cancel()if err != nil && !errors.Is(err, context.DeadlineExceeded) {return nil, err}if res == "OK" {return newLock(c.client, key, val, expiration), nil}interval, ok := retry.Next()if !ok {return nil, ErrLockTimeout}if timer == nil {timer = time.NewTimer(interval)} else {timer.Reset(interval)}select {case <-timer.C:case <-ctx.Done():return nil, ctx.Err()}}
}

解鎖unLock

// Unlock releases the lock
func (l *Lock) Unlock(ctx context.Context) error {res, err := l.client.Eval(ctx, luaUnlock, []string{l.key}, l.value).Int64()defer func() {l.unlockOne.Do(func() {l.unlock <- struct{}{}close(l.unlock)})}()if errors.Is(err, redis.Nil) {return ErrLockNotHold}if err != nil {return err}if res != 1 {return ErrLockNotHold}return nil
}

小結(jié)

  • 使用分布式鎖本身會有各種各樣的問題,需要自己去處理異常情況例如超時等
  • 對鎖的操作一定要判斷是不是自己加的那把鎖,否則會誤刪會導(dǎo)致業(yè)務(wù)錯誤
  • 對鎖的續(xù)約部分我們下一篇再講

本文go的代碼是完整的,可以直接copy使用,有興趣的小伙伴可以去使用一下

http://www.risenshineclean.com/news/61572.html

相關(guān)文章:

  • 徐州建設(shè)工程交易網(wǎng)平臺官網(wǎng)網(wǎng)站seo搜索引擎優(yōu)化案例
  • 太原小程序開發(fā)定制學(xué)校seo推廣培訓(xùn)班
  • 中央人民政府網(wǎng)站網(wǎng)址百度圖片
  • 西安專業(yè)網(wǎng)站建設(shè)公司開創(chuàng)集團與百度
  • wordpress 遠程數(shù)據(jù)庫太原百度搜索排名優(yōu)化
  • 網(wǎng)站備案添加域名識圖找圖
  • 網(wǎng)站建設(shè)的優(yōu)點如何搭建自己的網(wǎng)站
  • 手把手教你做網(wǎng)站7seo推廣方案
  • 臨海市城鄉(xiāng)建設(shè)規(guī)劃局網(wǎng)站廣州搜發(fā)網(wǎng)絡(luò)科技有限公司
  • 萬站群cms百度入口提交
  • 用國外服務(wù)器做網(wǎng)站網(wǎng)絡(luò)宣傳怎么做
  • 怎么用ps做網(wǎng)站圖片能讓手機流暢到爆的軟件
  • 網(wǎng)上服裝定制網(wǎng)站seo優(yōu)化軟件有哪些
  • 提供手機自適應(yīng)網(wǎng)站建設(shè)優(yōu)化疫情防控 這些措施你應(yīng)該知道
  • 這是我自己做的網(wǎng)站嗎百度怎么發(fā)廣告
  • 旅游酒店網(wǎng)站建設(shè)三葉草gw9356
  • 網(wǎng)站維護 公司簡介網(wǎng)站免費網(wǎng)站免費
  • 佛山做網(wǎng)站建設(shè)政府免費培訓(xùn)面點班
  • wordpress拉寬seo文章優(yōu)化技巧
  • 最火的網(wǎng)絡(luò)銷售平臺seo顧問合同
  • 高端網(wǎng)站定制方案seo網(wǎng)絡(luò)推廣培訓(xùn)
  • 高端網(wǎng)站建設(shè)kgu網(wǎng)站建設(shè)網(wǎng)站
  • b2b網(wǎng)站建設(shè)案例鄭州網(wǎng)絡(luò)營銷顧問
  • 昆明網(wǎng)站seo報價推廣普通話手抄報內(nèi)容大全資料
  • 網(wǎng)站常見攻擊營銷型網(wǎng)站建設(shè)步驟
  • 江蘇網(wǎng)站設(shè)計建站模板
  • 做網(wǎng)站的銷售簡述在線推廣網(wǎng)站的方法
  • 個體工商戶 做經(jīng)營性網(wǎng)站網(wǎng)站鏈接查詢
  • wifi擴展器做網(wǎng)站百度資源平臺鏈接提交
  • 鄭州好的網(wǎng)站設(shè)計公司搜索引擎關(guān)鍵詞排名優(yōu)化