常见面试问题
-
redis有哪些数据类型?
-
redis数据类型的使用场景?
-
常见的redis命令?
-
知道那些高级的redis数据类型?
redis常见数据类型
redis常见的数据结构有String、List、Set、Sorted Set、Hash。
String 常用命令
| 命令 | 描述 |
|---|---|
| SET key value | 设置指定 key 的值 |
| GET key | 获取指定 key 的值。 |
| GETSET key value | 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 |
| SETEX key seconds value | 获取指定 key 的值。 |
| SETNX key value | 只有在 key 不存在时设置 key 的值。 |
| INCR key | 将 key 中储存的数字值增一。 |
| DECR key | 将 key 中储存的数字值减一。 |
String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。 常规key-value缓存应用;常规计数:微博数,粉丝数等。
List 常用命令
| 命令 | 描述 |
|---|---|
| LLEN key | 获取列表长度 |
| LPOP key | 移出并获取列表的第一个元素。 |
| LPUSH key value1 [value2] | 将一个或多个值插入到列表头部。 |
| LRANGE key start stop | 获取列表指定范围内的元素。 |
| RPOP key | 移除列表的最后一个元素,返回值为移除的元素。 |
| RPUSH key value1 [value2] | 在列表中添加一个或多个值。 |
list 就是链表,Redis list 的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的 list 结构来实现。Redis list 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。另外可以通过 lrange 命令,就是从某个元素开始读取多少个元素,可以基于 list 实现分页查询,基于 redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西(一页一页的往下走),性能高。
Set 常用命令
| 命令 | 描述 |
|---|---|
| SADD key member1 [member2] | 向集合添加一个或多个成员 |
| SPOP key | 移除并返回集合中的一个随机元素 |
| SCARD key | 获取集合的成员数。 |
| SISMEMBER key member | 判断 member 元素是否是集合 key 的成员。 |
| SMEMBERS key | 返回集合中的所有成员。 |
| SUNION key1 [key2] | 返回所有给定集合的并集。 |
| SREM key member1 [member2] | 移除集合中一个或多个成员。 |
set 对外提供的功能与list类似是一个列表的功能,特殊之处在于 set 是可以自动排重的。当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。比如:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程,具体命令:sinterstore key1 key2 key3 (将交集存在key1内)
Sorted Set 常用命令
| 命令 | 描述 |
|---|---|
| ZADD key score1 member1 [score2 member2] | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
| ZCARD key | 获取有序集合的成员数 |
| ZRANGE key start stop [WITHSCORES] | 通过索引区间返回有序集合指定区间内的成员。 |
| ZSCORE key member | 返回有序集中,成员的分数值。 |
| ZREM key member [member ...] | 移除有序集合中的一个或多个成员。 |
和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。 举例: 在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息,适合使用 Redis 中的 SortedSet 结构进行存储。
Hash 常用命令
| 命令 | 描述 |
|---|---|
| HDEL key field1 [field2] | 删除一个或多个哈希表字段 |
| HEXISTS key field | 查看哈希表 key 中,指定的字段是否存在。 |
| HGET key field | 获取存储在哈希表中指定字段的值。 |
| HGETALL key | 获取在哈希表中指定 key 的所有字段和值。 |
| HKEYS key | 获取所有哈希表中的字段。 |
| HLEN key | 获取哈希表中字段的数量。 |
| HSET key field value | 将哈希表 key 中的字段 field 的值设为 value 。 |
Hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。 比如我们可以Hash数据结构来存储用户信息,商品信息等等。
redis高级数据类型
redis高级的数据结构有HyperLogLog、geo、bitmaps等。
HyperLogLog 常用命令
| 命令 | 描述 |
|---|---|
| PFADD key element [element ...] | 添加指定元素到 HyperLogLog 中。 |
| PFCOUNT key [key ...] | 返回给定 HyperLogLog 的基数估算值。 |
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
| 命令 | 示例 | 描述 |
|---|---|---|
| geoadd | geoadd cityGeo 22.505285 114.904989 "深圳" | 添加经纬度信息 |
| geopos | geopos cityGeo 深圳 | 查找指定key的经纬度信息 |
GEO功能在Redis3.2版本提供,支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。
bitmaps 常用命令
| 命令 | 示例 |
|---|---|
| SETBIT key offset value | setbit bitmaps_test 10 1 |
| GETBIT key offset | getbit bitmaps_test 10 |
| BITCOUNT key | bitcount bitmaps_test(统计位的值为1的数量) |
严格来说Bitmaps并不是一个新的数据结构,而是一个符合特殊约定的字符串。是set、get等一系列字符串操作的一种扩展,与其不同的是,它提供的是位级别的操作,从这个角度看,我们也可以把它当成是一种位数组、位向量结构。Redis从2.2.0版本开始新增了setbit ,getbit , bitcount等几个bitmap相关命令,我们详细看一下bitmaps是怎么操作的: set bitmaps_test 1
1对应二进制(1对应ASCII码为49,49转换成二进制就是110001)
00110001
getbit bitmaps_test 2 (获取到结果为1)
get bitmaps_test 3 (获取到结果为1)
get bitmaps_test 5 (获取到结果为0)
get bitmaps_test 7 (获取到结果为1)
setbit bitmaps_test 6 1
get bitmaps_test (获取到结果为3,因为我们将第7位改成了1,即00110011,转换成10进制就是51,查询ascii码表可得到它的值位3)
首先bitmap本质是String,String的最大长度为512m,所以它可以表示2^32=4294967296个不同的位。基本不用担心位数不够的问题,就拿最常见的点赞功能,再不需要记录点赞顺序的情况下我们就可以使用bitmap优雅的实现。我们使用不同位对应用户ID,当ID为10000的用户点赞了,给门就可以将offset为10000的位设置为1来标记当前点赞用户。当我们需要统计点赞总数时只需要使用bitcount 统计出所有为1的数即可实现。