github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/storage/redis/idalloc.go (about)

     1  package redis
     2  
     3  import (
     4  	"context"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/pkg/errors"
     9  	"github.com/redis/go-redis/v9"
    10  )
    11  
    12  // IDAlloc id生成器
    13  // key 为业务key, 由业务前缀+功能前缀+具体场景id组成
    14  // 比如生成用户id, 可以传入user_id, 完整示例: eagle:idalloc:user_id
    15  type IDAlloc struct {
    16  	// redis 实例,最好使用和业务独立的实例,最好可以部署集群,让 id alloc做到高可用
    17  	client *redis.Client
    18  }
    19  
    20  // NewIDAlloc create a id alloc instance
    21  func NewIDAlloc(conn *redis.Client) *IDAlloc {
    22  	return &IDAlloc{
    23  		client: conn,
    24  	}
    25  }
    26  
    27  // GetNewID 生成id
    28  func (ia *IDAlloc) GetNewID(key string, step int64) (int64, error) {
    29  	key = ia.GetKey(key)
    30  	id, err := ia.client.IncrBy(context.Background(), key, step).Result()
    31  	if err != nil {
    32  		return 0, errors.Wrapf(err, "redis incr err, key: %s", key)
    33  	}
    34  
    35  	if id == 0 {
    36  		return 0, errors.Wrapf(err, "[redis.idalloc] %s GetNewID failed", key)
    37  	}
    38  	return id, nil
    39  }
    40  
    41  // GetCurrentID 获取当前id
    42  func (ia *IDAlloc) GetCurrentID(key string) (int64, error) {
    43  	key = ia.GetKey(key)
    44  	ret, err := ia.client.Get(context.Background(), key).Result()
    45  	if err != nil {
    46  		return 0, errors.Wrapf(err, "redis get err, key: %s", key)
    47  	}
    48  	id, err := strconv.Atoi(ret)
    49  	if err != nil {
    50  		return 0, errors.Wrap(err, "str convert err")
    51  	}
    52  	return int64(id), nil
    53  }
    54  
    55  // GetKey 获取key
    56  func (ia *IDAlloc) GetKey(key string) string {
    57  	lockKey := "idalloc"
    58  	return strings.Join([]string{lockKey, key}, ":")
    59  }