gitee.com/h79/goutils@v1.22.10/dao/redis/pool/kv.go (about)

     1  package pool
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/go-redis/redis/v8"
     9  )
    10  
    11  // GetSet 的包装
    12  func (c *Client) GetSet(ctx context.Context, key string, value interface{}) (string, error) {
    13  	client, cErr := getClusterClient(c)
    14  
    15  	if cErr != nil {
    16  		return "", cErr
    17  	}
    18  
    19  	res := ""
    20  	var err error
    21  
    22  	res, err = client.GetSet(ctx, key, value).Result()
    23  
    24  	return res, err
    25  }
    26  
    27  // Set 对于Set
    28  func (c *Client) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) (string, error) {
    29  	client, cErr := getClusterClient(c)
    30  
    31  	if cErr != nil {
    32  		return "", cErr
    33  	}
    34  	return client.Set(ctx, key, value, expiration).Result()
    35  
    36  }
    37  
    38  //  对于SetNX 的包装
    39  func (c *Client) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error) {
    40  	client, cErr := getClusterClient(c)
    41  
    42  	if cErr != nil {
    43  		return false, cErr
    44  	}
    45  
    46  	return client.SetNX(ctx, key, value, expiration).Result()
    47  
    48  }
    49  
    50  func (c *Client) SetWithKeys(ctx context.Context, keys []string, value interface{}, expiration time.Duration) (string, error) {
    51  	client, cErr := getClusterClient(c)
    52  
    53  	if cErr != nil {
    54  		return "", cErr
    55  	}
    56  
    57  	res := ""
    58  	var err error
    59  
    60  	cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error {
    61  		for _, key := range keys {
    62  			pipe.Set(ctx, key, value, expiration)
    63  		}
    64  		return nil
    65  	})
    66  
    67  	for _, cmd := range cmds {
    68  		if value, ok := cmd.(*redis.StatusCmd); ok {
    69  			res, err = value.Result()
    70  			if err != nil {
    71  				return res, err
    72  			}
    73  		}
    74  	}
    75  
    76  	return res, err
    77  }
    78  
    79  // Sets 对于Set和SetNX 的包装
    80  func (c *Client) SetNXWithKeys(ctx context.Context, keys []string, value interface{}, expiration time.Duration) (bool, error) {
    81  	client, cErr := getClusterClient(c)
    82  
    83  	if cErr != nil {
    84  		return false, cErr
    85  	}
    86  
    87  	res := true
    88  	var err error
    89  
    90  	cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error {
    91  		for _, key := range keys {
    92  			pipe.SetNX(ctx, key, value, expiration)
    93  		}
    94  		return nil
    95  	})
    96  
    97  	for _, cmd := range cmds {
    98  		if value, ok := cmd.(*redis.BoolCmd); ok {
    99  			res, err = value.Result()
   100  			if err != nil {
   101  				return res, err
   102  			}
   103  		}
   104  		//switch value := cmd.(type) {
   105  		//case *redis.StatusCmd:
   106  		//	_, err = value.Result()
   107  		//case *redis.BoolCmd:
   108  		//	res, err = value.Result()
   109  		//
   110  		//}
   111  		//
   112  		//if err != nil {
   113  		//	return res, err
   114  		//}
   115  	}
   116  
   117  	return res, err
   118  }
   119  
   120  //Get 获取字段
   121  func (c *Client) Get(ctx context.Context, key string) (string, error) {
   122  	client, cErr := getClusterClient(c)
   123  
   124  	if cErr != nil {
   125  		return "", cErr
   126  	}
   127  
   128  	return client.Get(ctx, key).Result()
   129  }
   130  
   131  //MSetReq MSets的参数
   132  type MSetReq struct {
   133  	Key   string
   134  	Value interface{}
   135  }
   136  
   137  //MSet 批量设置
   138  func (c *Client) MSet(ctx context.Context, req ...*MSetReq) (string, error) {
   139  	client, cErr := getClusterClient(c)
   140  
   141  	if cErr != nil {
   142  		return "", cErr
   143  	}
   144  
   145  	slotsMap := make(map[int][]*MSetReq)
   146  	for _, r := range req {
   147  		slot := Slot(r.Key)
   148  		if _, ok := slotsMap[slot]; !ok {
   149  			slotsMap[slot] = make([]*MSetReq, 0)
   150  		}
   151  		slotsMap[slot] = append(slotsMap[slot], r)
   152  	}
   153  
   154  	cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error {
   155  		for _, r := range slotsMap {
   156  			pairs := make([]interface{}, 0)
   157  			for _, p := range r {
   158  				pairs = append(pairs, p.Key, p.Value)
   159  			}
   160  			err := pipe.MSet(ctx, pairs...).Err()
   161  			if err != nil {
   162  				return err
   163  			}
   164  		}
   165  		return nil
   166  	})
   167  
   168  	var res string
   169  	for _, cmd := range cmds {
   170  		res, err = cmd.(*redis.StatusCmd).Result()
   171  		if err != nil {
   172  			return res, err
   173  		}
   174  	}
   175  
   176  	return res, err
   177  }
   178  
   179  //KeyValue key-value数对
   180  type KeyValue struct {
   181  	Key   string
   182  	Value string
   183  	Err   error
   184  }
   185  
   186  //MGet 批量设置
   187  func (c *Client) MGet(ctx context.Context, keys ...string) ([]*KeyValue, error) {
   188  	client, cErr := getClusterClient(c)
   189  
   190  	if cErr != nil {
   191  		return nil, cErr
   192  	}
   193  
   194  	slotsMap := make(map[int][]string)
   195  	for _, k := range keys {
   196  		slot := Slot(k)
   197  		if _, ok := slotsMap[slot]; !ok {
   198  			slotsMap[slot] = make([]string, 0)
   199  		}
   200  		slotsMap[slot] = append(slotsMap[slot], k)
   201  	}
   202  
   203  	slotsSlice := make([][]string, 0)
   204  
   205  	for _, s := range slotsMap {
   206  		slotsSlice = append(slotsSlice, s)
   207  	}
   208  
   209  	res := make([]*KeyValue, 0)
   210  	cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error {
   211  		for _, k := range slotsSlice {
   212  			pipe.MGet(ctx, k...)
   213  		}
   214  		return nil
   215  	})
   216  
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  
   221  	if len(cmds) != len(slotsSlice) {
   222  		return nil, fmt.Errorf("MGet fail, keys = %v", keys)
   223  	}
   224  
   225  	i := 0
   226  	for _, slot := range slotsSlice {
   227  		// fmt.Println(i)
   228  		r, err := cmds[i].(*redis.SliceCmd).Result()
   229  		if len(slot) != len(r) {
   230  			return nil, fmt.Errorf("MGet fail, keys = %v", keys)
   231  		}
   232  
   233  		for j, k := range slot {
   234  			v := ""
   235  			if r[j] != nil {
   236  				v = r[j].(string)
   237  
   238  				res = append(res, &KeyValue{
   239  					Key:   k,
   240  					Value: v,
   241  					Err:   err,
   242  				})
   243  			}
   244  		}
   245  		i++
   246  	}
   247  
   248  	return res, nil
   249  }
   250  
   251  //HSet Hash table 插入
   252  func (c *Client) HSet(ctx context.Context, key, field string, value interface{}) (int64, error) {
   253  	client, cErr := getClusterClient(c)
   254  
   255  	if cErr != nil {
   256  		return 0, cErr
   257  	}
   258  	return client.HSet(ctx, key, field, value).Result()
   259  }
   260  
   261  //HSet Hash table 插入
   262  func (c *Client) HSetNX(ctx context.Context, key, field string, value interface{}) (bool, error) {
   263  	client, cErr := getClusterClient(c)
   264  
   265  	if cErr != nil {
   266  		return false, cErr
   267  	}
   268  
   269  	return client.HSetNX(ctx, key, field, value).Result()
   270  
   271  }