记得点赞+关注呦。
更多更好的文章,请关注公众号【蘑菇睡不着】,里面有知识点干货以及刷题相关的分享。
前言
在 Redis 最重要最基础就属 它丰富的数据结构了,Redis 之所以能脱颖而出很大原因是他数据结构丰富,可以支持多种场景。并且 Redis 的数据结构实现以及应用场景在面试中是相当常见的,接下来就和大家聊聊 Redis 的数据结构。
Redis数据结构有:string、list、hash、set、sorted set 这五个是大家都知道的,但Redis还有更高级得数据结构,比如:HyperLogLog、Geo、BloomFilter 这几个数据结构,接下来聊聊Redis得这些数据结构吧。
String
基本概念:String 是 Redis 最简单最常用的数据结构,也是 Memcached 唯一的数据结构。在平时的开发中,String 可以说是使用最频繁的了。
底层实现:
- 如果一个字符串对象保存的是整数值, 并且这个整数值可以用 long 类型来表示, 那么字符串对象会将整数值保存在字符串对象结构的 ptr 属性里面(将 void* 转换成 long ), 并将字符串对象的编码设置为 int 。
- 如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度大于 39 字节, 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值, 并将对象的编码设置为 raw。
- 如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度小于等于 39 字节, 那么字符串对象将使用 embstr 编码的方式来保存这个字符串值。
使用:
> redis_cli # 启动redis-cli 客户端
> set hello world # 将键 hello 的值设置为 world
OK # set 命令成功后 会返回 OK
> get hello # 通过 get 命令获取 键为 hello 的值
"world" # 获得到的值
> del hello # 删除键为 hello 的值
(integer) 1 # 返回的是删除的数量
> mset a 10 b 20 c 30 # 批量的设置值
OK
> mget a b c # 批量的返回值
1)"10"
2)"20"
3)"30"
> exists hello # 是否存在该键
(integer) 1 # 1 表示存在,0 表示不存在
> expire hello 10 # 给 hello 设置过期时间,单位,秒
(integer) 1 # 返回1代表成功,0代表key不存在或无法设置过期时间
> pexpire hello 10 # 给 hello 设置过期时间,单位,毫秒
(integer) 1 # 返回1代表成功,0代表key不存在或无法设置过期时间
接下来会重点讲一下 set key value [EX seconds] [PX milliseconds] [NX|XX] 这个一系列命令,这块还是挺重要的,也很容易混淆。
reids 每次对 以前的值覆盖时,会 清空 TLL 值。(TTL 是过期时间)
- EX second:设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。
- PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。
- NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。
- XX :只在键已经存在时,才对键进行设置操作。
# 使用 EX 选项
> set key1 hello EX 1000 # 设置 过期时间 1000s
OK
> ttl hello # 获取 hello 的过期时间
(integer) 1000
# 使用 PX 选项
> set key1 hello PX 1000 # 设置 过期时间 1000ms
OK
> ttl hello # 获取 hello 的过期时间
(integer) 1000
# 使用 NX 选项
> set hello world NX
OK # 键不存在,设置成功
> get hello
"value"
> set hello world NX
(nil) # 键已经存在,设置失败
> get hello
"world" # 维持原值不变
# 使用 XX 选项
> exists hello # 先确定 hello 不存在
(integer) 0
> set hello world XX
(nil) # 因为键不存在,设置失败
> set hello wolrd # 先给 hello 设置一个值
OK
> set hello newWolrd XX
OK # 这回设置成功了
> get hello
"newWorld"
# NX 或 XX 可以和 EX 或者 PX 组合使用
> set hello world EX 1000 NX
OK
> get hello
"world"
> ttl hello
(integer)1000
> set hello wolrd PX 30000 NX
OK
> pttl hello
(integer)30000 # 实际操作中 这个值肯定小于 30000,这次是为了效果才这么写的
# EX 和 PX 可以同时出现,但后面给出的选项会覆盖前面给出的选项
> set hello wolrd EX 1000 PX 30000
OK
> ttl hello
(integer)30 # 这个是 PX 设置的参数,
> pttl hello
(integer)30000
> set number 1
OK
> incr number # 对 number 做自增操作
(integer) 2
在开发过程中,用 redis 来实现锁是很常用的操作。结合 NX 以及 EX 来实现。
> set hello world NX EX 10 # 成功加锁,过期时间是 10s
OK
> set hello wolrd NX EX 10 # 在10s内执行这个命令返回错误,因为上一次的锁还没有释放
(nil)
> del hello # 释放了锁
OK
> set hello world NX EX 10 # 成功加锁,过期时间是 10s
OK
> setnx hello world # 也可以这么写
> setex hello 10 wolrd
锁可以通过设置过期时间以及手动 del 删除来释放锁。
string 的命令比较常用就多介绍了点,下面的命令我就挑重点介绍了。
应用场景:
- 缓存功能:string 最常用的就是缓存功能,会将一些更新不频繁但是查询频繁的数据缓存起来,以此来减轻 DB 的压力。
- 计数器:可以用来计数,通过 incr 操作,如统计网站的访问量、文章访问量等。
List
基本概念: list 是有序可重复列表,和 Java 的 List 蛮像的,查询速度快,可以通过索引查询;插入删除速度慢。