命令不区分大小写,而key是区分大小写的
string
- 一个string类型最多存储512MB,
- 对于大部分的字符串操作都是O(1),
- 但是对于substr,getrange,setrange这些对范围进行操作的处理都是O(n),对于大数据会有问题
- 处理结构化的数据,就需要使用hash
set
string类型是二进制安全的,string可以包含任何类型,入jpg或者对象
SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]
1. ex seconds:以秒为单位设置过期时间
2. px milliseconds:以毫秒为单位设置过期时间
3. exat unix-time-second:设置以毫秒为单位的unix时间戳对应的时间为过期时间
4. nx key不存在的时候设置key值
5. xx:key存在的时候设置key值,(相当于堆之前的值进行了一个覆盖)
6. keepttl:保存设置前指定key的生存时间,若key不存在返回nil,继承上之前已经设置好的过期时间
7. get返回指定key原本的值,如果不存在返回nil,先得到原来的值
nx
127.0.0.1:6379> set k1 v1 nx
OK
127.0.0.1:6379> set k1 b2 nx//因为已经存在,所以失效了
(nil)
xx
127.0.0.1:6379> set k1 ca xx
OK
127.0.0.1:6379> set k1 caa xx
OK
127.0.0.1:6379> set k1 caas xx
OK
127.0.0.1:6379> get k1
"caas"
ex time
设置过期时间
127.0.0.1:6379> set k1 v1 ex 12
OK
但是set只要对之前的值进行了修改,就会把原本应该有的超时时间给重新设置成永不超时
一次性处理多个
mset
一次性设置多个
mset k1 v1 k2 v2 k3 v4
msetnx
不存在设置
127.0.0.1:6379> MSETNX k33 v2 k56 6 //不存在才创建成功,只要有一个是存在,就不成功
(integer) 1
mget
获得多个值
127.0.0.1:6379> mget k1 k2 k3 k5
1) "v1"
2) "v2"
3) "v4"
4) (nil)
getrange
获得一个key
的value
的一部分值
getrange key start end
相当于字符串截取
127.0.0.1:6379> set k1 abcdef
OK
127.0.0.1:6379> GETRANGE k1 2 4
"cde"
setrange
设置指定范围的数据
127.0.0.1:6379> SETRANGE k1 1 xxyy
(integer) 6
127.0.0.1:6379> get k1
"axxyyf"
需要强调的是,setrange和getrange的处理都是O(N),可能比较低效,在处理一些大数据的时候可能会出现一些问题
数值增减
这个功能就可以做一个计数器
incr
原子性自增,decr
就是相减,
127.0.0.1:6379> set l1 12
OK
127.0.0.1:6379> INCR l1
(integer) 13
指定增加多少,decrby
指定减多少,这个地方只能自增或者自减一个整数
127.0.0.1:6379> INCRBY l1 4
(integer) 17
incrbyfloat
incrbyfloat l1 1.1
长度追加
append
127.0.0.1:6379> APPEND l1 sdadasd
(integer) 20
127.0.0.1:6379> get l1
"17xxxxsdadasdsdadasd"
分布式锁
setnx key value(不存在就创建)(set if not exist)
setex (set with expire)健秒值,相当于set和expire两个操作进行了合二为一
getset
先get再set,其实就是把set里面进行了一个优化
应用场合
- 比如抖音无限点赞某个视频或者某个商品,点一下加一下(INCR)
- 是否喜欢的文章(incrby命令进行多个增加)
- 一个网页的浏览次数
list
双端链表
的结构,对两端的操作性能很高,通过索引下标的操作中间的节点性能较差(lset lindex linsert
),可以添加元素再左边,也可以添加元素再右边,最多可以包含2^32-1
个元素
- 特点:
单key多value
- 主要功能有
push/pop
一般可以看作一个栈(lpush.lpop)(先进后出),队列(lpush rpop)(先进先出),消息队列(使用的就是作为一个先进先出)的场景下
操作
lpush
(从左往右添加元素),rpush(从右往左添加元素)
lpush(就向一个栈一样从左边进入链表)
127.0.0.1:6379> lpush list1 1 2 3 4 5
rpush
127.0.0.1:6379> rpush list2 1 2 3 4 5//从右边端口进去
lrange
(从左边出),没有rrange
127.0.0.1:6379> LRANGE list1 0 -1// 0 -1全部遍历
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> LRANGE list2 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
- 出队列(删除数据)
lpop
从左边出队列,rpop从右边出队列
127.0.0.1:6379> lpop list2
"1"
lmove
//将ll的数据弹出给work:queue
127.0.0.1:6379> lmove ll work:queue left right
lindex
按照索引下标获得元素
127.0.0.1:6379> LINDEX list1 1
"4"
llen
可以查看列表中的元素个数
127.0.0.1:6379> llen list1
(integer) 3
lrem
删除n个值为给定1的元素,可以进行数量的去重
127.0.0.1:6379> lpush ll 1 2 3 4 1 1 1 1
(integer) 8
127.0.0.1:6379> LREM ll 2 1 //这个是再ll里面删除2个元素值为1
(integer) 2
ltrim
key开始的索引和结束的索引,截取指定范围的值,后再赋值给key(这里的索引值都是从0开始的),相当于是进行截取了一个子串
可以用来创建一个有上限的链表,可以在每次
LPUSH
之后调用LTRIM
127.0.0.1:6379> LRANGE ll 0 -1
1) "11"
2) "11"
3) "1"
4) "1"
5) "1"
127.0.0.1:6379> LTRIM ll 2 4
OK
127.0.0.1:6379> LRANGE ll 0 -1
1) "1"
2) "1"
3) "1"
rpoplpush
将source的数据进行了一个rpop操作,将出去的数据,进行lpush到destination处
RPOPLPUSH l2 ll
lset
将某一个位置的值进行设置
LSET ll 1 c++
127.0.0.1:6379> LRANGE ll 0 -1
1) "12"
2) "c++"
3) "1"
4) "1"
linsert
在某一个值的前面/后面插入一个值
127.0.0.1:6379> LINSERT ll before c++ java
(integer) 5
127.0.0.1:6379> LRANGE ll 0 -1
1) "12"
2) "java"
3) "c++"
4) "1"
5) "1"
blpop
blpush
blmove
这些都是阻塞式的对list进行操作
直到list里面有数据或者设置的超时时间大大才会停止
使用场景
微信公众号订阅消息
如果我关注了两个博主,只要他们发布了新的文章,就会装进我的list中
lpush listarticle:id 11 22
如果我想要查看自己订阅的全部文章,类似分页,下面0-10就是一次显示10条的消息
lrange listarticle:id 0 9
哈希
map<string,map<file,value>>
- hash的绝大部分命令都是O(1)
- hkeys hvals hgetall 这些命令都是O(N),N就是有多少个pair
- 最大存储元素是2^32-1
操作
hset
把数据添加到hash,现在也是可以添加多个filed里面,和hmset没有区别,hget从哈希里面获取需要的元素,hmset 一次性添加多个元素,hmget一次性获得多个元素
127.0.0.1:6379> hset h1 name 12 id 1
(integer) 2
127.0.0.1:6379> hget h1 id
"1"
127.0.0.1:6379> hget h1 name
"12"
127.0.0.1:6379> HMGET h1 id name
1) "1"
2) "12"
* hgetall
遍历hash里面的所有数据
127.0.0.1:6379> HGETALL h1
1) "name"
2) "12"
3) "id"
4) "1"
hdel
删除hash里面的一个元素
127.0.0.1:6379> HDEL h1 name
(integer) 1
127.0.0.1:6379> HGETALL h1
1) "id"
2) "1"
hlen
查看key里面的field个数
127.0.0.1:6379> hlen h1
(integer) 2
hexists
查看一个key中有没有某一个字段
127.0.0.1:6379> HEXISTS h1 id
(integer) 1
127.0.0.1:6379> HEXISTS h1 ll
(integer) 0
hkeys
查看某一个hash里面的所有key
127.0.0.1:6379> hkeys h1
1) "id"
2) "age"
hvals
查看一个hash里面的所有val
127.0.0.1:6379> HVALS h1
1) "1"
2) "12"
hincrby
给某个字段进行增加
127.0.0.1:6379> HINCRBY h1 id 2
(integer) 3
hsetnx
如果不存在就创建,存在就失败
使用场景
淘宝的购物车
//新增商品
hset shop 334488 1 334455 1
//增加商品的数量
hincrby shop 334488 1
//商品的总数
hlen shop
//全部选择
hgetall shop
set
set
的底层是无序的string类型(unordered_set
)的集合,底层使用的是unordered_set,对于set的增删改查操作都是O(1)
单值多value
redis中set最大的存储元素2^32-1
- 集合中的add,remove,sismember操作都是O(1)
- 如果一个集合里面有非常多的元素的时候,在使用
smember
的时候就需要小心- 在运行一个很多元素的集合,就需要使用
SSCAN
,进行对集合进行一个迭代的检索- 对大型数据集,对一个成员存在与否进行检查的时候,如果对精度不是很关心,就可以使用布隆过滤器来处理
操作
sadd
自动进行去重
127.0.0.1:6379> SADD s1 1 1 1 1 2 3
(integer) 3
smembers
遍历set里面的元素,对于元素少的集合可以使用
127.0.0.1:6379> SMEMBERS s1
1) "1"
2) "2"
3) "3"
SSCAN
对于元素多的集合,进行一个迭代式的遍历
迭代器光标从0开始,每一次调用都是O(1),并返回光标给下一次使用
//光标从2开始
127.0.0.1:6379> SSCAN te 2 count 2
1) "0"
2) 1) "1"
2) "2"
3) "3"
sismember
判断某个元素是否在set里面
127.0.0.1:6379> SISMEMBER s1 33
(integer) 0
127.0.0.1:6379> SISMEMBER s1 3
(integer) 1
srem
删除set里面的元素,删除1和2
127.0.0.1:6379> SREM s1 1 2
(integer) 2
scard
统计set里面有多少个元素
127.0.0.1:6379> SCARD s1
(integer) 1
srandmember
随机选几个元素进行展示
127.0.0.1:6379> SRANDMEMBER s1 3con1) "8"
2) "2"
3) "6"
spop
随机从set里面删除一个元素smove
把一个set里面的一个元素迁移到另一个set里面
127.0.0.1:6379> SMOVE s1 s2 3
(integer) 1
127.0.0.1:6379> SMEMBERS s2
1) "c"
2) "d"
3) "a"
4) "v"
5) "3"
-
集合运算
集合A:abc12
集合B:123ax- 差集
A-B
//属于1不属于2的元素 127.0.0.1:6379> SDIFF s1 s2 1) "c" 2) "b" //属于2 不属于1的元素 127.0.0.1:6379> SDIFF s2 s1 1) "3" 2) "x"
- 并集
sunion
127.0.0.1:6379> SUNION s1 s2 1) "3" 2) "a" 3) "2" 4) "b" 5) "1" 6) "c" 7) "x"
- 交集
SINTER
即属于s1,s2
127.0.0.1:6379> SINTER s1 s2 1) "a" 2) "2" 3) "1"
SINTERCARD
计算交集中有几个元素127.0.0.1:6379> SINTERCARD 2 s1 s2 limiT 2 (integer) 2
- 差集
使用场景
- 社交,关注列表,你可能认识的人
- 微信抽奖(随机抽取几个人)
- 跟踪一个项目(有多个少ip地址访问了某一个网站)
- 执行一些集合的运算
ZSET
sorted set可排序的集合,在每个成员前面都有一个double类型的分数,redis就是使用这些分数来堆集合中的成员进行一个从小到大的一个排序,当分数相同时候,就是按照字典序来进行排序
k1 score v1 score v2 …(相当于hash)
可以用作一个排行榜
- 大多数的有序集合操作都是O(logN)
操作
* zadd
实时更新玩家的分数变化
127.0.0.1:6379> ZADD z1 20 v1 12 v2 21 v3
(integer) 3
zrange
遍历
127.0.0.1:6379> ZRANGE z1 0 -1
1) "v2"
2) "v1"
3) "v3"
带分数遍历(这个是从小到大)
127.0.0.1:6379> zrange z1 0 -1 withscores
1) "v2"
2) "12"
3) "v1"
4) "20"
5) "v3"
6) "21"
从大到小进行排序
127.0.0.1:6379> zrevrange z1 0 -1 withscores
1) "v3"
2) "21"
3) "v1"
4) "20"
5) "v2"
6) "12"
zrangebyscores
在某个范围进行排序
127.0.0.1:6379> ZRANGEBYSCORE z1 13 35 withscores
1) "v1"
2) "20"
3) "v3"
4) "21"
//(就是==不包含12
127.0.0.1:6379> ZRANGEBYSCORE z1 (12 90 withscores
1) "v1"
2) "20"
3) "v3"
4) "21"
//从0开始走1步
127.0.0.1:6379> ZRANGEBYSCORE z1 (12 21 withscores limit 0 1
1) "v1"
2) "20"
zscore
获取对应元素的分数
127.0.0.1:6379> zscore z1 v1
"20"
zcard
查看有多少个元素
127.0.0.1:6379> ZCARD z1
(integer) 3
zrem
删除zset里面的元素,删除的是field
127.0.0.1:6379> ZREM z1 v1 v2
(integer) 2
zincrby
给zset里面的一个元素进行增加值
127.0.0.1:6379> ZINCRBY z1 3 v3
"24"
*zcount
计算范围内有几个值
127.0.0.1:6379> ZCOUNT z1 1 21
(integer) 0
* zmpop
从键名列表中的第一个非空排序集中弹出一个或多个元素,他们是成员分数
//把z1中最小的元素进行出栈
127.0.0.1:6379> ZMPOP 1 z1 min count 1
1) "z1"
2) 1) 1) "v1"
2) "1"
//把z1中最打的两个元素进行出栈
127.0.0.1:6379> ZMPOP 1 z1 max count 2
1) "z1"
2) 1) 1) "v3"
2) "3"
2) 1) "v2"
2) "2"
zrank
获得对应的索引值(从小到大进行排序的)
127.0.0.1:6379> zrank z1 four
(integer) 3
zrevrank
从大到小进行一个排序
127.0.0.1:6379> zrevrank z1 four
(integer) 1
使用场景
- 热销的商品
- 热销的主播
- 可以做一个速率限制器,避免过多的API请求
key的操作命令
- 查看所有的redis的key
keys *
- 判断某个key是否存在,返回值就是有几个key存在
EXISTS k1
- 查看key的value,这个就是用来查看string里面的数据
get list
- 查看key的类型
type list
- 删除一个key(原子删除,如果一个key数据非常大,就需要一值在这里的等待,进行删除)
del list
- 非阻塞删除,(删除是不需要等待,进行异步)
比del更好用
UNLINK k1
- 查看还有多少秒这个key过期
-1代表这个key永远不过期,-2代表已经过期
ttl 4
- expire key 给定的key设置过期时间(这个key可以是任何类型)
expire list 4
- 将当前的数据库的key移动到其他的库
move o_key 3//将o_key移动到3号数据库中
- 切换数据库(默认都是使用0号库,但是redis一共有16个仓库)
select 3//切换到3号数据库中
-
flushdb
清空数据库 -
查看key的个数
dbsize
- flushall
通杀所有库