SETNX 命令
SETNX key value :

  • 如果 key 不存在,则设置成功,返回 1。
  • 如果 key 已存在,则不做任何操作,返回 0。

👉 这就是实现“只有第一个人能抢到锁”的关键。


过期时间 (TTL)
给锁加上过期时间(EX 秒 或 PX 毫秒),避免死锁。比如持有锁的客户端挂掉了,Redis 会自动释放。


package redis

import (
	"context"
	"github.com/redis/go-redis/v9"
	"time"
)

func tryLock(rc *redis.Client, key string, duration time.Duration) bool {
	// 尝试获取锁
	cmd := rc.SetNX(context.Background(), key, "value can any", duration)
	if cmd.Err() != nil {
		return false
	} else {
		return cmd.Val()
	}
}

func releaseLock(rc *redis.Client, key string) {
	// 释放分布式锁
	rc.Del(context.Background(), key)
}

test:

package redis

import (
	"fmt"
	"sync"
	"testing"
	"time"
)

func TestTryLock(t *testing.T) {
	clinet := newTestClient()
	const P = 100 // 假设100个协程抢锁
	key := "iphone秒杀活动-第2台"
	defer releaseLock(clinet, key)
	wg := sync.WaitGroup{}
	wg.Add(P)
	for i := 0; i < P; i++ {
		go func(i int) {
			defer wg.Done()
			if tryLock(clinet, key, time.Hour) {
				fmt.Printf("协程%d抢到了手机!\n", i)
			} else {
				fmt.Printf("协程%d没有抢到手机~\n", i)
			}
		}(i)
	}
	wg.Wait()
}

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐