golang 利用redis实现分布式锁
互联网集市收集整理的这篇技术教程文章主要介绍了golang 利用redis实现分布式锁,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2582字,纯文字阅读大概需要4分钟。
redis知识准备
redis SETNX命令
SETNX 如果key不存在则创建,并返回true
如果key存在则不操作,并返回false
redis TTL命令
如果对key设置了过期时间,则TTL命令返回key到过期时所剩余的时间
如果key没有设置过期时间,则TTL命令返回-1
代码
package main
import (
"fmt"
"github.com/go-redis/redis"
"time"
)
type redisClient redis.Client
func connRedisCluster(address []string, password string) *redis.ClusterClient {
conf := redis.ClusterOptions{
Addrs: address,
Password: password,
}
return redis.NewClusterClient(&conf)
}
func connRedisSingle(addr, password string) *redis.Client {
conf := redis.Options{
Addr: addr,
Password: password,
}
return redis.NewClient(&conf)
}
func (r *redisClient) lock(value string) (error, bool) {
ret := r.SetNX("hello", value, time.Second*10)
if err := ret.Err(); err != nil {
fmt.Printf("set value %s error: %v\n", value, err)
return err, false
}
return nil, ret.Val()
}
func (r *redisClient) unlock() bool {
ret := r.Del("hello")
if err := ret.Err(); err != nil {
fmt.Println("unlock error: ", err)
return false
}
return true
}
func (r *redisClient) retryLock() bool {
ok := false
for !ok {
err, t := r.getTTL()
if err != nil {
return false
}
if t > 0 {
fmt.Printf("锁被抢占, %f 秒后重试...\n", (t / 10).Seconds())
time.Sleep(t / 10)
}
err, ok = r.lock("Jan")
if err != nil {
return false
}
}
return ok
}
func (r *redisClient) getLock() (error, string) {
ret := r.Get("hello")
if err := ret.Err(); err != nil {
fmt.Println("get lock error: ", err)
return err, ""
}
rt, _ := ret.Bytes()
return nil, string(rt)
}
// 获取锁的过期剩余时间
func (r *redisClient) getTTL() (error, time.Duration) {
ret := r.TTL("hello")
if err := ret.Err(); err != nil {
fmt.Println("get TTL error: ", err)
return err, 0
}
return nil, ret.Val()
}
func (r *redisClient) threadLock(threadId string) {
for {
err, _ := r.getLock()
if err != nil && err.Error() == "redis: nil" {
// 没有获取到值,说明目前没有人持有锁
fmt.Printf("线程 %s 开始加锁\n", threadId)
err, ok := r.lock("Jan")
if err != nil {
return
}
if !ok {
if !r.retryLock() {
fmt.Printf("线程 %s 加锁失败\n", threadId)
return
}
}
fmt.Printf("线程 %s 已加锁\n", threadId)
// 加锁后执行相应操作
time.Sleep(5 * time.Second)
// 释放锁
r.unlock()
fmt.Printf("线程 %s 已释放锁\n", threadId)
return
} else if err != nil {
return
}
err, t := r.getTTL()
if err != nil {
return
}
if t > 0 {
fmt.Printf("线程 %s 锁被占用, %f 秒后重试\n", threadId, (t/10).Seconds())
time.Sleep(t/10)
}
}
}
func main() {
var r redisClient
address := "192.168.1.151:6379"
cl := connRedisSingle(address, "")
defer cl.Close()
r = redisClient(*cl)
// 线程1获取锁
go r.threadLock("1")
//time.Sleep(10 * time.Millisecond)
// 线程2获取锁
go r.threadLock("2")
select {}
}
以上是互联网集市为您收集整理的golang 利用redis实现分布式锁全部内容,希望文章能够帮你解决golang 利用redis实现分布式锁所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
扫描二维码推送至手机访问。