栗:
func (s *commentRedisStore) SyncArticleCommentActionChanged() error {
randomKey, err := utils.GetNO(commonModel.InfoType(89), 0, s.RedisClient)
sourceKey := utils.GetArticleCommentActionChangedKey()
destKey := fmt.Sprintf("%s:%d", sourceKey, randomKey)
if err != nil {
logrus.Errorf("get sync action random key err, %v", err)
return err
}
pipe := s.RedisClient.Pipeline()
pipe.SUnionStore(destKey, sourceKey)
pipe.Del(sourceKey)
_, err = pipe.Exec()
if err != nil {
logrus.Errorf("sunion store key %s to %s err, %v", sourceKey, destKey, err)
return err
}
// 开始执行同步操作,每次获取 100 个 sn
var length int64 = 100
var keys []string
var cursor uint64 = 0
var i = 1
for cursor != 0 || i > 0 {
i--
keys, cursor = s.RedisClient.SScan(destKey, cursor, "*", length).Val()
for _, key := range keys {
cacheKey := utils.GetCommentSKey(key)
pipe.HGetAll(cacheKey)
}
if cmder, err := pipe.Exec(); err == nil {
syncArticleCommentAction(cmder)
}
}
pipe.Del(destKey)
_, _ = pipe.Exec()
return nil
}
用法:
SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
以下是一个 SCAN 命令的迭代过程示例:
redis 127.0.0.1:6379> scan 0 1) "17" 2) 1) "key:12" 2) "key:8" 3) "key:4" 4) "key:14" 5) "key:16" 6) "key:17" 7) "key:15" 8) "key:10" 9) "key:3" 10) "key:7" 11) "key:1" redis 127.0.0.1:6379> scan 17 1) "0" 2) 1) "key:5" 2) "key:18" 3) "key:0" 4) "key:2" 5) "key:19" 6) "key:13" 7) "key:6" 8) "key:9" 9) "key:11"
在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。
第二次迭代使用的是第一次迭代时返回的游标, 也即是命令回复第一个元素的值 —— 17 。
从上面的示例可以看到, SCAN 命令的回复是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素。
在第二次调用 SCAN 命令时, 命令返回了游标 0 , 这表示迭代已经结束, 整个数据集(collection)已经被完整遍历过了。
以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历(full iteration)。
更多:http://doc.redisfans.com/key/scan.html