自学内容网 自学内容网

Redis的各种操作

使用golang语言实现了各种redis的实现

包括初始化redisDb,在服务重启时需要删除的 redis 缓存,对redis里的值进行自增操作并设置过期时间,简单分布式锁,set,get,ttl,delete等等。

哎嘿,你就看吧,一看一个不吱声。

func InitRedisDB(cfg *dbridgeredis.RedisConfig) {
defer ClearCacheOnServiceRestart()
client := dbridgeredis.InitRedis(cfg)
if cfg.ClusterEnable {
RedisClusterDB = client.(*redis.ClusterClient)
} else {
redisDB = client.(*redis.Client)
injectredis.SetRedis(redisDB)
injectredis.Inject()
}
}



// IncrAndExpire 对redis里的值进行自增操作并设置过期时间
func IncrAndExpire(key string, expiration time.Duration) (count int64) {
c := context.Background()
currentValues := redisDB.Get(c, key)
logger.Info(fmt.Sprintf("redis key=%s, currentValues=%v", key, currentValues))
result := redisDB.Incr(c, key)
if err := result.Err(); err != nil {
logger.Error("incr redis key failed", err)
} else {
count = result.Val()
if err := redisDB.Expire(c, key, expiration).Err(); err != nil {
logger.Error("set redis key expire failed", err)
}
}
return
}

// Set value需要传指针地址
func Set(key string, value interface{}, expiration time.Duration) error {
c := context.Background()
if key == "" || value == nil {
return errors.New("param empty")
}
err := hystrixPing()
if err != nil {
return err
}

data, err := json.Marshal(value)
if err != nil {
return err
}
err = redisDB.Set(c, key, data, expiration).Err()
return err
}

func SetNX(key string, value interface{}, expiration time.Duration) error {
c := context.Background()
if key == "" || value == nil {
return errors.New("param empty")
}
data, err := json.Marshal(value)
if err != nil {
return err
}
return redisDB.SetNX(c, key, data, expiration).Err()
}

// SetNXForLock 简单分布式锁
func SetNXForLock(key string, expiration time.Duration) error {
c := context.Background()
if key == "" {
return errors.New("key empty")
}
suc := redisDB.SetNX(c, key, 1, expiration)
if suc.Val() {
return nil
}
return errors.New(locales.TM("common.key_exist", nil))
}

// RedisDistributedLock 方便的在定时任务中使用
func RedisDistributedLock(key string, expiration time.Duration, execFunction func()) (err error) {
// 设置Redis中的键为分布式锁,如果不存在
if err = SetNXForLock(key, expiration); err != nil {
return fmt.Errorf(fmt.Sprintf("Set redis distributed lock error|key=%s|err=", key), err)
}
defer func() {
if err := recover(); err != nil {
logger.Error(fmt.Sprintf("exec function panic: %v", err), nil)
}
// 删除Redis中的键
err = Delete(key)
if err != nil {
logger.Error(fmt.Sprintf("Delete redis distributed lock error|key=%s|err=", key), err)
}
}()
execFunction()
return
}

// Get ret需要传指针地址
func Get(key string, ret interface{}) error {
c := context.Background()
if key == "" {
return errors.New("param empty")
}
err := hystrixPing()
if err != nil {
return err
}

handle := redisDB.Get(c, key)
if err := handle.Err(); err != nil {
return err
}
res := handle.Val()
return json.Unmarshal([]byte(res), &ret)
}

func TTL(key string) (int64, error) {
c := context.Background()
if key == "" {
return -1, errors.New("param empty")
}
err := hystrixPing()
if err != nil {
return -1, err
}

handle := redisDB.TTL(c, key)
if err := handle.Err(); err != nil {
return -1, err
}

return int64(handle.Val().Seconds()), nil
}

// Delete 删除缓存
func Delete(key string) error {
c := context.Background()
if key == "" {
return fmt.Errorf("empty key when delete")
}
err := hystrixPing()
if err != nil {
return err
}
return redisDB.Del(c, key).Err()
}

func Expire(key string, expiration time.Duration) error {
return redisDB.Expire(context.Background(), key, expiration).Err()
}

func Scan(cursor uint64, match string, count int64) *redis.ScanCmd {
return redisDB.Scan(context.Background(), cursor, match, count)
}

func FlushAll() {
redisDB.FlushDB(context.Background())
}

// Keys 获取指定 key 的所有值,并以切片的形式返回
func Keys(key string) []string {
c := context.Background()
var ret []string
err := hystrixPing()
if err != nil {
return ret
}
if key == "" {
return ret
}
handle := redisDB.Keys(c, key)
if err := handle.Err(); err != nil {
logger.Error("Keys err", err)
return ret
}
res := handle.Val()
return res
}

// ZAdd 给有序集合中添加元素及分数
func ZAdd(key string, member interface{}, score float64) (int64, error) {
c := context.Background()
item := &redis.Z{
Score:  score,
Member: member,
}
addedCount, err := redisDB.ZAdd(c, key, item).Result()
if err != nil {
logger.Error("redis add member to zadd error", err)
return 0, err
}
return addedCount, nil
}

// ZRemRangeByRank 移除有序集合中给定的排名区间内的所有成员
// Redis ZREMRANGEBYRANK 移除有序集key中,指定排名(rank)区间 start 和 stop 内的所有成员。下标参数start和stop都是从0开始计数,
// 0是分数最小的那个元素。索引也可是负数,表示位移从最高分处开始数。例如,-1是分数最高的元素,-2是分数第二高的,依次类推。
func ZRemRangeByRank(key string, start, stop int64) (int64, error) {
c := context.Background()
removeCount, err := redisDB.ZRemRangeByRank(c, key, start, stop).Result()
if err != nil {
logger.Error("redis remove zadd member error", err)
return 0, err
}
return removeCount, nil
}

// ZRange 获取有序集合中的元素,并对其按照分数进行从大到小排序
func ZRange(key string, start, stop int64) (members []string, err error) {
c := context.Background()
members, err = redisDB.ZRange(c, key, start, stop).Result()
if err != nil {
logger.Error("redis get zadd error", err)
return nil, err
}
if len(members) > 1 {
members = utils.ReverseSlice(members)
}
return
}

func SAdd(key string, value interface{}) (int64, error) {
c := context.Background()
addedCount, err := redisDB.SAdd(c, key, value).Result()
if err != nil {
logger.Error("redis setting error", err)
return 0, err
}
return addedCount, nil
}

func SIsMember(key string, value int) (bool, error) {
c := context.Background()
existValue, err := redisDB.SIsMember(c, key, value).Result()
if err != nil {
logger.Error("查询失败", err)
return false, err
}
return existValue, nil
}

func SIsMemberString(key string, value string) (bool, error) {
c := context.Background()
existValue, err := redisDB.SIsMember(c, key, value).Result()
if err != nil {
logger.Error("查询失败", err)
return false, err
}
return existValue, nil
}

// Incr 对redis里的值进行自增操作
func Incr(key string) (int, error) {
err := hystrixPing()
if err != nil {
return 0, err
}
c := context.Background()
cmd := redisDB.Incr(c, key)
return int(cmd.Val()), cmd.Err()
}

// Decr 对redis里的值进行自减操作
func Decr(key string) (int, error) {
c := context.Background()
cmd := redisDB.Decr(c, key)
return int(cmd.Val()), cmd.Err()
}

// DeleteBatch 批量删除缓存
func DeleteBatch(key []string) error {
err := hystrixPing()
if err != nil {
return err
}
c := context.Background()
return redisDB.Del(c, key...).Err()
}

func UnlinkPrefixKeys(prefix string) error {
err := hystrixPing()
if err != nil {
return err
}
c := context.Background()
keys, _ := redisDB.Keys(c, prefix).Result()
if len(keys) > 0 {
// unlink 异步删
err = UnlinkKeys(keys)
if err != nil {
logger.Error("redis unlink keys error", err)
}
}
return nil
}

func UnlinkKeys(keys []string) error {
err := hystrixPing()
if err != nil {
return err
}
c := context.Background()
return redisDB.Unlink(c, keys...).Err()
}

func HMget(key string, fields []string) (val []interface{}, err error) {
c := context.Background()
return redisDB.HMGet(c, key, fields...).Result()
}

func HSet(key string, field, value interface{}) (res int64, err error) {
c := context.Background()
return redisDB.HSet(c, key, field, value).Result()
}

func HGet(key string, field string) (res string, err error) {
c := context.Background()
return redisDB.HGet(c, key, field).Result()
}

func HDel(key, field string) (res int64, err error) {
c := context.Background()
return redisDB.HDel(c, key, field).Result()
}

func HGetAll(key string) (map[string]string, error) {
c := context.Background()
return redisDB.HGetAll(c, key).Result()
}

func HMSet(key string, fields map[string]string) (bool, error) {
c := context.Background()
return redisDB.HMSet(c, key, fields).Result()
}

func Lock(lockKey string, expiration time.Duration) (bool, error) {
var resp *redis.BoolCmd
for {
goId := utils.GetCurrentGoroutineId()
resp = redisDB.SetNX(context.Background(), lockKey, goId, expiration) //返回执行结果
lockSuccess, err := resp.Result()
if err == nil && lockSuccess {
//抢锁成功,开启看门狗 并跳出,否则失败继续自旋
tls.GoSafe(tls.GetLangLocalStorage(), func() { watchDog(goId, lockKey, expiration) })
return lockSuccess, err
}
//time.Sleep(time.Millisecond * 30) //可以适当休眠
return lockSuccess, err
}
}

// 自动续期看门狗
func watchDog(goId int, lockKey string, expiration time.Duration) {
// 创建一个定时器NewTicker, 每隔2秒触发一次,类似于闹钟
expTicker := time.NewTicker(time.Second * 2)
//确认锁与锁续期打包原子化
script := redis.NewScript(`
    if redis.call('get', KEYS[1]) == ARGV[1]
    then
      return redis.call('expire', KEYS[1], ARGV[2])
    else
      return 0
    end
  `)

for {
select {
case <-expTicker.C: //因为上边是用NewTicker创建的定时器,所以每隔2s都会触发
resp := script.Run(context.Background(), redisDB, []string{lockKey}, goId, expiration)
if result, err := resp.Result(); err != nil || result == int64(0) {
//续期失败
_, _ = fmt.Printf("expire lock failed:%s", err)
}
case <-unlockCh: //任务完成后用户解锁通知看门狗退出
return
}
}
}

func Unlock(lockKey string) error {
script := redis.NewScript(`
    if redis.call('get', KEYS[1]) == ARGV[1]
    then
      return redis.call('del', KEYS[1])
     else
        return 0
     end
  `)
resp := script.Run(context.Background(), redisDB, []string{lockKey}, utils.GetCurrentGoroutineId())
if result, err := resp.Result(); err != nil || result == 0 {
return fmt.Errorf(fmt.Sprintf("unlock %s failed: %s", lockKey, err))
}
//删锁成功后,通知看门狗退出
unlockCh <- struct{}{}
return nil
}

// LRange LRange
func LRange(key string, start, stop int64) (members []string, err error) {
c := context.Background()
members, err = redisDB.LRange(c, key, start, stop).Result()
if err != nil {
logger.Error("redis get LRange error", err)
return nil, err
}
return
}

// RPop RPop
func RPop(key string) (err error) {
c := context.Background()
err = redisDB.RPop(c, key).Err()
if err != nil {
logger.Error("redis RPop error", err)
return err
}
return
}

// LPush LPush
func LPush(key string, values ...interface{}) (err error) {
c := context.Background()
err = redisDB.LPush(c, key, values).Err()
if err != nil {
logger.Error("redis LPush error", err)
return err
}
return
}

func LPushValue(key string, value interface{}) error {
c := context.Background()
if key == "" || value == nil {
return errors.New("param empty")
}
data, err := json.Marshal(value)
if err != nil {
return err
}
return redisDB.LPush(c, key, data).Err()
}

func RPopValue(key string, ret interface{}) error {
c := context.Background()
if key == "" {
return errors.New("param empty")
}
handle := redisDB.RPop(c, key)
if err := handle.Err(); err != nil {
return err
}
res := handle.Val()
return json.Unmarshal([]byte(res), &ret)
}

func AddUniqueLock() (err error) {
pc, _, _, ok := runtime.Caller(1)
if !ok {
logger.Info("AddUniqueLock err")
return
}
funcName := runtime.FuncForPC(pc).Name()

err = SetNXForLock(fmt.Sprintf("crond_lock:%s", funcName), 3*time.Second)
return
}

func AddUniqueLockSecTime(sec int64) (err error) {
pc, _, _, ok := runtime.Caller(1)
if !ok {
logger.Info("AddUniqueLock err")
return
}
funcName := runtime.FuncForPC(pc).Name()

err = SetNXForLock(fmt.Sprintf("crond_lock:%s", funcName), time.Duration(sec)*time.Second)
return
}

func Exists(key string) (int64, error) {
c := context.Background()
return redisDB.Exists(c, key).Result()
}
func SAddNX(key string, value interface{}, expiration time.Duration) (int64, error) {
c := context.Background()
addedCount, err := redisDB.SAdd(c, key, value).Result()
if err != nil {
logger.Error("redis setting error", err)
return 0, err
}
redisDB.Expire(c, key, expiration)
return addedCount, nil
}

func BLPop(key string, timeout time.Duration) ([]string, error) {
err := hystrixPing()
if err != nil {
return nil, err
}
return redisDB.BLPop(context.Background(), timeout, key).Result()
}

func Watch(key string, function func(tx *redis.Tx) error) error {
err := hystrixPing()
if err != nil {
return err
}
return redisDB.Watch(context.Background(), function, key)
}

func RPush(key string, values ...interface{}) (err error) {
err = hystrixPing()
if err != nil {
return err
}
return redisDB.RPush(context.Background(), key, values).Err()
}

 


原文地址:https://blog.csdn.net/2301_77174919/article/details/145092595

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!