主要是命令相关html
1.redis是基于键值对的NoSQL.java
2.redis的值能够是 string, hash, list, set, zset, bitmaps, hyperloglog, georedis
3.redis的值不只能够是字符串还能够是具体的数据结构数据库
4.redis的2种持久方案:rdb和aof.安全
5.redis-server XXX.conf能够以conf的配置启动redis.数据结构
6.redis-cli shutdown能够关闭redis. 不要使用kill -9 杀死redis进程,可能会形成AOF和复制丢失数据的问题.app
1.keys * 能够列出全部键, dbsize返回全部键的总数.dbsize时间复杂度是o(1),keys是o(n).因此键太多的时候不要使用keys *dom
另外实验发现keys 后面*表明任意数量的字符 ?表明单个字符分布式
2.exists查看键是否存在,del删除键,del后面能够跟任意数量的键,好比del a b c .....大数据
3. expire能够设置键过时时间(秒),剩余时间可使用ttl查看.
127.0.0.1:6379> expire abcd -99 //设置负数,直接过时 (integer) 1 127.0.0.1:6379> ttl abcd (integer) -2 // ttl 大于0表示剩余秒, -1表示键没设置过时时间, -2表示键不存在
4.type key能够查看key的数据结构
127.0.0.1:6379> set a 1 OK 127.0.0.1:6379> LPUSH b 1 2 3 4 5 (integer) 5 127.0.0.1:6379> type a string 127.0.0.1:6379> type b list
127.0.0.1:6379> type rrr //不存在的key
none
5.type命令返回的是redis对外的数据结构.每种数据结构对内还有N种内部编码实现.1种内部实现也能够对应N个外部数据结构.
使用object encoding查看内部数据编码
127.0.0.1:6379> set a 1 OK 127.0.0.1:6379> set b 2 OK 127.0.0.1:6379> lpush c 1 2 3 4 (integer) 4 127.0.0.1:6379> OBJECT encoding a "int" 127.0.0.1:6379> OBJECT encoding b "int" 127.0.0.1:6379> OBJECT encoding c "ziplist" 127.0.0.1:6379> set d qqq OK 127.0.0.1:6379> OBJECT encoding d "embstr" 127.0.0.1:6379> set e 99999999999999 OK 127.0.0.1:6379> OBJECT encoding e "int" 127.0.0.1:6379> set f 9999999999999999999999999.9999999999999999999999 OK 127.0.0.1:6379> OBJECT encoding f "raw" 127.0.0.1:6379> set g 123.456 OK 127.0.0.1:6379> OBJECT encoding g "embstr" 127.0.0.1:6379> set h 99999999999999999999999999999999999999999999999 OK 127.0.0.1:6379> OBJECT encoding h "raw"
我以为对于咱们外部其余语言使用redis来讲可能不太关心内部实现而是关心接口返回的外部数据结构..这个有点像java里经过接口引用具体的集合对象..
6.每次客户端调用都经历了发送命令,执行命令,返回结果三个过程.每条命令从客户端到达服务端之后不会被马上执行,全部命令都回进入1个队列中,而后逐个被执行.
1.字符串值不能超过512M
2.实验
127.0.0.1:6379> set k1 abc //set设置值 OK 127.0.0.1:6379> set k2 def ex 999 //ex设置过时秒数,px设置毫秒数 OK 127.0.0.1:6379> ttl k2 (integer) 997 127.0.0.1:6379> set k1 change xx // xx key 存在才更新否则不操做,用于更新 OK 127.0.0.1:6379> get k1 "change" 127.0.0.1:6379> set k1 qqq OK 127.0.0.1:6379> get k1 "qqq" 127.0.0.1:6379> ttl k2 (integer) 957 127.0.0.1:6379> set k3 ttt nx // nx key 不存在才操做,用于插入 OK 127.0.0.1:6379> get k3 "ttt" 127.0.0.1:6379> set k3 www xx OK 127.0.0.1:6379> get k3 "www" 127.0.0.1:6379> set k3 ppp nx // 不存在key,用nx操做. (nil) 127.0.0.1:6379> get k3 "www"
3.setex和setnx的实验
setex key seconds value
setnx key value
setex多了1个seconds不知道为啥
127.0.0.1:6379> exists k1 (integer) 1 127.0.0.1:6379> setnx k1 change //setnx不像set nx返回nil而是返回了操做了0个key (integer) 0 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> exists k2 (integer) 0 127.0.0.1:6379> setnx k2 v2 // 操做成功返回操做了1个key的数量 (integer) 1 127.0.0.1:6379> setnx k2 v22 (integer) 0 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批量操做
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v4 OK 127.0.0.1:6379> mget k1 k2 k3 k4 1) "v1" 2) "v2" 3) "v4" 4) (nil) 127.0.0.1:6379>
5.计数
incr incrby自增,decr decrby自减
127.0.0.1:6379> set k1 NaN OK 127.0.0.1:6379> INCR k1 //不是数字自增报错 (error) ERR value is not an integer or out of range 127.0.0.1:6379> set k2 1 OK 127.0.0.1:6379> incr k2 (integer) 2 127.0.0.1:6379> incr k2 (integer) 3 127.0.0.1:6379> get k2 "3" 127.0.0.1:6379> incrby k2 3 (integer) 6 127.0.0.1:6379> incrby k2 NaN //同incr (error) ERR value is not an integer or out of range 127.0.0.1:6379> incrby k2 -3 // 自增指定数量能够自增负数 (integer) 3 127.0.0.1:6379> decr k1 (error) ERR value is not an integer or out of range 127.0.0.1:6379> decr k2 1 (error) ERR wrong number of arguments for 'decr' command 127.0.0.1:6379> decr k2 (integer) 2 127.0.0.1:6379> decrby k2 2 (integer) 0 127.0.0.1:6379> decrby k2 -9 //同自增 (integer) 9
127.0.0.1:6379> exists k3 (integer) 1 127.0.0.1:6379> del k3 (integer) 1 127.0.0.1:6379> exists k3 (integer) 0 127.0.0.1:6379> incr k3 //操做不存在的key,值直接当成0 (integer) 1 127.0.0.1:6379> del k3 (integer) 1 127.0.0.1:6379> incr k3 3 (error) ERR wrong number of arguments for 'incr' command 127.0.0.1:6379> incrby k3 3 //同incr (integer) 3 127.0.0.1:6379>
127.0.0.1:6379> del k1 (integer) 1 127.0.0.1:6379> del k1 (integer) 0 127.0.0.1:6379> set k1 0.1 OK 127.0.0.1:6379> incr k1 //自增自减只能用于整数 (error) ERR value is not an integer or out of range 127.0.0.1:6379>
6.append追加字符串
127.0.0.1:6379> exists k1 (integer) 1 127.0.0.1:6379> del k1 (integer) 1 127.0.0.1:6379> set k1 hello OK 127.0.0.1:6379> APPEND k1 " world" //返回字符串长度 (integer) 11 127.0.0.1:6379> get k1 "hello world" 127.0.0.1:6379>
127.0.0.1:6379> get k1 "hello world" 127.0.0.1:6379> APPEND k1 "'''" (integer) 14 127.0.0.1:6379> APPEND k1 """" Invalid argument(s) 127.0.0.1:6379> APPEND k1 "\"\"" //追加"能够用/" (integer) 16 127.0.0.1:6379> get k1 "hello world'''\"\"" 127.0.0.1:6379> set k1 "" OK 127.0.0.1:6379> get k1 "" 127.0.0.1:6379> append k1 "" (integer) 0 127.0.0.1:6379> append k1 " Invalid argument(s) 127.0.0.1:6379> append k1 '' (integer) 0 127.0.0.1:6379> append k1 '"' //或者用'"' (integer) 1 127.0.0.1:6379> get k1 "\"" 127.0.0.1:6379> append k1 "'" (integer) 2 127.0.0.1:6379> get k1 "\"'" 127.0.0.1:6379>
7.用strlen返回字符串长度,用getset能够设置新值而且返回本来字符串的值(有多是nil).setrange key offset value能够改变指定位置字符,从0开始计数返回字符串长度
getrange key start end返回substr. 0开始计数,start和end都包括
127.0.0.1:6379> set k1 helloworld OK 127.0.0.1:6379> GETRANGE k1 1 2 "el" 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字节的字符串
127.0.0.1:6379> set k1 9203372036054477800
OK
127.0.0.1:6379> OBJECT encoding k1
"int"
127.0.0.1:6379> set k1 9233372000000000000
OK
127.0.0.1:6379> OBJECT encoding k1
"embstr"
8字节是64位,java里long的范围应该是
-9233372036854477808-9233372036854477808 (https://zhidao.baidu.com/question/256678932.html)
可是不知道为何这里redis彷佛不是
127.0.0.1:6379> set k1 呵 //length=3 OK 127.0.0.1:6379> object encoind k1 (error) ERR Syntax error. Try OBJECT (refcount|encoding|idletime) 127.0.0.1:6379> object encoding k1 "embstr" 127.0.0.1:6379> strlen k1 (integer) 3 127.0.0.1:6379> set k1 呵呵呵呵呵呵呵呵呵呵呵呵呵 //length=39 OK 127.0.0.1:6379> object encoding k1 "embstr" 127.0.0.1:6379> set k1 呵呵呵呵呵呵呵呵呵呵呵呵呵a //40 OK 127.0.0.1:6379> strlenth k1 (error) ERR unknown command 'strlenth' 127.0.0.1:6379> strlen k1 (integer) 40 127.0.0.1:6379> object encoding k1 "raw" 127.0.0.1:6379>
彷佛是1个中文UTF-8占3个字节的缘故
1.
hset key field value
het key field
127.0.0.1:6379> hset k1 f1 v1 (integer) 1 127.0.0.1:6379> hget k1 (error) ERR wrong number of arguments for 'hget' command 127.0.0.1:6379> hget k1 f1 "v1" 127.0.0.1:6379> HGETALL k1 1) "f1" 2) "v1" 127.0.0.1:6379>
2.hdel key field [...field]
127.0.0.1:6379> hset k1 f1 v1 (integer) 1 127.0.0.1:6379> hset k1 f2 v2 (integer) 1 127.0.0.1:6379> hset k1 f3 v3 (integer) 1 127.0.0.1:6379> hdel k1 f1 f2 //返回删除个数 (integer) 2 127.0.0.1:6379> hget k1 (error) ERR wrong number of arguments for 'hget' command 127.0.0.1:6379> hgetall k1 1) "f3" 2) "v3" 127.0.0.1:6379>
3.hlen key返回field的个数
4.hmget field [field....]
hmset key field value [field value...]
批量操做hash
127.0.0.1:6379> hmset k1 f1 v1 f2 v2 f3 v3 OK 127.0.0.1:6379> mhget k1 f1 f2 f3 (error) ERR unknown command 'mhget' 127.0.0.1:6379> hmget k1 f1 f2 f3 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379> HGETALL k1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" 127.0.0.1:6379>
5.
hexists key field 判断field是否存在
127.0.0.1:6379> HEXISTS l1 f1 (integer) 0 127.0.0.1:6379> HEXISTS k1 f1 (integer) 1 127.0.0.1:6379> hget k1 f1 "v1" 127.0.0.1:6379> hget l1 f1 (nil) 127.0.0.1:6379>
6.
hkeys * 获取全部field
hvals获取全部value
hgetall key 获取全部fieldvalue
127.0.0.1:6379> HKEYS k1 1) "f1" 2) "f2" 3) "f3" 127.0.0.1:6379> HVALS k1 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379> HGETALL k1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" 127.0.0.1:6379>
7.
没有hincr命令.hincrby和hincrbyfloat和hstrlen与String的相似
8.
hash的内部编码有ziplist(个数小于512,或者全部值小于64字节),hashtable
一个列表最多能够存储2^32 -1 个元素.
lpush key value [value...]
rpush key value[value...]
127.0.0.1:6379> exists k1 (integer) 1 127.0.0.1:6379> del k1 (integer) 1 127.0.0.1:6379> lpush a b c (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> lpush k1 a b c (integer) 3 127.0.0.1:6379> rpush k1 d e f (integer) 6 127.0.0.1:6379> lrange k1 0 -1 1) "c" 2) "b" 3) "a" 4) "d" 5) "e" 6) "f" 127.0.0.1:6379> lrange k1 2 3 //取下标对应的元素,从0开始 1) "a" 2) "d" 127.0.0.1:6379>
linsert key before|after pivotValue value 在pivotValue以前或者以后插入元素
127.0.0.1:6379> lrange k1 0 -1 1) "c" 2) "b" 3) "a" 4) "d" 5) "e" 6) "f" 127.0.0.1:6379> 127.0.0.1:6379> LINSERT k1 before a 9 (integer) 7 127.0.0.1:6379> lrange k1 0 -1 1) "c" 2) "b" 3) "9" 4) "a" 5) "d" 6) "e" 7) "f" 127.0.0.1:6379> LINSERT k1 after a 8 (integer) 8 127.0.0.1:6379> lrange k1 0 -1 1) "c" 2) "b" 3) "9" 4) "a" 5) "8" 6) "d" 7) "e" 8) "f" 127.0.0.1:6379> lpush k1 a (integer) 9 127.0.0.1:6379> lrange k1 0 -1 1) "a" 2) "c" 3) "b" 4) "9" 5) "a" 6) "8" 7) "d" 8) "e" 9) "f" 127.0.0.1:6379> LINSERT k1 after a 7 //在找到的第一个元素后面添加而后直接return (integer) 10 127.0.0.1:6379> lrange k1 0 -1 1) "a" 2) "7" 3) "c" 4) "b" 5) "9" 6) "a" 7) "8" 8) "d" 9) "e" 10) "f" 127.0.0.1:6379> rINSERT k1 after a 7 //没有rinsert (error) ERR unknown command 'rINSERT' 127.0.0.1:6379>
lindex key index 获取指定位置的元素,负数就是从最后面1个元素开始数
127.0.0.1:6379> lrange k1 0 -1 1) "a" 2) "7" 3) "c" 4) "b" 5) "9" 6) "a" 7) "8" 8) "d" 9) "e" 10) "f" 127.0.0.1:6379> lindex k1 1 "7" 127.0.0.1:6379> lindex k1 -2 //倒数第二个元素 "e" 127.0.0.1:6379>
llen key获取列表元素个数
lpop key和rpop key用于删除元素
lrem key count value找到value之后最多删除count个值为value的元素
count>0才可以左往右删除,<0从右往左,=0所有删除
127.0.0.1:6379> lrange k1 0 -1 1) "a" 2) "7" 3) "c" 4) "b" 5) "9" 6) "a" 7) "8" 8) "d" 9) "e" 10) "f" 127.0.0.1:6379> lrem k1 2 a //2个a都删除了 (integer) 2 127.0.0.1:6379> lrange k1 0 -1 1) "7" 2) "c" 3) "b" 4) "9" 5) "8" 6) "d" 7) "e" 8) "f" 127.0.0.1:6379> lrem k1 8 -1 (integer) 0 127.0.0.1:6379> lrem k1 -1 8 //删除1个8右边开始 (integer) 1 127.0.0.1:6379> lrange k1 0 -1 1) "7" 2) "c" 3) "b" 4) "9" 5) "d" 6) "e" 7) "f" 127.0.0.1:6379> lrem k1 0 e //全部e都删除 (integer) 1 127.0.0.1:6379> lrange k1 0 -1 1) "7" 2) "c" 3) "b" 4) "9" 5) "d" 6) "f" 127.0.0.1:6379>
ltrim key start end 按照索引保留元素
127.0.0.1:6379> exists k1 (integer) 1 127.0.0.1:6379> lrange k1 0 -1 1) "7" 2) "c" 3) "b" 4) "9" 5) "d" 6) "f" 127.0.0.1:6379> LTRIM k1 1 3 OK 127.0.0.1:6379> lrange k1 0 -1 1) "c" 2) "b" 3) "9" 127.0.0.1:6379>
lset key index newValue能够修改index的元素
127.0.0.1:6379> lrange k1 0 -1 1) "c" 2) "b" 3) "9" 127.0.0.1:6379> lset k1 0 a OK 127.0.0.1:6379> lrange k1 0 -1 1) "a" 2) "b" 3) "9" 127.0.0.1:6379> lset k1 99 a (error) ERR index out of range 127.0.0.1:6379>
blpop key [key...] timeout 弹出key最左边的元素,阻塞timeout秒.
brpop同理
127.0.0.1:6379> lrange k1 0 -1 1) "a" 2) "b" 3) "9" 127.0.0.1:6379> blpop k1 9 1) "k1" 2) "a" 127.0.0.1:6379> exists k2 (integer) 1 127.0.0.1:6379> del k2 (integer) 1 127.0.0.1:6379> del k2 (integer) 0 127.0.0.1:6379> blpop k2 9 (nil) (9.02s) 127.0.0.1:6379>
多个key只要有1个能返回就当即返回.
多个客户端同时阻塞,添加元素后.哪一个客户端命令先执行哪一个就先返回,剩下的继续阻塞.
列表的内部实现有ziplist和linkedlist.条件范围同hash
使用场景:
lpush和brpop能够实现消息队列.
集合不容许重复yuansu,zuiduo储存2^32-1个元素.
sadd key element [element...] 新增元素
srem key element [element...] 删除元素
scard key 计算元素个数(居然不是slen...)
smenbers key 返回集合全部元素
127.0.0.1:6379> exists k3 (integer) 1 127.0.0.1:6379> type k3 string 127.0.0.1:6379> get k3 "3vv\n" 127.0.0.1:6379> del k3 (integer) 1 127.0.0.1:6379> sadd k3 e1 e2 e3 e4 (integer) 4 127.0.0.1:6379> srem e2 e5 (integer) 0 127.0.0.1:6379> srem k3 e2 e5 //e2存在 e5不存在 (integer) 1 //成功删除e2返回结果1 127.0.0.1:6379> scard k3 //返回集合元素个数为3 (integer) 3 127.0.0.1:6379> SMEMBERS k3 //查看全部元素 1) "e1" 2) "e4" 3) "e3" 127.0.0.1:6379>
sismenmber key element 判断元素是否在集合内
srandmember key [count] 随机返回count个元素,默认为1
spop 随机弹出1个元素
127.0.0.1:6379> smembers k3 1) "e1" 2) "e4" 3) "e3" 127.0.0.1:6379> sismember k3 e1 //存在元素返回1 (integer) 1 127.0.0.1:6379> sismember k3 e2 //不存在返回0 (integer) 0 127.0.0.1:6379> sismember k3 e1 e2 (error) ERR wrong number of arguments for 'sismember' command 127.0.0.1:6379> sranmember key 1 (error) ERR unknown command 'sranmember' 127.0.0.1:6379> sranmember k3 1 (error) ERR unknown command 'sranmember' 127.0.0.1:6379> srandmember k3 1 //随机返回1个元素不删除 1) "e4" 127.0.0.1:6379> srandmember k3 1 1) "e1" 127.0.0.1:6379> srandmember k3 4 1) "e1" 2) "e4" 3) "e3" 127.0.0.1:6379> spop k3 //随机返回1个元素并删除 "e1" 127.0.0.1:6379> smembers (error) ERR wrong number of arguments for 'smembers' command 127.0.0.1:6379> smembers k3 1) "e4" 2) "e3" 127.0.0.1:6379> spop k3 9 //3.2之后支持 (error) ERR wrong number of arguments for 'spop' command 127.0.0.1:6379>
sinter key [key...] 取交集
sunion key [key...] 取并集
sdiff key [key..] 取差集
sinterstore destination key [keys...]
union和diff同理
127.0.0.1:6379> del k1 k2 k3 (integer) 3 127.0.0.1:6379> sadd k1 1 2 3 4 5 6 7 (integer) 7 127.0.0.1:6379> sadd k2 3 4 5 6 (integer) 4 127.0.0.1:6379> sadd k3 5 6 7 8 9 10 (integer) 6 127.0.0.1:6379> sinter k1 k2 1) "3" 2) "4" 3) "5" 4) "6" 127.0.0.1:6379> sinter k1 k2 k3 1) "5" 2) "6" 127.0.0.1:6379> sinterstore k4 k1 k2 k3 (integer) 2 127.0.0.1:6379> sdiff k1 k2 1) "1" 2) "2" 3) "7" 127.0.0.1:6379> sdiff k1 k2 k3 1) "1" 2) "2" 127.0.0.1:6379> SDIFFSTORE k6 k1 k2 k3 (integer) 2 127.0.0.1:6379>
集合内部使用intset或者hashtable实现
intset为集合全部元素都为整形或者元素小于等于512个时候
hashtable为不知足intset的时候
场景
能够用于用户标签
有序集合保留了集合不能有重复元素的特征,可是能够排序,每一个元素都有个对应的分数做为排序依据(分数能够重复).
zadd key score member [score member...] 添加元素
zcard key 计算元素个数
zscore key member 计算元素的分数
127.0.0.1:6379> del k1 (integer) 1 127.0.0.1:6379> zadd k1 1 e1 2 e2 3 e3 4 e4 5 e5 (integer) 5 127.0.0.1:6379> zcard k1 (integer) 5 127.0.0.1:6379> zscore k1 e3 "3" 127.0.0.1:6379>
zrank key member [member...] 和 zrevrank key member 对元素进行排序输出排序好吗,从0开始
zrem key remember [member...] 对元素进行删除
zincrby key incrememt member 增长成员的分数
127.0.0.1:6379> zrem k1 e2 (integer) 1 127.0.0.1:6379> zrank k1 e1 (integer) 0 127.0.0.1:6379> zrevrank k1 e1 (integer) 3 127.0.0.1:6379> ZINCRBY k1 99 e1 "100" 127.0.0.1:6379> zrevrank k1 e1 (integer) 0 127.0.0.1:6379> zrank k1 e1 (integer) 3 127.0.0.1:6379>
zrange key start end [withscores] 低到高排序输出start-end的元素
zrevrange key start end [withscores] 高到低排序输出元素
127.0.0.1:6379> zrange k1 0 -1 // 输出全部元素 -1是最后1个 0是第一个 1) "e3" 2) "e4" 3) "e5" 4) "e1" 127.0.0.1:6379> zrange k1 0 0 1) "e3" 127.0.0.1:6379> zrange k1 0 -3 1) "e3" 2) "e4" 127.0.0.1:6379> zrange k1 1 1 1) "e4" 127.0.0.1:6379> zrange k1 0 -1 withscores 1) "e3" 2) "3" 3) "e4" 4) "4" 5) "e5" 6) "5" 7) "e1" 8) "100" 127.0.0.1:6379> zrevrange k1 0 -1 withscores 1) "e1" 2) "100" 3) "e5" 4) "5" 5) "e4" 6) "4" 7) "e3" 8) "3" 127.0.0.1:6379>
zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores] [limit offser count]
返回指定分数范围内的成员
127.0.0.1:6379> zrange k1 0 -1 withscores 1) "e3" 2) "3" 3) "e4" 4) "4" 5) "e5" 6) "5" 7) "e1" 8) "100" 127.0.0.1:6379> 127.0.0.1:6379> zrangebyscore k1 0 999 withscores 1) "e3" 2) "3" 3) "e4" 4) "4" 5) "e5" 6) "5" 7) "e1" 8) "100" 127.0.0.1:6379> zrangebyscore k1 0 +inf withscores //+inf表示无限大 1) "e3" 2) "3" 3) "e4" 4) "4" 5) "e5" 6) "5" 7) "e1" 8) "100" 127.0.0.1:6379> zrangebyscore k1 (3 +inf withscores //默认是[闭区间 (表示开区间 1) "e4" 2) "4" 3) "e5" 4) "5" 5) "e1" 6) "100" 127.0.0.1:6379> zrangebyscore k1 {3 +inf withscores (error) ERR min or max is not a float 127.0.0.1:6379> zrangebyscore k1 [3 +inf withscores //彷佛不能是[ (error) ERR min or max is not a float 127.0.0.1:6379> zrangebyscore k1 3 -inf withscores (empty list or set) 127.0.0.1:6379> zrangebyscore k1 3 2 withscores (empty list or set) 127.0.0.1:6379> ZREVRANGEBYSCORE k1 +inf 0 withscores //reverse的时候先写max再写min 1) "e1" 2) "100" 3) "e5" 4) "5" 5) "e4" 6) "4" 7) "e3" 8) "3" 127.0.0.1:6379> ZREVRANGEBYSCORE k1 (100 0 withscores 1) "e5" 2) "5" 3) "e4" 4) "4" 5) "e3" 6) "3" 127.0.0.1:6379> ZREVRANGEBYSCORE k1 (100 101 withscores (empty list or set) 127.0.0.1:6379>
zcount key min max 返回分数范围内成员个数
zremrangebyzrank key start end 删除元素,按升序
zremrangebyscore key min max 删除元素按分数
127.0.0.1:6379> zcount k1 50 +inf (integer) 1 127.0.0.1:6379> ZRANK k1 0 -1 (error) ERR wrong number of arguments for 'zrank' command 127.0.0.1:6379> zrange k1 0 -1 1) "e3" 2) "e4" 3) "e5" 4) "e1" 127.0.0.1:6379> zrange k1 0 -1 withscores 1) "e3" 2) "3" 3) "e4" 4) "4" 5) "e5" 6) "5" 7) "e1" 8) "100" 127.0.0.1:6379> ZREMRANGEBYRANK k1 0 1 (integer) 2 127.0.0.1:6379> zrange k1 0 -1 withscores 1) "e5" 2) "5" 3) "e1" 4) "100" 127.0.0.1:6379> ZREMRANGEBYSCORE k1 0 5 (integer) 1 127.0.0.1:6379> zrange k1 0 -1 withscores 1) "e1" 2) "100" 127.0.0.1:6379>
zinterstore destnation numkeys key [key...] [weights weight [weight....]] [aggragate sum|min|max] 计算交集
127.0.0.1:6379> del k1 (integer) 1 127.0.0.1:6379> ZADD k1 10 e1 20 e2 30 e3 40 e4 50 e5 (integer) 5 127.0.0.1:6379> del k2 (integer) 1 127.0.0.1:6379> ZADD k2 11 e1 22 e2 33 e3 44 e4 55 e5 (integer) 5 127.0.0.1:6379> zadd k2 66 e6 (integer) 1 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 (integer) 5 127.0.0.1:6379> zrange k1_2 0 -1 1) "e1" 2) "e2" 3) "e3" 4) "e4" 5) "e5" 127.0.0.1:6379> zrange k1_2 0 -1 withscores 1) "e1" 2) "21" 3) "e2" 4) "42" 5) "e3" 6) "63" 7) "e4" 8) "84" 9) "e5" 10) "105" 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.5 1 (integer) 5 127.0.0.1:6379> zrange k1_2 0 -1 withscores //默认是weight都是1,aggregate是sum 1) "e1" 2) "16" 3) "e2" 4) "32" 5) "e3" 6) "48" 7) "e4" 8) "64" 9) "e5" 10) "80" 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.3 //weights写了1个就必须都得写完 (error) ERR syntax error 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.3 1 (integer) 5 127.0.0.1:6379> zrange k1_2 0 -1 withscores 1) "e1" 2) "14" 3) "e2" 4) "28" 5) "e3" 6) "42" 7) "e4" 8) "56" 9) "e5" 10) "70" 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.5 0.5 (integer) 5 127.0.0.1:6379> zrange k1_2 0 -1 withscores 1) "e1" 2) "10.5" 3) "e2" 4) "21" 5) "e3" 6) "31.5" 7) "e4" 8) "42" 9) "e5" 10) "52.5" 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 1 1 aggragate min (error) ERR syntax error 127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 1 1 aggregate min (integer) 5 127.0.0.1:6379> zrange k1_2 0 -1 withscores 1) "e1" 2) "10" 3) "e2" 4) "20" 5) "e3" 6) "30" 7) "e4" 8) "40" 9) "e5" 10) "50" 127.0.0.1:6379>
zunionstore destination numkeys key [key...] [weights weight [weight...]] [aggregate sum|min|max] 计算并集
127.0.0.1:6379> clear 127.0.0.1:6379> zrange k1 0 -1 withscores 1) "e1" 2) "10" 3) "e2" 4) "20" 5) "e3" 6) "30" 7) "e4" 8) "40" 9) "e5" 10) "50" 127.0.0.1:6379> zrange k2 0 -1 withscores 1) "e1" 2) "11" 3) "e2" 4) "22" 5) "e3" 6) "33" 7) "e4" 8) "44" 9) "e5" 10) "55" 11) "e6" 12) "66" 127.0.0.1:6379> zunoin k1_2 2 k1 k2 weights 1 0.5 (error) ERR unknown command 'zunoin' 127.0.0.1:6379> zunion k1_2 2 k1 k2 weights 1 0.5 (error) ERR unknown command 'zunion' 127.0.0.1:6379> zunionstore k1_2 2 k1 k2 weights 1 0.5 (integer) 6 127.0.0.1:6379> zrange k1_2 0 -1 WITHSCORES 1) "e1" 2) "15.5" 3) "e2" 4) "31" 5) "e6" 6) "33" 7) "e3" //e6只有33由于k1里没有,k2 weight是0.5 8) "46.5" 9) "e4" 10) "62" 11) "e5" 12) "77.5" 127.0.0.1:6379>
内部使用ziplist和skiplist.
元素个数小于128而且只都小于64字节时用ziplist不然用skiplist
场景
主要用于排行榜
rename key newKey 重命名键
renamenx key newKey 当newkey不存在的时候才会成功重命名
randomkey 随机返回1个键
127.0.0.1:6379> del k1 k2 (integer) 2 127.0.0.1:6379> mset k1 haha k2 hehe OK 127.0.0.1:6379> mget k1 k2 1) "haha" 2) "hehe" 127.0.0.1:6379> rename k1 k2 OK 127.0.0.1:6379> exists k1 (integer) 0 127.0.0.1:6379> exists k2 (integer) 1 127.0.0.1:6379> get k2 "haha" 127.0.0.1:6379> rename k2 k2 //同样的key在3.2如下版本会boom (error) ERR source and destination objects are the same 127.0.0.1:6379> keys * 1) "e" 2) "k2" 3) "b" 4) "k4" 5) "f" 6) "h" 7) "k6" 8) "k3" 9) "d" 10) "g" 11) "k1_2" 12) "c" 13) "a" 127.0.0.1:6379> RANDOMKEY "k4" 127.0.0.1:6379> RANDOMKEY "k4" 127.0.0.1:6379> RANDOMKEY "a" 127.0.0.1:6379> RANDOMKEY "k4" 127.0.0.1:6379> RANDOMKEY "b" 127.0.0.1:6379>
expire key seconds 设置X秒后键过时,负数直接删除
expireat key timestamp 在秒级时间戳后x后过时
ttl key 返回键的剩余过时秒数
persist 清除键过时时间
127.0.0.1:6379> exists k2 (integer) 1 127.0.0.1:6379> ttl k2 (integer) -1 // -1不过时 127.0.0.1:6379> expire k2 999 (integer) 1 127.0.0.1:6379> ttl k2 (integer) 997 127.0.0.1:6379> PERSIST k2 //永不过时 (integer) 1 127.0.0.1:6379> ttl k2 (integer) -1 127.0.0.1:6379> get k2 "haha" 127.0.0.1:6379> del k2 (integer) 1 127.0.0.1:6379> ttl k2 (integer) -2 // -2键不存在 127.0.0.1:6379>
pexpire key milliseconds 设置键X毫秒后捡国旗
pexpireat key milliseconds-timestamp 在毫秒级时间戳X后键过时
set会去除过时时间
127.0.0.1:6379> set k1 heihei ex 999 OK 127.0.0.1:6379> get k1 "heihei" 127.0.0.1:6379> ttl k1 (integer) 994 127.0.0.1:6379> ttl k1 (integer) 993 127.0.0.1:6379> set k1 wahaha OK 127.0.0.1:6379> ttl k1 (integer) -1 // 时间被清除了 127.0.0.1:6379>
redis不支持对二级数据结构作过时时间设置
setex命令是原子执行的
move能够在redis内部数据库进行键迁移
127.0.0.1:6379> select 0 OK 127.0.0.1:6379> get k1 "wahaha" 127.0.0.1:6379> move k1 1 (integer) 1 127.0.0.1:6379> exists k1 (integer) 0 127.0.0.1:6379> select 1 OK 127.0.0.1:6379[1]> keys * 1) "k1" 127.0.0.1:6379[1]> get k1 "wahaha" 127.0.0.1:6379[1]>
dump key 将值序列化
restore key ttl value 将值反序列化到数据库中
127.0.0.1:6379> exists k1 (integer) 1 127.0.0.1:6379> type k1 string 127.0.0.1:6379> dump l1 (nil) 127.0.0.1:6379> dump k1 "\x00\x06wahaha\x06\x00\xd7\x03\xb2\xb3I5\xd9\xc7" 127.0.0.1:6379>
127.0.0.1:6380> RESTORE k1 0 "\x00\x06wahaha\x06\x00\xd7\x03\xb2\xb3I5\xd9\xc7" OK 127.0.0.1:6380> get k1 "wahaha" 127.0.0.1:6380>
migrate host port key| "" destination-db timeout [copy] [replace] [keys key [key ...]] 在redis以前迁移数据,migrate命令具备原子性
127.0.0.1:6379> keys * 1) "e" 2) "b" 3) "k4" 4) "k1" 5) "f" 6) "h" 7) "k6" 8) "k3" 9) "d" 10) "g" 11) "k1_2" 12) "c" 13) "a" 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 (error) ERR syntax error 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 (error) ERR syntax error 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 (error) ERR syntax error 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 (error) ERR syntax error 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 (error) ERR When using MIGRATE KEYS option, the key argument must be set to the empty string 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 //不要忘记写"" OK 127.0.0.1:6379>
127.0.0.1:6380> keys * 1) "k1_change" 127.0.0.1:6380> del k1_change (integer) 1 127.0.0.1:6380> keys * (empty list or set) //等待6379迁移数据过来 127.0.0.1:6380> keys * 1) "k4" 2) "c" 3) "b" 4) "k3" 5) "e" 6) "a" 7) "k6" 8) "k1_2" 9) "h" 10) "d" 11) "k1" 12) "f" 13) "g" 127.0.0.1:6380>
不知道为何我1个redis实例不一样数据库之间迁移不行,我以为多是由于这是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 (error) IOERR error or timeout reading to target instance (1.00s) 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 (error) IOERR error or timeout reading to target instance (3.00s) 127.0.0.1:6379>
迁移命令比较
命令 | 做用域 | 原子性 | 支持多个键 |
move | redis实例内部 | 是 | 否 |
dump+restore | redis实例之间 | 否 | 否 |
migrate | redis实例之间 | 是 | 是 |
keys pattern 遍历键
*表明任意字符
?表明一个字符
[]表明部分匹配,[1,3]表明匹配1,3 [1-10]表明匹配1-10任意数字
\x用来转义
127.0.0.1:6380> exists ka1 (integer) 1 127.0.0.1:6380> keys k[a-z]1 1) "ka1" 127.0.0.1:6380> k?[1-99] (error) ERR unknown command 'k?[1-99]' 127.0.0.1:6380> k?[0-10] (error) ERR unknown command 'k?[0-10]' 127.0.0.1:6380> k?[1-10] (error) ERR unknown command 'k?[1-10]' 127.0.0.1:6380> keys k?[0-99] 1) "ka1" 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,命令返回当前游标值
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 (error) ERR wrong number of arguments for MSET 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 OK 127.0.0.1:6380> scan 0 1) "22" 2) 1) "y" 2) "g" 3) "o" 4) "z" 5) "s" 6) "e" 7) "i" 8) "h" 9) "a" 10) "t" 127.0.0.1:6380> scan 22 1) "7" 2) 1) "b" 2) "j" 3) "k" 4) "q" 5) "d" 6) "m" 7) "r" 8) "n" 9) "p" 10) "x" 11) "f" 127.0.0.1:6380> scan 7 1) "0" 2) 1) "v" 2) "l" 3) "u" 4) "w" 5) "c" 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 清除全部数据库数据