最近网易面试问到了使用zset取第i个数的指令,没有回答出来😅。写这篇文章来整理一下redis常用的指令,会根据不同的数据类型进行汇总。如果大家有兴趣的话可以自己在这个网站上面尝试使用redis:在线redis指令
String 字符串
基本指令
- 展示所有的key
- 设置key,value
- 获取key对应的value
- 给一个key的值追加内容
- 同时设置多对key value
- 同时获取多个key的值
- 获取value某个区间内的值
- 替换value从某个offset开始的后续内容
> keys * # 展示所有的key
(empty list or set)
> set k1 v1 # 设置一个key value对
OK
> get k1 # 获取k1对应的值
"v1"
> append k1 1 # 对k1的值追加内容"1"
3
> get k1
"v11"
> mset k2 v2 k3 v3 # 设置多个key value对
OK
> mget k2 k3 # 得到多个key的值
1) "v2"
2) "v3"
> getrange k1 1 2 # 得到value对应的范围内的字符串
"11"
> setrange k1 1 2222 # 替换1索引位置之后的部分为"2222"
5
> get k1
"v2222"
拓展功能
- 计数:value除了是字符串,也可以是数字,可以应用在计数器、粉丝量等应用场景下,需要结合
incrby和decrby指令使用:
> set counter 1
OK
> incrby counter 2 # 将counter中的字符串转换为数字并加2
(integer) 3
> decrby counter 1 # 将counter中的字符串转换为数字并减1
(integer) 2
- 对象存储:
> mset user:1:name zhangsan user:1:age 24
OK
- 分布式锁:当key不存在时才能设置key,相当于在并发操作时某一个时刻最多只有一个线程能够设置这个key的值,因此可以设置为分布式锁
- 持有锁的线程宕机了怎么办?这种情况会导致其他线程无法获取锁,因此可以添加一个失效时间,在该线程宕机之后能够通过超时机制释放锁,但是这个过期时间难以准确的设置,过短的话业务逻辑可能没处理完,过长的话可能会导致宕机之后产生的死锁时间长。可以发现过期时间接近业务逻辑的处理时间时才更好,如何设置这个业务逻辑的时间?可以通过看门狗的方式,相当于在持有锁的线程中再记录一个计时器,当时间经过一半之后会自动重新设置过期时间,让它重新开始计时,当宕机之后这个看门狗也会同时挂掉,因此不会自动续约,这样就可以保证一个合理的失效时间。
- 如何保证释放的是自己加的锁?可能线程A释放锁之前,这个锁就过期了,但是线程B已经开始持有这个锁,如果A去释放这个锁的话就会导致A把B的锁的释放,从而产生冲突。在加锁的指令setnx key value,这个value的值会是一个随机数,当释放锁时会判断这个value是否和自己设置的随机数相同,相同的时候才会去释放锁。
- setnx不支持直接设置失效时间需要结合expire指令使用,但是这样操作不能保证原子性,可以采用set ex nx指令set key value ex exp_time nx,该指令是原子的
- 红锁是什么?为了保证redis的高可用,可能会使用redis集群,使其在某些redis实例挂掉的时候也能提供服务,红锁采用主节点过半机制,即获取锁或者释放锁成功的标志为:在过半的节点上操作成功。加锁步骤:参考链接
- 获取当前的时间(单位是毫秒)。
- 使用相同的key和随机值在N个节点上请求锁。这里获取锁的尝试时间要远远小于锁的超时时间,防止某个masterDown了,我们还在不断的获取锁,而被阻塞过长的时间。
- 只有在大多数节点上获取到了锁,而且总的获取时间小于锁的超时时间的情况下,认为锁获取成功了。
- 如果锁获取成功了,锁的超时时间就是最初的锁超时时间进去获取锁的总耗时时间。
- 如果锁获取失败了,不管是因为获取成功的节点的数目没有过半,还是因为获取锁的耗时超过了锁的释放时间,都会将已经设置了key的master上的key删除。
> setnx key value # 不存在key时才设置 set key value when key not exists
List 列表
指令都是以l开头,可以用来实现队列、栈等结构,栈:lpush lpop,队列:rpush lpop
LINDEX, LLEN, LPOP, LPUSH, LRANGE, LREM, LSET, LTRIM, RPOP, RPOPLPUSH, RPUSH,
- list实现栈
- list实现队列
- 得到列表长度
- 获得某个索引对应的元素
- 查看指定索引范围内的元素
- 在指定位置前/后插入元素
- 移除指定值的元素
> lpush mystack 1 2 3 4 # 从左侧依次插入1 2 3 4共4个元素
(integer) 4
> lrange mystack 0 -1 # 查看所有元素
1) "4"
2) "3"
3) "2"
4) "1"
> lpop mystack # 从左侧弹出一个元素
"4"
> lpop mystack
"3"
> rpush myqueue 1 2 3 4 # 从右侧依次插入1 2 3 4共4个元素
(integer) 4
> lrange 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
> lpop myqueue
"1"
> llen myqueue # 查看列表myqueue的长度
(integer) 3
> lindex myqueue 0 # 查看索引0处的元素值
"2"
> lrange myqueue 0 1 # 查看[0,1]范围内的元素值
1) "2"
2) "3"
> linsert myqueue after 2 1 # 在值为2的元素后面插入1
4
> lrange myqueue 0 -1
1) "2"
2) "1"
3) "3"
4) "4"
> lrem myqueue 1 2 # 从左到右移除1个值为2的元素
(integer) 1
> ltrim myqueue 0 1 # 按照索引范围截取列表
OK
> lrange myqueue 0 -1
1) "1"
2) "3"
> lset myqueue 0 3 # 设置索引0处的值为3
OK
Set 集合
无序不重复集合,set中的值不可以重复,命令都是s开头
SADD, SCARD, SDIFF, SDIFFSTORE, SINTER, SINTERSTORE, SISMEMBER, SMEMBERS, SMOVE, SORT, SPOP, SRANDMEMBER, SREM, SUNION, SUNIONSTORE
- 添加一个元素
- 查看某个元素是否存在
- 查看所有的元素
- 查看集合中元素的个数
- 随机抽取指定数量的元素
- 随机删除一个值
- 将元素从集合A移动到集合B
- 两个集合的交集
- 两个集合的并集
- 两个集合的差集
> sadd a 1 2 3 # 向集合a中依次加入元素1 2 3
(integer) 3
> smembers a # 查看集合中的所有元素
1) "1"
2) "2"
3) "3"
> sismember a 1 # 查看1是否存在于a中
(integer) 1
> scard a # 查看集合a的元素个数
3
> srem a 2 # 删除集合a中值为2的元素
1
> srandmember a 1 # 随机获取1个元素
1) "1"
> spop a # 随机删除一个元素
"1"
> sadd b 1 2 3 4
(integer) 4
> sdiff a b # a-b a中有但是b中没有的元素
(empty list or set)
> sdiff b a # b-a b中有但是a中没有的元素
1) "1"
2) "2"
3) "4"
> sinter a b # a和b的交集
1) "3"
> sunion a b # a和b的并集
1) "1"
2) "2"
3) "3"
4) "4"
Hash 哈希
Map集合 <key, map>,本质上还是相当于String类型HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HKEYS, HLEN, HMGET, HMSET, HSET, HVALS
- 创建一个map
- 在map中创建一个kv对
- 在map中创建多个kv对
- 查看map中所有的key
- 查看map中所有的value
- 查看map中所有的kv对
- 查看map中key的数量
- 判断map中某个key是否存在
- 删除map中的某个key
> hmset mymap k1 v1 k2 v2
OK
> hkeys mymap
1) "k1"
2) "k2"
> hvals mymap
1) "v1"
2) "v2"
> hgetall mymap
1) "k1"
2) "v1"
3) "k2"
4) "v2"
> hlen mymap
2
> hexists mymap k1
(integer) 1
> hdel mymap k1
(integer) 1
Zset 有序集合
在set的基础上,增加了一个值(float类型)来表示优先级 set k1 v1 -> zset k1 score1 v1,指令都是以z开头
- 增加元素
- 集合中元素的个数
- 移除元素
- 获取指定score区间内元素的个数
- 从小到大展示
- 从大到小展示
- 获取第i大的元素
> zadd myzset 1 a 2 b 3 c # 加入元素 score在前 value在后
(integer) 3
> zcard myzset # 查看集合中的元素
3
> zrem myzset a # 删除集合中为a的元素
1
> zcount myzset 2 3 # 统计score>=2并且score<=3的元素数量
2
> zrangebyscore myzset -inf inf # 根据score正序输出
1) "b"
2) "c"
> zrangebyscore myzset -inf inf withscores # 根据score正序输出 带有score值
1) "b"
2) 2.0
3) "c"
4) 3.0
> zrevrangebyscore myzset inf -inf # 倒序输出
1) "c"
2) "b"
> zrevrange myzset 0 -1 # 倒序输出
1) "c"
2) "b"
> zrange myzset 0 -1 # 正序输出
1) "b"
2) "c"
> zrange myzset 1 1 # 找到集合中索引为1的元素
1) "c"