主要是命令相关

第一章 初识Redis

1.redis是基于键值对的NoSQL.

2.redis的值可以是 string, hash, list, set, zset, bitmaps, hyperloglog, geo

3.redis的值不仅可以是字符串还可以是具体的数据结构

4.redis的2种持久方案:rdb和aof.

5.redis-server XXX.conf可以以conf的配置启动redis.

6.redis-cli shutdown可以关闭redis. 不要使用kill -9 杀死redis进程,可能会造成AOF和复制丢失数据的问题.

第二章 API的理解和使用

2.1预备

1.keys * 可以列出所有键, dbsize返回所有键的总数.dbsize时间复杂度是o(1),keys是o(n).所以键太多的时候不要使用keys *

另外实验发现keys 后面*代表任意数量的字符 ?代表单个字符

2.exists查看键是否存在,del删除键,del后面可以跟任意数量的键,比如del a b c .....

3. expire可以设置键过期时间(秒),剩余时间可以使用ttl查看.

  1. 127.0.0.1:6379> expire abcd -99 //设置负数,直接过期
  2. (integer) 1
  3. 127.0.0.1:6379> ttl abcd
  4. (integer) -2 // ttl 大于0表示剩余秒, -1表示键没设置过期时间, -2表示键不存在

4.type key可以查看key的数据结构

  1. 127.0.0.1:6379> set a 1
  2. OK
  3. 127.0.0.1:6379> LPUSH b 1 2 3 4 5
  4. (integer) 5
  5. 127.0.0.1:6379> type a
  6. string
  7. 127.0.0.1:6379> type b
  8. list
  9.  
  10. 127.0.0.1:6379> type rrr //不存在的key
    none

5.type命令返回的是redis对外的数据结构.每种数据结构对内还有N种内部编码实现.1种内部实现也可以对应N个外部数据结构.

使用object encoding查看内部数据编码

  1. 127.0.0.1:6379> set a 1
  2. OK
  3. 127.0.0.1:6379> set b 2
  4. OK
  5. 127.0.0.1:6379> lpush c 1 2 3 4
  6. (integer) 4
  7. 127.0.0.1:6379> OBJECT encoding a
  8. "int"
  9. 127.0.0.1:6379> OBJECT encoding b
  10. "int"
  11. 127.0.0.1:6379> OBJECT encoding c
  12. "ziplist"
  13. 127.0.0.1:6379> set d qqq
  14. OK
  15. 127.0.0.1:6379> OBJECT encoding d
  16. "embstr"
  17. 127.0.0.1:6379> set e 99999999999999
  18. OK
  19. 127.0.0.1:6379> OBJECT encoding e
  20. "int"
  21. 127.0.0.1:6379> set f 9999999999999999999999999.9999999999999999999999
  22. OK
  23. 127.0.0.1:6379> OBJECT encoding f
  24. "raw"
  25. 127.0.0.1:6379> set g 123.456
  26. OK
  27. 127.0.0.1:6379> OBJECT encoding g
  28. "embstr"
  29. 127.0.0.1:6379> set h 99999999999999999999999999999999999999999999999
  30. OK
  31. 127.0.0.1:6379> OBJECT encoding h
  32. "raw"

我觉得对于我们外部其他语言使用redis来说可能不太关心内部实现而是关心接口返回的外部数据结构..这个有点像java里通过接口引用具体的集合对象..

6.每次客户端调用都经历了发送命令,执行命令,返回结果三个过程.每条命令从客户端到达服务端以后不会被立刻执行,所有命令都回进入1个队列中,然后逐个被执行.

2.2字符串

1.字符串值不能超过512M

2.实验

  1. 127.0.0.1:> set k1 abc //set设置值
  2. OK
  3. 127.0.0.1:> set k2 def ex 999 //ex设置过期秒数,px设置毫秒数
  4. OK
  5. 127.0.0.1:> ttl k2
  6. (integer)
  7. 127.0.0.1:> set k1 change xx // xx key 存在才更新不然不操作,用于更新
  8. OK
  9. 127.0.0.1:> get k1
  10. "change"
  11. 127.0.0.1:> set k1 qqq
  12. OK
  13. 127.0.0.1:> get k1
  14. "qqq"
  15. 127.0.0.1:> ttl k2
  16. (integer)
  17. 127.0.0.1:> set k3 ttt nx // nx key 不存在才操作,用于插入
  18. OK
  19. 127.0.0.1:> get k3
  20. "ttt"
  21. 127.0.0.1:> set k3 www xx
  22. OK
  23. 127.0.0.1:> get k3
  24. "www"
  25. 127.0.0.1:> set k3 ppp nx // 不存在key,用nx操作.
  26. (nil)
  27. 127.0.0.1:> get k3
  28. "www"

3.setex和setnx的实验

setex key seconds value

setnx key value

setex多了1个seconds不知道为啥

  1. 127.0.0.1:6379> exists k1
  2. (integer) 1
  3. 127.0.0.1:6379> setnx k1 change //setnx不像set nx返回nil而是返回了操作了0个key
  4. (integer) 0
  5. 127.0.0.1:6379> get k1
  6. "v1"
  7. 127.0.0.1:6379> exists k2
  8. (integer) 0
  9. 127.0.0.1:6379> setnx k2 v2 // 操作成功返回操作了1个key的数量
  10. (integer) 1
  11. 127.0.0.1:6379> setnx k2 v22
  12. (integer) 0
  13. 127.0.0.1:6379>

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> setex k1 999 v999
OK
127.0.0.1:6379> ttl k1
(integer) 996
127.0.0.1:6379>

setnx可以作为分布式锁的一种方案.因为redis是单线程只有1个操作会成功返回1,其他都是0

4.mset和mget批量操作

  1. 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v4
  2. OK
  3. 127.0.0.1:6379> mget k1 k2 k3 k4
  4. 1) "v1"
  5. 2) "v2"
  6. 3) "v4"
  7. 4) (nil)
  8. 127.0.0.1:6379>

5.计数

incr incrby自增,decr decrby自减

  1. 127.0.0.1:6379> set k1 NaN
  2. OK
  3. 127.0.0.1:6379> INCR k1 //不是数字自增报错
  4. (error) ERR value is not an integer or out of range
  5. 127.0.0.1:6379> set k2 1
  6. OK
  7. 127.0.0.1:6379> incr k2
  8. (integer) 2
  9. 127.0.0.1:6379> incr k2
  10. (integer) 3
  11. 127.0.0.1:6379> get k2
  12. "3"
  13. 127.0.0.1:6379> incrby k2 3
  14. (integer) 6
  15. 127.0.0.1:6379> incrby k2 NaN //同incr
  16. (error) ERR value is not an integer or out of range
  17. 127.0.0.1:6379> incrby k2 -3 // 自增指定数量可以自增负数
  18. (integer) 3
  19. 127.0.0.1:6379> decr k1
  20. (error) ERR value is not an integer or out of range
  21. 127.0.0.1:6379> decr k2 1
  22. (error) ERR wrong number of arguments for 'decr' command
  23. 127.0.0.1:6379> decr k2
  24. (integer) 2
  25. 127.0.0.1:6379> decrby k2 2
  26. (integer) 0
  27. 127.0.0.1:6379> decrby k2 -9 //同自增
  28. (integer) 9
  1. 127.0.0.1:6379> exists k3
  2. (integer) 1
  3. 127.0.0.1:6379> del k3
  4. (integer) 1
  5. 127.0.0.1:6379> exists k3
  6. (integer) 0
  7. 127.0.0.1:6379> incr k3 //操作不存在的key,值直接当成0
  8. (integer) 1
  9. 127.0.0.1:6379> del k3
  10. (integer) 1
  11. 127.0.0.1:6379> incr k3 3
  12. (error) ERR wrong number of arguments for 'incr' command
  13. 127.0.0.1:6379> incrby k3 3 //同incr
  14. (integer) 3
  15. 127.0.0.1:6379>
  1. 127.0.0.1:6379> del k1
  2. (integer) 1
  3. 127.0.0.1:6379> del k1
  4. (integer) 0
  5. 127.0.0.1:6379> set k1 0.1
  6. OK
  7. 127.0.0.1:6379> incr k1 //自增自减只能用于整数
  8. (error) ERR value is not an integer or out of range
  9. 127.0.0.1:6379>

6.append追加字符串

  1. 127.0.0.1:6379> exists k1
  2. (integer) 1
  3. 127.0.0.1:6379> del k1
  4. (integer) 1
  5. 127.0.0.1:6379> set k1 hello
  6. OK
  7. 127.0.0.1:6379> APPEND k1 " world" //返回字符串长度
  8. (integer) 11
  9. 127.0.0.1:6379> get k1
  10. "hello world"
  11. 127.0.0.1:6379>
  1. 127.0.0.1:6379> get k1
  2. "hello world"
  3. 127.0.0.1:6379> APPEND k1 "'''"
  4. (integer) 14
  5. 127.0.0.1:6379> APPEND k1 """"
  6. Invalid argument(s)
  7. 127.0.0.1:6379> APPEND k1 "\"\"" //追加"可以用/"
  8. (integer) 16
  9. 127.0.0.1:6379> get k1
  10. "hello world'''\"\""
  11. 127.0.0.1:6379> set k1 ""
  12. OK
  13. 127.0.0.1:6379> get k1
  14. ""
  15. 127.0.0.1:6379> append k1 ""
  16. (integer) 0
  17. 127.0.0.1:6379> append k1 "
  18. Invalid argument(s)
  19. 127.0.0.1:6379> append k1 ''
  20. (integer) 0
  21. 127.0.0.1:6379> append k1 '"' //或者用'"'
  22. (integer) 1
  23. 127.0.0.1:6379> get k1
  24. "\""
  25. 127.0.0.1:6379> append k1 "'"
  26. (integer) 2
  27. 127.0.0.1:6379> get k1
  28. "\"'"
  29. 127.0.0.1:6379>

7.用strlen返回字符串长度,用getset可以设置新值并且返回原本字符串的值(有可能是nil).setrange key offset value可以改变指定位置字符,从0开始计数返回字符串长度

getrange key start end返回substr. 0开始计数,start和end都包括

  1. 127.0.0.1:6379> set k1 helloworld
  2. OK
  3. 127.0.0.1:6379> GETRANGE k1 1 2
  4. "el"
  5. 127.0.0.1:6379>

127.0.0.1:6379> GETRANGE k1 2 -1 // -1是最后1个字符串
"lloworld"
127.0.0.1:6379> GETRANGE k1 2 -2
"lloworl"
127.0.0.1:6379> GETRANGE k1 2 0
""
127.0.0.1:6379> GETRANGE k1 2 -0
""
127.0.0.1:6379>

8.字符串内部有3种编码,int 8字节长整型,embstr<=39字节的字符串,raw>39字节的字符串

  1. 127.0.0.1:6379> set k1 9203372036054477800
  2. OK
  3. 127.0.0.1:6379> OBJECT encoding k1
  4. "int"
  5. 127.0.0.1:6379> set k1 9233372000000000000
  6. OK
  7. 127.0.0.1:6379> OBJECT encoding k1
  8. "embstr"

8字节是64位,java里long的范围应该是

  1. -9233372036854477808-9233372036854477808 (https://zhidao.baidu.com/question/256678932.html)

但是不知道为什么这里redis似乎不是

  1. 127.0.0.1:6379> set k1 //length=3
  2. OK
  3. 127.0.0.1:6379> object encoind k1
  4. (error) ERR Syntax error. Try OBJECT (refcount|encoding|idletime)
  5. 127.0.0.1:6379> object encoding k1
  6. "embstr"
  7. 127.0.0.1:6379> strlen k1
  8. (integer) 3
  9. 127.0.0.1:6379> set k1 呵呵呵呵呵呵呵呵呵呵呵呵呵 //length=39
  10. OK
  11. 127.0.0.1:6379> object encoding k1
  12. "embstr"
  13. 127.0.0.1:6379> set k1 呵呵呵呵呵呵呵呵呵呵呵呵呵a //40
  14. OK
  15. 127.0.0.1:6379> strlenth k1
  16. (error) ERR unknown command 'strlenth'
  17. 127.0.0.1:6379> strlen k1
  18. (integer) 40
  19. 127.0.0.1:6379> object encoding k1
  20. "raw"
  21. 127.0.0.1:6379>

似乎是1个中文UTF-8占3个字节的缘故

2.3哈希

1.

hset key field value

het key field

  1. 127.0.0.1:6379> hset k1 f1 v1
  2. (integer) 1
  3. 127.0.0.1:6379> hget k1
  4. (error) ERR wrong number of arguments for 'hget' command
  5. 127.0.0.1:6379> hget k1 f1
  6. "v1"
  7. 127.0.0.1:6379> HGETALL k1
  8. 1) "f1"
  9. 2) "v1"
  10. 127.0.0.1:6379>

2.hdel key field [...field]

  1. 127.0.0.1:6379> hset k1 f1 v1
  2. (integer) 1
  3. 127.0.0.1:6379> hset k1 f2 v2
  4. (integer) 1
  5. 127.0.0.1:6379> hset k1 f3 v3
  6. (integer) 1
  7. 127.0.0.1:6379> hdel k1 f1 f2 //返回删除个数
  8. (integer) 2
  9. 127.0.0.1:6379> hget k1
  10. (error) ERR wrong number of arguments for 'hget' command
  11. 127.0.0.1:6379> hgetall k1
  12. 1) "f3"
  13. 2) "v3"
  14. 127.0.0.1:6379>

3.hlen key返回field的个数

4.hmget field [field....]

hmset key field value [field value...]

批量操作hash

  1. 127.0.0.1:6379> hmset k1 f1 v1 f2 v2 f3 v3
  2. OK
  3. 127.0.0.1:6379> mhget k1 f1 f2 f3
  4. (error) ERR unknown command 'mhget'
  5. 127.0.0.1:6379> hmget k1 f1 f2 f3
  6. 1) "v1"
  7. 2) "v2"
  8. 3) "v3"
  9. 127.0.0.1:6379> HGETALL k1
  10. 1) "f1"
  11. 2) "v1"
  12. 3) "f2"
  13. 4) "v2"
  14. 5) "f3"
  15. 6) "v3"
  16. 127.0.0.1:6379>

5.

hexists key field 判断field是否存在

  1. 127.0.0.1:6379> HEXISTS l1 f1
  2. (integer) 0
  3. 127.0.0.1:6379> HEXISTS k1 f1
  4. (integer) 1
  5. 127.0.0.1:6379> hget k1 f1
  6. "v1"
  7. 127.0.0.1:6379> hget l1 f1
  8. (nil)
  9. 127.0.0.1:6379>

6.

hkeys * 获取所有field

hvals获取所有value

hgetall key 获取所有fieldvalue

  1. 127.0.0.1:6379> HKEYS k1
  2. 1) "f1"
  3. 2) "f2"
  4. 3) "f3"
  5. 127.0.0.1:6379> HVALS k1
  6. 1) "v1"
  7. 2) "v2"
  8. 3) "v3"
  9. 127.0.0.1:6379> HGETALL k1
  10. 1) "f1"
  11. 2) "v1"
  12. 3) "f2"
  13. 4) "v2"
  14. 5) "f3"
  15. 6) "v3"
  16. 127.0.0.1:6379>

7.

没有hincr命令.hincrby和hincrbyfloat和hstrlen与String的类似

8.

hash的内部编码有ziplist(个数小于512,或者所有值小于64字节),hashtable

2.4列表

一个列表最多可以存储2^32 -1 个元素.

lpush key value [value...]

rpush key value[value...]

  1. 127.0.0.1:6379> exists k1
  2. (integer) 1
  3. 127.0.0.1:6379> del k1
  4. (integer) 1
  5. 127.0.0.1:6379> lpush a b c
  6. (error) WRONGTYPE Operation against a key holding the wrong kind of value
  7. 127.0.0.1:6379> lpush k1 a b c
  8. (integer) 3
  9. 127.0.0.1:6379> rpush k1 d e f
  10. (integer) 6
  11. 127.0.0.1:6379> lrange k1 0 -1
  12. 1) "c"
  13. 2) "b"
  14. 3) "a"
  15. 4) "d"
  16. 5) "e"
  17. 6) "f"
  18. 127.0.0.1:6379> lrange k1 2 3 //取下标对应的元素,从0开始
  19. 1) "a"
  20. 2) "d"
  21. 127.0.0.1:6379>

linsert key before|after pivotValue value 在pivotValue之前或者之后插入元素

  1. 127.0.0.1:6379> lrange k1 0 -1
  2. 1) "c"
  3. 2) "b"
  4. 3) "a"
  5. 4) "d"
  6. 5) "e"
  7. 6) "f"
  8. 127.0.0.1:6379>
  9. 127.0.0.1:6379> LINSERT k1 before a 9
  10. (integer) 7
  11. 127.0.0.1:6379> lrange k1 0 -1
  12. 1) "c"
  13. 2) "b"
  14. 3) "9"
  15. 4) "a"
  16. 5) "d"
  17. 6) "e"
  18. 7) "f"
  19. 127.0.0.1:6379> LINSERT k1 after a 8
  20. (integer) 8
  21. 127.0.0.1:6379> lrange k1 0 -1
  22. 1) "c"
  23. 2) "b"
  24. 3) "9"
  25. 4) "a"
  26. 5) "8"
  27. 6) "d"
  28. 7) "e"
  29. 8) "f"
  30. 127.0.0.1:6379> lpush k1 a
  31. (integer) 9
  32. 127.0.0.1:6379> lrange k1 0 -1
  33. 1) "a"
  34. 2) "c"
  35. 3) "b"
  36. 4) "9"
  37. 5) "a"
  38. 6) "8"
  39. 7) "d"
  40. 8) "e"
  41. 9) "f"
  42. 127.0.0.1:6379> LINSERT k1 after a 7 //在找到的第一个元素后面添加然后直接return
  43. (integer) 10
  44. 127.0.0.1:6379> lrange k1 0 -1
  45. 1) "a"
  46. 2) "7"
  47. 3) "c"
  48. 4) "b"
  49. 5) "9"
  50. 6) "a"
  51. 7) "8"
  52. 8) "d"
  53. 9) "e"
  54. 10) "f"
  55. 127.0.0.1:6379> rINSERT k1 after a 7 //没有rinsert
  56. (error) ERR unknown command 'rINSERT'
  57. 127.0.0.1:6379>

lindex key index 获取指定位置的元素,负数就是从最后面1个元素开始数

  1. 127.0.0.1:6379> lrange k1 0 -1
  2. 1) "a"
  3. 2) "7"
  4. 3) "c"
  5. 4) "b"
  6. 5) "9"
  7. 6) "a"
  8. 7) "8"
  9. 8) "d"
  10. 9) "e"
  11. 10) "f"
  12. 127.0.0.1:6379> lindex k1 1
  13. "7"
  14. 127.0.0.1:6379> lindex k1 -2 //倒数第二个元素
  15. "e"
  16. 127.0.0.1:6379>

llen key获取列表元素个数

lpop key和rpop key用于删除元素

lrem key count value找到value以后最多删除count个值为value的元素

count>0才能够左往右删除,<0从右往左,=0全部删除

  1. 127.0.0.1:6379> lrange k1 0 -1
  2. 1) "a"
  3. 2) "7"
  4. 3) "c"
  5. 4) "b"
  6. 5) "9"
  7. 6) "a"
  8. 7) "8"
  9. 8) "d"
  10. 9) "e"
  11. 10) "f"
  12. 127.0.0.1:6379> lrem k1 2 a //2个a都删除了
  13. (integer) 2
  14. 127.0.0.1:6379> lrange k1 0 -1
  15. 1) "7"
  16. 2) "c"
  17. 3) "b"
  18. 4) "9"
  19. 5) "8"
  20. 6) "d"
  21. 7) "e"
  22. 8) "f"
  23. 127.0.0.1:6379> lrem k1 8 -1
  24. (integer) 0
  25. 127.0.0.1:6379> lrem k1 -1 8 //删除1个8右边开始
  26. (integer) 1
  27. 127.0.0.1:6379> lrange k1 0 -1
  28. 1) "7"
  29. 2) "c"
  30. 3) "b"
  31. 4) "9"
  32. 5) "d"
  33. 6) "e"
  34. 7) "f"
  35. 127.0.0.1:6379> lrem k1 0 e //所有e都删除
  36. (integer) 1
  37. 127.0.0.1:6379> lrange k1 0 -1
  38. 1) "7"
  39. 2) "c"
  40. 3) "b"
  41. 4) "9"
  42. 5) "d"
  43. 6) "f"
  44. 127.0.0.1:6379>

ltrim key start end 按照索引保留元素

  1. 127.0.0.1:6379> exists k1
  2. (integer) 1
  3. 127.0.0.1:6379> lrange k1 0 -1
  4. 1) "7"
  5. 2) "c"
  6. 3) "b"
  7. 4) "9"
  8. 5) "d"
  9. 6) "f"
  10. 127.0.0.1:6379> LTRIM k1 1 3
  11. OK
  12. 127.0.0.1:6379> lrange k1 0 -1
  13. 1) "c"
  14. 2) "b"
  15. 3) "9"
  16. 127.0.0.1:6379>

lset key index newValue可以修改index的元素

  1. 127.0.0.1:6379> lrange k1 0 -1
  2. 1) "c"
  3. 2) "b"
  4. 3) "9"
  5. 127.0.0.1:6379> lset k1 0 a
  6. OK
  7. 127.0.0.1:6379> lrange k1 0 -1
  8. 1) "a"
  9. 2) "b"
  10. 3) "9"
  11. 127.0.0.1:6379> lset k1 99 a
  12. (error) ERR index out of range
  13. 127.0.0.1:6379>

blpop key [key...] timeout 弹出key最左边的元素,阻塞timeout秒.

brpop同理

  1. 127.0.0.1:6379> lrange k1 0 -1
  2. 1) "a"
  3. 2) "b"
  4. 3) "9"
  5. 127.0.0.1:6379> blpop k1 9
  6. 1) "k1"
  7. 2) "a"
  8. 127.0.0.1:6379> exists k2
  9. (integer) 1
  10. 127.0.0.1:6379> del k2
  11. (integer) 1
  12. 127.0.0.1:6379> del k2
  13. (integer) 0
  14. 127.0.0.1:6379> blpop k2 9
  15. (nil)
  16. (9.02s)
  17. 127.0.0.1:6379>

多个key只要有1个能返回就立即返回.

多个客户端同时阻塞,添加元素后.哪个客户端命令先执行哪个就先返回,剩下的继续阻塞.

列表的内部实现有ziplist和linkedlist.条件范围同hash

使用场景:

lpush和brpop可以实现消息队列.

2.5集合

集合不允许重复yuansu,zuiduo储存2^32-1个元素.

sadd key element [element...] 新增元素

srem key element [element...] 删除元素

scard key 计算元素个数(竟然不是slen...)

smenbers key 返回集合所有元素

  1. 127.0.0.1:6379> exists k3
  2. (integer) 1
  3. 127.0.0.1:6379> type k3
  4. string
  5. 127.0.0.1:6379> get k3
  6. "3vv\n"
  7. 127.0.0.1:6379> del k3
  8. (integer) 1
  9. 127.0.0.1:6379> sadd k3 e1 e2 e3 e4
  10. (integer) 4
  11. 127.0.0.1:6379> srem e2 e5
  12. (integer) 0
  13. 127.0.0.1:6379> srem k3 e2 e5 //e2存在 e5不存在
  14. (integer) 1 //成功删除e2返回结果1
  15. 127.0.0.1:6379> scard k3 //返回集合元素个数为3
  16. (integer) 3
  17. 127.0.0.1:6379> SMEMBERS k3 //查看所有元素
  18. 1) "e1"
  19. 2) "e4"
  20. 3) "e3"
  21. 127.0.0.1:6379>

sismenmber key element 判断元素是否在集合内

srandmember key [count] 随机返回count个元素,默认为1

spop 随机弹出1个元素

  1. 127.0.0.1:6379> smembers k3
  2. 1) "e1"
  3. 2) "e4"
  4. 3) "e3"
  5. 127.0.0.1:6379> sismember k3 e1 //存在元素返回1
  6. (integer) 1
  7. 127.0.0.1:6379> sismember k3 e2 //不存在返回0
  8. (integer) 0
  9. 127.0.0.1:6379> sismember k3 e1 e2
  10. (error) ERR wrong number of arguments for 'sismember' command
  11. 127.0.0.1:6379> sranmember key 1
  12. (error) ERR unknown command 'sranmember'
  13. 127.0.0.1:6379> sranmember k3 1
  14. (error) ERR unknown command 'sranmember'
  15. 127.0.0.1:6379> srandmember k3 1 //随机返回1个元素不删除
  16. 1) "e4"
  17. 127.0.0.1:6379> srandmember k3 1
  18. 1) "e1"
  19. 127.0.0.1:6379> srandmember k3 4
  20. 1) "e1"
  21. 2) "e4"
  22. 3) "e3"
  23. 127.0.0.1:6379> spop k3 //随机返回1个元素并删除
  24. "e1"
  25. 127.0.0.1:6379> smembers
  26. (error) ERR wrong number of arguments for 'smembers' command
  27. 127.0.0.1:6379> smembers k3
  28. 1) "e4"
  29. 2) "e3"
  30. 127.0.0.1:6379> spop k3 9 //3.2以后支持
  31. (error) ERR wrong number of arguments for 'spop' command
  32. 127.0.0.1:6379>

sinter key [key...] 取交集

sunion key [key...] 取并集

sdiff key [key..] 取差集

sinterstore destination key [keys...]

union和diff同理

  1. 127.0.0.1:6379> del k1 k2 k3
  2. (integer) 3
  3. 127.0.0.1:6379> sadd k1 1 2 3 4 5 6 7
  4. (integer) 7
  5. 127.0.0.1:6379> sadd k2 3 4 5 6
  6. (integer) 4
  7. 127.0.0.1:6379> sadd k3 5 6 7 8 9 10
  8. (integer) 6
  9. 127.0.0.1:6379> sinter k1 k2
  10. 1) "3"
  11. 2) "4"
  12. 3) "5"
  13. 4) "6"
  14. 127.0.0.1:6379> sinter k1 k2 k3
  15. 1) "5"
  16. 2) "6"
  17. 127.0.0.1:6379> sinterstore k4 k1 k2 k3
  18. (integer) 2
  19. 127.0.0.1:6379> sdiff k1 k2
  20. 1) "1"
  21. 2) "2"
  22. 3) "7"
  23. 127.0.0.1:6379> sdiff k1 k2 k3
  24. 1) "1"
  25. 2) "2"
  26. 127.0.0.1:6379> SDIFFSTORE k6 k1 k2 k3
  27. (integer) 2
  28. 127.0.0.1:6379>

集合内部使用intset或者hashtable实现

intset为集合所有元素都为整形或者元素小于等于512个时候

hashtable为不满足intset的时候

场景

可以用于用户标签

2.6有序集合

有序集合保留了集合不能有重复元素的特征,但是可以排序,每个元素都有个对应的分数作为排序依据(分数可以重复).

zadd key score member [score member...] 添加元素

zcard key 计算元素个数

zscore key member 计算元素的分数

  1. 127.0.0.1:6379> del k1
  2. (integer) 1
  3. 127.0.0.1:6379> zadd k1 1 e1 2 e2 3 e3 4 e4 5 e5
  4. (integer) 5
  5. 127.0.0.1:6379> zcard k1
  6. (integer) 5
  7. 127.0.0.1:6379> zscore k1 e3
  8. "3"
  9. 127.0.0.1:6379>

zrank key member [member...] 和 zrevrank key member 对元素进行排序输出排序好吗,从0开始

zrem key remember [member...] 对元素进行删除

zincrby key incrememt member 增加成员的分数

  1. 127.0.0.1:6379> zrem k1 e2
  2. (integer) 1
  3. 127.0.0.1:6379> zrank k1 e1
  4. (integer) 0
  5. 127.0.0.1:6379> zrevrank k1 e1
  6. (integer) 3
  7. 127.0.0.1:6379> ZINCRBY k1 99 e1
  8. "100"
  9. 127.0.0.1:6379> zrevrank k1 e1
  10. (integer) 0
  11. 127.0.0.1:6379> zrank k1 e1
  12. (integer) 3
  13. 127.0.0.1:6379>

zrange key start end [withscores] 低到高排序输出start-end的元素

zrevrange key start end [withscores] 高到低排序输出元素

  1. 127.0.0.1:6379> zrange k1 0 -1 // 输出所有元素 -1是最后1个 0是第一个
  2. 1) "e3"
  3. 2) "e4"
  4. 3) "e5"
  5. 4) "e1"
  6. 127.0.0.1:6379> zrange k1 0 0
  7. 1) "e3"
  8. 127.0.0.1:6379> zrange k1 0 -3
  9. 1) "e3"
  10. 2) "e4"
  11. 127.0.0.1:6379> zrange k1 1 1
  12. 1) "e4"
  13. 127.0.0.1:6379> zrange k1 0 -1 withscores
  14. 1) "e3"
  15. 2) "3"
  16. 3) "e4"
  17. 4) "4"
  18. 5) "e5"
  19. 6) "5"
  20. 7) "e1"
  21. 8) "100"
  22. 127.0.0.1:6379> zrevrange k1 0 -1 withscores
  23. 1) "e1"
  24. 2) "100"
  25. 3) "e5"
  26. 4) "5"
  27. 5) "e4"
  28. 6) "4"
  29. 7) "e3"
  30. 8) "3"
  31. 127.0.0.1:6379>

zrangebyscore key min max [withscores] [limit offset count]

zrevrangebyscore key max min [withscores] [limit offser count]

返回指定分数范围内的成员

  1. 127.0.0.1:6379> zrange k1 0 -1 withscores
  2. 1) "e3"
  3. 2) "3"
  4. 3) "e4"
  5. 4) "4"
  6. 5) "e5"
  7. 6) "5"
  8. 7) "e1"
  9. 8) "100"
  10. 127.0.0.1:6379>
  11. 127.0.0.1:6379> zrangebyscore k1 0 999 withscores
  12. 1) "e3"
  13. 2) "3"
  14. 3) "e4"
  15. 4) "4"
  16. 5) "e5"
  17. 6) "5"
  18. 7) "e1"
  19. 8) "100"
  20. 127.0.0.1:6379> zrangebyscore k1 0 +inf withscores //+inf表示无限大
  21. 1) "e3"
  22. 2) "3"
  23. 3) "e4"
  24. 4) "4"
  25. 5) "e5"
  26. 6) "5"
  27. 7) "e1"
  28. 8) "100"
  29. 127.0.0.1:6379> zrangebyscore k1 (3 +inf withscores //默认是[闭区间 (表示开区间
  30. 1) "e4"
  31. 2) "4"
  32. 3) "e5"
  33. 4) "5"
  34. 5) "e1"
  35. 6) "100"
  36. 127.0.0.1:6379> zrangebyscore k1 {3 +inf withscores
  37. (error) ERR min or max is not a float
  38. 127.0.0.1:6379> zrangebyscore k1 [3 +inf withscores //似乎不能是[
  39. (error) ERR min or max is not a float
  40. 127.0.0.1:6379> zrangebyscore k1 3 -inf withscores
  41. (empty list or set)
  42. 127.0.0.1:6379> zrangebyscore k1 3 2 withscores
  43. (empty list or set)
  44. 127.0.0.1:6379> ZREVRANGEBYSCORE k1 +inf 0 withscores //reverse的时候先写max再写min
  45. 1) "e1"
  46. 2) "100"
  47. 3) "e5"
  48. 4) "5"
  49. 5) "e4"
  50. 6) "4"
  51. 7) "e3"
  52. 8) "3"
  53. 127.0.0.1:6379> ZREVRANGEBYSCORE k1 (100 0 withscores
  54. 1) "e5"
  55. 2) "5"
  56. 3) "e4"
  57. 4) "4"
  58. 5) "e3"
  59. 6) "3"
  60. 127.0.0.1:6379> ZREVRANGEBYSCORE k1 (100 101 withscores
  61. (empty list or set)
  62. 127.0.0.1:6379>

zcount key min max 返回分数范围内成员个数

zremrangebyzrank key start end 删除元素,按升序

zremrangebyscore key min max 删除元素按分数

  1. 127.0.0.1:6379> zcount k1 50 +inf
  2. (integer) 1
  3. 127.0.0.1:6379> ZRANK k1 0 -1
  4. (error) ERR wrong number of arguments for 'zrank' command
  5. 127.0.0.1:6379> zrange k1 0 -1
  6. 1) "e3"
  7. 2) "e4"
  8. 3) "e5"
  9. 4) "e1"
  10. 127.0.0.1:6379> zrange k1 0 -1 withscores
  11. 1) "e3"
  12. 2) "3"
  13. 3) "e4"
  14. 4) "4"
  15. 5) "e5"
  16. 6) "5"
  17. 7) "e1"
  18. 8) "100"
  19. 127.0.0.1:6379> ZREMRANGEBYRANK k1 0 1
  20. (integer) 2
  21. 127.0.0.1:6379> zrange k1 0 -1 withscores
  22. 1) "e5"
  23. 2) "5"
  24. 3) "e1"
  25. 4) "100"
  26. 127.0.0.1:6379> ZREMRANGEBYSCORE k1 0 5
  27. (integer) 1
  28. 127.0.0.1:6379> zrange k1 0 -1 withscores
  29. 1) "e1"
  30. 2) "100"
  31. 127.0.0.1:6379>

zinterstore destnation numkeys key [key...] [weights weight [weight....]] [aggragate sum|min|max] 计算交集

  1. 127.0.0.1:6379> del k1
  2. (integer) 1
  3. 127.0.0.1:6379> ZADD k1 10 e1 20 e2 30 e3 40 e4 50 e5
  4. (integer) 5
  5. 127.0.0.1:6379> del k2
  6. (integer) 1
  7. 127.0.0.1:6379> ZADD k2 11 e1 22 e2 33 e3 44 e4 55 e5
  8. (integer) 5
  9. 127.0.0.1:6379> zadd k2 66 e6
  10. (integer) 1
  11. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2
  12. (integer) 5
  13. 127.0.0.1:6379> zrange k1_2 0 -1
  14. 1) "e1"
  15. 2) "e2"
  16. 3) "e3"
  17. 4) "e4"
  18. 5) "e5"
  19. 127.0.0.1:6379> zrange k1_2 0 -1 withscores
  20. 1) "e1"
  21. 2) "21"
  22. 3) "e2"
  23. 4) "42"
  24. 5) "e3"
  25. 6) "63"
  26. 7) "e4"
  27. 8) "84"
  28. 9) "e5"
  29. 10) "105"
  30. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.5 1
  31. (integer) 5
  32. 127.0.0.1:6379> zrange k1_2 0 -1 withscores //默认是weight都是1,aggregate是sum
  33. 1) "e1"
  34. 2) "16"
  35. 3) "e2"
  36. 4) "32"
  37. 5) "e3"
  38. 6) "48"
  39. 7) "e4"
  40. 8) "64"
  41. 9) "e5"
  42. 10) "80"
  43. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.3 //weights写了1个就必须都得写完
  44. (error) ERR syntax error
  45. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.3 1
  46. (integer) 5
  47. 127.0.0.1:6379> zrange k1_2 0 -1 withscores
  48. 1) "e1"
  49. 2) "14"
  50. 3) "e2"
  51. 4) "28"
  52. 5) "e3"
  53. 6) "42"
  54. 7) "e4"
  55. 8) "56"
  56. 9) "e5"
  57. 10) "70"
  58. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.5 0.5
  59. (integer) 5
  60. 127.0.0.1:6379> zrange k1_2 0 -1 withscores
  61. 1) "e1"
  62. 2) "10.5"
  63. 3) "e2"
  64. 4) "21"
  65. 5) "e3"
  66. 6) "31.5"
  67. 7) "e4"
  68. 8) "42"
  69. 9) "e5"
  70. 10) "52.5"
  71. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 1 1 aggragate min
  72. (error) ERR syntax error
  73. 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 1 1 aggregate min
  74. (integer) 5
  75. 127.0.0.1:6379> zrange k1_2 0 -1 withscores
  76. 1) "e1"
  77. 2) "10"
  78. 3) "e2"
  79. 4) "20"
  80. 5) "e3"
  81. 6) "30"
  82. 7) "e4"
  83. 8) "40"
  84. 9) "e5"
  85. 10) "50"
  86. 127.0.0.1:6379>

zunionstore destination numkeys key [key...] [weights weight [weight...]] [aggregate sum|min|max] 计算并集

  1. 127.0.0.1:6379> clear
  2. 127.0.0.1:6379> zrange k1 0 -1 withscores
  3. 1) "e1"
  4. 2) "10"
  5. 3) "e2"
  6. 4) "20"
  7. 5) "e3"
  8. 6) "30"
  9. 7) "e4"
  10. 8) "40"
  11. 9) "e5"
  12. 10) "50"
  13. 127.0.0.1:6379> zrange k2 0 -1 withscores
  14. 1) "e1"
  15. 2) "11"
  16. 3) "e2"
  17. 4) "22"
  18. 5) "e3"
  19. 6) "33"
  20. 7) "e4"
  21. 8) "44"
  22. 9) "e5"
  23. 10) "55"
  24. 11) "e6"
  25. 12) "66"
  26. 127.0.0.1:6379> zunoin k1_2 2 k1 k2 weights 1 0.5
  27. (error) ERR unknown command 'zunoin'
  28. 127.0.0.1:6379> zunion k1_2 2 k1 k2 weights 1 0.5
  29. (error) ERR unknown command 'zunion'
  30. 127.0.0.1:6379> zunionstore k1_2 2 k1 k2 weights 1 0.5
  31. (integer) 6
  32. 127.0.0.1:6379> zrange k1_2 0 -1 WITHSCORES
  33. 1) "e1"
  34. 2) "15.5"
  35. 3) "e2"
  36. 4) "31"
  37. 5) "e6"
  38. 6) "33"    
  39. 7) "e3" //e6只有33因为k1里没有,k2 weight是0.5
  40. 8) "46.5"
  41. 9) "e4"
  42. 10) "62"
  43. 11) "e5"
  44. 12) "77.5"
  45. 127.0.0.1:6379>

内部使用ziplist和skiplist.

元素个数小于128并且只都小于64字节时用ziplist否则用skiplist

场景

主要用于排行榜

2.7键管理

rename key newKey 重命名键

renamenx key newKey  当newkey不存在的时候才会成功重命名

randomkey 随机返回1个键

  1. 127.0.0.1:6379> del k1 k2
  2. (integer) 2
  3. 127.0.0.1:6379> mset k1 haha k2 hehe
  4. OK
  5. 127.0.0.1:6379> mget k1 k2
  6. 1) "haha"
  7. 2) "hehe"
  8. 127.0.0.1:6379> rename k1 k2
  9. OK
  10. 127.0.0.1:6379> exists k1
  11. (integer) 0
  12. 127.0.0.1:6379> exists k2
  13. (integer) 1
  14. 127.0.0.1:6379> get k2
  15. "haha"
  16. 127.0.0.1:6379> rename k2 k2 //一样的key在3.2以下版本会boom
  17. (error) ERR source and destination objects are the same
  18. 127.0.0.1:6379> keys *
  19. 1) "e"
  20. 2) "k2"
  21. 3) "b"
  22. 4) "k4"
  23. 5) "f"
  24. 6) "h"
  25. 7) "k6"
  26. 8) "k3"
  27. 9) "d"
  28. 10) "g"
  29. 11) "k1_2"
  30. 12) "c"
  31. 13) "a"
  32. 127.0.0.1:6379> RANDOMKEY
  33. "k4"
  34. 127.0.0.1:6379> RANDOMKEY
  35. "k4"
  36. 127.0.0.1:6379> RANDOMKEY
  37. "a"
  38. 127.0.0.1:6379> RANDOMKEY
  39. "k4"
  40. 127.0.0.1:6379> RANDOMKEY
  41. "b"
  42. 127.0.0.1:6379>

expire key seconds 设置X秒后键过期,负数直接删除

expireat key timestamp 在秒级时间戳后x后过期

ttl key 返回键的剩余过期秒数

persist 清除键过期时间

  1. 127.0.0.1:6379> exists k2
  2. (integer) 1
  3. 127.0.0.1:6379> ttl k2
  4. (integer) -1 // -1不过期
  5. 127.0.0.1:6379> expire k2 999
  6. (integer) 1
  7. 127.0.0.1:6379> ttl k2
  8. (integer) 997
  9. 127.0.0.1:6379> PERSIST k2 //永不过期
  10. (integer) 1
  11. 127.0.0.1:6379> ttl k2
  12. (integer) -1
  13. 127.0.0.1:6379> get k2
  14. "haha"
  15. 127.0.0.1:6379> del k2
  16. (integer) 1
  17. 127.0.0.1:6379> ttl k2
  18. (integer) -2 // -2键不存在
  19. 127.0.0.1:6379>

pexpire key milliseconds 设置键X毫秒后捡国旗

pexpireat key milliseconds-timestamp 在毫秒级时间戳X后键过期

set会去除过期时间

  1. 127.0.0.1:6379> set k1 heihei ex 999
  2. OK
  3. 127.0.0.1:6379> get k1
  4. "heihei"
  5. 127.0.0.1:6379> ttl k1
  6. (integer) 994
  7. 127.0.0.1:6379> ttl k1
  8. (integer) 993
  9. 127.0.0.1:6379> set k1 wahaha
  10. OK
  11. 127.0.0.1:6379> ttl k1
  12. (integer) -1 // 时间被清除了
  13. 127.0.0.1:6379>

redis不支持对二级数据结构做过期时间设置

setex命令是原子执行的

move可以在redis内部数据库进行键迁移

  1. 127.0.0.1:6379> select 0
  2. OK
  3. 127.0.0.1:6379> get k1
  4. "wahaha"
  5. 127.0.0.1:6379> move k1 1
  6. (integer) 1
  7. 127.0.0.1:6379> exists k1
  8. (integer) 0
  9. 127.0.0.1:6379> select 1
  10. OK
  11. 127.0.0.1:6379[1]> keys *
  12. 1) "k1"
  13. 127.0.0.1:6379[1]> get k1
  14. "wahaha"
  15. 127.0.0.1:6379[1]>

dump key 将值序列化

restore key ttl value 将值反序列化到数据库中

  1. 127.0.0.1:6379> exists k1
  2. (integer) 1
  3. 127.0.0.1:6379> type k1
  4. string
  5. 127.0.0.1:6379> dump l1
  6. (nil)
  7. 127.0.0.1:6379> dump k1
  8. "\x00\x06wahaha\x06\x00\xd7\x03\xb2\xb3I5\xd9\xc7"
  9. 127.0.0.1:6379>
  1. 127.0.0.1:6380> RESTORE k1 0 "\x00\x06wahaha\x06\x00\xd7\x03\xb2\xb3I5\xd9\xc7"
  2. OK
  3. 127.0.0.1:6380> get k1
  4. "wahaha"
  5. 127.0.0.1:6380>

migrate host port key| "" destination-db timeout [copy] [replace] [keys key [key ...]] 在redis之前迁移数据,migrate命令具有原子性

  1. 127.0.0.1:6379> keys *
  2. 1) "e"
  3. 2) "b"
  4. 3) "k4"
  5. 4) "k1"
  6. 5) "f"
  7. 6) "h"
  8. 7) "k6"
  9. 8) "k3"
  10. 9) "d"
  11. 10) "g"
  12. 11) "k1_2"
  13. 12) "c"
  14. 13) "a"
  15. 127.0.0.1:6379> MIGRATE localhost 6379 0 0 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
  16. (error) ERR syntax error
  17. 127.0.0.1:6379> MIGRATE localhost 6380 0 0 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
  18. (error) ERR syntax error
  19. 127.0.0.1:6379> MIGRATE localhost 6380 0 1000 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
  20. (error) ERR syntax error
  21. 127.0.0.1:6379> MIGRATE 127.0.0.1 6380 0 0 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
  22. (error) ERR syntax error
  23. 127.0.0.1:6379> MIGRATE localhost 6380 0 0 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a
  24. (error) ERR When using MIGRATE KEYS option, the key argument must be set to the empty string
  25. 127.0.0.1:6379> MIGRATE localhost 6380 "" 0 0 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a //不要忘记写""
  26. OK
  27. 127.0.0.1:6379>
  1. 127.0.0.1:6380> keys *
  2. 1) "k1_change"
  3. 127.0.0.1:6380> del k1_change
  4. (integer) 1
  5. 127.0.0.1:6380> keys *
  6. (empty list or set) //等待6379迁移数据过来
  7. 127.0.0.1:6380> keys *
  8. 1) "k4"
  9. 2) "c"
  10. 3) "b"
  11. 4) "k3"
  12. 5) "e"
  13. 6) "a"
  14. 7) "k6"
  15. 8) "k1_2"
  16. 9) "h"
  17. 10) "d"
  18. 11) "k1"
  19. 12) "f"
  20. 13) "g"
  21. 127.0.0.1:6380>

不知道为什么我1个redis实例不同数据库之间迁移不行,我觉得可能是因为这是1个事务,同个实例要接受迁移的键也要等这个事务结束才行.所以迁移需要等待接受好才能结束,接受需要等迁移事务结束才可以开始造成的.(猜测)

  1. 127.0.0.1:6379> MIGRATE localhost 6379 "" 1 0 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a
  2. (error) IOERR error or timeout reading to target instance
  3. (1.00s)
  4. 127.0.0.1:6379> MIGRATE localhost 6379 "" 1 3000 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a
  5. (error) IOERR error or timeout reading to target instance
  6. (3.00s)
  7. 127.0.0.1:6379>

迁移命令比较

命令 作用域 原子性 支持多个键
move redis实例内部
dump+restore redis实例之间
migrate redis实例之间

  

keys pattern 遍历键

*代表任意字符

?代表一个字符

[]代表部分匹配,[1,3]代表匹配1,3 [1-10]代表匹配1-10任意数字

\x用来转义

  1. 127.0.0.1:6380> exists ka1
  2. (integer) 1
  3. 127.0.0.1:6380> keys k[a-z]1
  4. 1) "ka1"
  5. 127.0.0.1:6380> k?[1-99]
  6. (error) ERR unknown command 'k?[1-99]'
  7. 127.0.0.1:6380> k?[0-10]
  8. (error) ERR unknown command 'k?[0-10]'
  9. 127.0.0.1:6380> k?[1-10]
  10. (error) ERR unknown command 'k?[1-10]'
  11. 127.0.0.1:6380> keys k?[0-99]
  12. 1) "ka1"
  13. 127.0.0.1:6380>

删除键

redis-cli keys pattern | xargs redis-cli del //我执行是失败的,不认识xargs....

渐进式遍历键

scan cursor [match pattern] [count number]

cursor是游标,从0开始,count number默认是10,命令返回当前游标值

  1. 127.0.0.1:6380> mset a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q qr r s s t t u u v v w w x x y y z z
  2. (error) ERR wrong number of arguments for MSET
  3. 127.0.0.1:6380> mset a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z
  4. OK
  5. 127.0.0.1:6380> scan 0
  6. 1) "22"
  7. 2) 1) "y"
  8. 2) "g"
  9. 3) "o"
  10. 4) "z"
  11. 5) "s"
  12. 6) "e"
  13. 7) "i"
  14. 8) "h"
  15. 9) "a"
  16. 10) "t"
  17. 127.0.0.1:6380> scan 22
  18. 1) "7"
  19. 2) 1) "b"
  20. 2) "j"
  21. 3) "k"
  22. 4) "q"
  23. 5) "d"
  24. 6) "m"
  25. 7) "r"
  26. 8) "n"
  27. 9) "p"
  28. 10) "x"
  29. 11) "f"
  30. 127.0.0.1:6380> scan 7
  31. 1) "0"
  32. 2) 1) "v"
  33. 2) "l"
  34. 3) "u"
  35. 4) "w"
  36. 5) "c"
  37. 127.0.0.1:6380>

注意第二次返回了11个元素

SCAN 命令的保证(guarantees)

SCAN 命令, 以及其他增量式迭代命令, 在进行完整遍历的情况下可以为用户带来以下保证: 从完整遍历开始直到完整遍历结束期间, 一直存在于数据集内的所有元素都会被完整遍历返回; 这意味着, 如果有一个元素, 它从遍历开始直到遍历结束期间都存在于被遍历的数据集当中, 那么 SCAN 命令总会在某次迭代中将这个元素返回给用户。

然而因为增量式命令仅仅使用游标来记录迭代状态, 所以这些命令带有以下缺点:

  • 同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责, 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。
  • 如果一个元素是在迭代过程中被添加到数据集的, 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会, 这是未定义的(undefined)。

SCAN 命令每次执行返回的元素数量

增量式迭代命令并不保证每次执行都返回某个给定数量的元素。

增量式命令甚至可能会返回零个元素, 但只要命令返回的游标不是 0 , 应用程序就不应该将迭代视作结束。

不过命令返回的元素数量总是符合一定规则的, 在实际中:

  • 对于一个大数据集来说, 增量式迭代命令每次最多可能会返回数十个元素;
  • 而对于一个足够小的数据集来说, 如果这个数据集的底层表示为编码数据结构(encoded data structure,适用于是小集合键、小哈希键和小有序集合键), 那么增量迭代命令将在一次调用中返回数据集中的所有元素。

最后, 用户可以通过增量式迭代命令提供的 COUNT 选项来指定每次迭代返回元素的最大值。

COUNT 选项

虽然增量式迭代命令不保证每次迭代所返回的元素数量, 但我们可以使用 COUNT 选项, 对命令的行为进行一定程度上的调整。

基本上, COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。

虽然 COUNT 选项只是对增量式迭代命令的一种提示(hint), 但是在大多数情况下, 这种提示都是有效的。

  • COUNT 参数的默认值为 10 。
  • 在迭代一个足够大的、由哈希表实现的数据库、集合键、哈希键或者有序集合键时, 如果用户没有使用 MATCH 选项, 那么命令返回的元素数量通常和 COUNT 选项指定的一样, 或者比 COUNT 选项指定的数量稍多一些。
  • 在迭代一个编码为整数集合(intset,一个只由整数值构成的小集合)、 或者编码为压缩列表(ziplist,由不同值构成的一个小哈希或者一个小有序集合)时, 增量式迭代命令通常会无视 COUNT 选项指定的值, 在第一次迭代就将数据集包含的所有元素都返回给用户。

并非每次迭代都要使用相同的 COUNT 值。

用户可以在每次迭代中按自己的需要随意改变 COUNT 值, 只要记得将上次迭代返回的游标用到下次迭代里面就可以了。

http://doc.redisfans.com/key/scan.html

select index 切换数据库

建议使用多个实例,只是用数据库0.因为1个实例多个数据库也是共享1个CPU的.

flushdb 清除当前数据库数据

flushall 清除所有数据库数据

redis 开发与运维 学习心得1的更多相关文章

  1. Redis开发与运维学习笔记

    <Redis开发与运维>读书笔记   一.初始Redis 1.Redis特性与优点 速度快.redis所有数据都存放于内存:是用C语言实现,更加贴近硬件:使用了单线程架构,避免了多线程竞争 ...

  2. Redis开发与运维:SDS

    STRING 我们会经常打交道的string类型,在redis中拥有广泛的使用.也是开启redis数据类型的基础. 在我最最开始接触的redis的时候,总是以为字符串类型就是值的类型是字符串. 比如: ...

  3. Redis实战(七)Redis开发与运维

    Redis用途 1.缓存 Redis提供了键值过期时间设置, 并且也提供了灵活控制最大内存和内存溢出后的淘汰策略. 可以这么说, 一个合理的缓存设计能够为一个网站的稳定保驾护航. 2.排行榜系统 Re ...

  4. Redis 开发与运维

    Getting Start 高性能 性能优势的体现 C语言实现的内存管理 epoll的I/O多路复用技术+IO连接/关闭/读写通过事件实现异步的非阻塞IO TCP协议 单线程架构,不会因为高并发对服务 ...

  5. 《Redis开发与运维》快速笔记(一)

    1.前言&基本介绍 在原始的系统架构中,我们都由程序直接连接DB,随着业务的进一步开展,DB的压力越来越大,为了缓解DB的这一压力,我们引入了缓存,在程序连接DB中加入缓存层, 从而减轻数据库 ...

  6. 《Redis开发与运维》

    第1章 初识Redis 1. Redis介绍: Redis是一种基于键值对(key-value)的NoSQL数据库. 与很多键值对数据库不同的是,Redis中的值可以是由string(字符串).has ...

  7. 《Redis开发与运维》读书笔记

    一.初始Redis 1.Redis特性与优点 速度快.redis所有数据都存放于内存:是用C语言实现,更加贴近硬件:使用了单线程架构,避免了多线程竞争问题 基于键值对的数据结构,支持的数据结构丰富.它 ...

  8. Redis开发与运维

    常用命令 redis-server启动redis redis-server /opt/redis/redis.conf    配置启动 redis-server --port 6379 --dir / ...

  9. Redis开发与运维:linux安装

    Linux 安装 我的系统是inux 系统,官网下载 https://redis.io/download redis-5.0.5.tar.gz 解压: 编译安装: 官网和文档说得已经很清楚了,现在就执 ...

随机推荐

  1. 剑指offer第七章&第八章

    剑指offer第七章&第八章 1.把字符串转换成整数 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 输入描述: 输入一个字符串 ...

  2. UVA11806 Cheerleaders

    题意 PDF 分析 如果要求是某行某列没有石子很好算,就一个组合数. 然后要求某行某列有,就用容斥原理就行了. 时间复杂度\(O(k^2 + 16T)\) 代码 #include<iostrea ...

  3. WPF 自定义消息框(转)

    相信很多人用过MessageBox.show(),是不是觉得这个消息框有点丑呢,反正我是觉得有点丑的,所以我自己重写了一个.先不说,上两幅图对比先: 当然,也不是很好看,不过比原有的好多了. 不多说了 ...

  4. Gixy Nginx 配置分析工具

    项目简介 Gixy 是一款用来分析 Nginx 配置的工具. Gixy 的主要目标是防止安全配置错误,并自动进行缺陷检测. 目前支持的 Python 版本是 2.7 和 3.5+ . 免责声明:Gix ...

  5. Rabbitmq的调度策略

    Rabbitmq的调度策略是指Exchange在收到消息后依据什么规则把消息投到一个或多个队列中保存.它根两个因素相关:Exchange的类型和Exchange和Queue的绑定关系BindingKe ...

  6. gitlab安装、配置与阿里云产品集成

    https://www.ilanni.com/?p=12819 一.gitlab安装与部署 gitlab的安装可以分为源码安装和通过安装包进行安装,要是按照我以前的写作习惯的话,我也会把源码安装在本文 ...

  7. 如何将angular-ui-bootstrap的分页组件封装成一个指令

    准备工作: (1)一如既往的我还是使用了requireJS进行js代码的编译 (2)必须引入angualrJS , ui-bootstrap-tpls-1.3.2.js , bootstrap.css ...

  8. pandas之DateFrame 数据过滤+遍历行+读写csv-txt-excel

    # XLS转CSV df = pd.read_excel(r'列表.xls') df2 = pd.DataFrame()df2 = df2.append(list(df['列名']), ignore_ ...

  9. Ubuntu : 在主机和虚拟机之间传文件

    电脑用的是windows的系统,vmware player打开了一台ubuntu虚拟机,想在它们之间传送文件. 在宿主机上安装FTP文件传输软件 步骤如下: 1.Ubuntu中安装ssh,命令:sud ...

  10. 如何安装nginx第三方模块

    nginx文件非常小但是性能非常的高效,这方面完胜apache,nginx文件小的一个原因之一是nginx自带的功能相对较少,好在nginx允许第三方模块,第三方模块使得nginx越发的强大. 在安装 ...