Redis的数据结构

文章目录

  • 1、String
    • 常用指令
    • 使用场景
  • 2、 List
    • 常用指令
    • 使用场景
  • 3、Hash
    • 常用命令
    • 使用场景
  • 4、Set
    • 常用命令
    • 使用场景
  • 5、SortSet
    • 常用指令
    • 使用场景
  • 6、Geospatial
    • 常用指令
  • 7、BloomFilter(布隆过滤器)

1、String

字符串类型,可以包含任何数据,最大可以是512MB,内部的实现结构和ArrayList类似,采用内分配冗余的形式,来减少内存的频繁分配(降低CPU压力)
虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 简单动态字符串(simple dynamic string,SDS)。相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。

常用指令

set name Bruce   --存放字符串键值对
mset name Bruce    age 20 --批量存放键值对
SETNX name Bruce   --如果不存在key为name,那么就设置value(分布式锁的原理)
get name   -- 获取key
mget name age  --批量获取key
DEL key -- 删除key
expire key 60 --设置过期时间,单位为秒
INCR key -- 将key中存储的数字加1
DECR key -- 将key中存储的数字减1
INCRBY key 2  --将key中存储的值都加上2
DECRBY key 2 --将key中存储的值都减去2

需要注意的是,尽量避免同时操作大批量的key,比如给所有的key设置过期时间,因为redis是单线程的,如果操作耗费太多时间,会造成redis的假死(暂时不对外提供服务)

使用场景

  1. 不需要持久化的数据或者频繁更新的数据,比如验证码,点赞数
  2. 对象缓存
    可以通过序列化工具类,来缓存java对象,比如将某个对象序列化为json,需要用的时候再取出来,反序列化。常见的使用方式有mybatis二级缓存,接口级别缓存等等。
  3. 使用setnx来实现分布式锁,(使用分布式锁时一定要设置过期时间,防止不能释放锁,造成死锁)
  4. 可以用incr,decr来实现点赞数
  5. 分布式全局id
    在一个大型的系统下,如果涉及到分库分表后,mysql 的自增id,肯定满足不了需要,如果用户量不大,可以每次从redis 这里通过自增获取id,但是如果用户量大,每次都拿肯定会给redis造成压力,可以一次取1000个,放本地缓存里,等用完了再去取。

2、 List

list 即是 链表。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 list 的实现为一个 双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。

常用指令

rpush myList valu5e1 --向 list 的头部(右边)添加元素
rpush myList value2 value3 --向list的头部(最右边)添加多个元素
lpop myList # 将 list的尾部(最左边)元素取出
lpush myList2 value1 --尾插

通过图来解释,理解起来会好一些
Redis的数据结构_第1张图片

使用场景

发布与订阅或者说消息队列、慢查询。

3、Hash

是一个key-value的键值对,和java里的hashMap相似,当数据量较小是采用的是ziphash(默认),当数据量较大时采用hashtable。至于什么转换可以在配置文件进行配置。

hash-max-ziplist-entries 512  //配置当field-value超过512时(合起来1024),使用hashtable编码
                              
hash-max-ziplist-value 64  //配置当key的单个field或value长度超过64时,使用hashtable编码

常用命令

hset hash name bruce --设置值,
hget hash name  -- 获取值
hmset hash name bruce age 18 --批量设置
hmget hash name age --批量获取
hgetall hash 获取key的所有值
hkeys hash 获取hashmap中所有的key
hvals hash 获取hashmap中所有的value

使用场景

可以用于存储系统中对象的数据。

4、Set

set 类似于 Java 中的 HashSet 。Redis 中的 set 类型是一种无序集合,集合中的元素没有先后顺序。当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。

常用命令

127.0.0.1:6379> sadd mySet value1 value2 # 添加元素进去
(integer) 2
127.0.0.1:6379> sadd mySet value1 # 不允许有重复元素
(integer) 0
127.0.0.1:6379> smembers mySet # 查看 set 中所有的元素
1) "value1"
2) "value2"
127.0.0.1:6379> scard mySet # 查看 set 的长度
(integer) 2
127.0.0.1:6379> sismember mySet value1 # 检查某个元素是否存在set 中,只能接收单个元素
(integer) 1
127.0.0.1:6379> sadd mySet2 value2 value3
(integer) 2
127.0.0.1:6379> sinterstore mySet3 mySet mySet2 # 获取 mySet 和 mySet2 的交集并存放在 mySet3 中
(integer) 1
127.0.0.1:6379> smembers mySet3
1) "value2"

使用场景

可以基于 set 轻易实现交集、并集、差集的操作。比如:你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。

5、SortSet

和set很相似,sortedSet是一个有序不重复的列表。SortedSet里面的每个节点都关联了一个权重,用来排序。(集合里的每个节点是唯一的,但是评分却可以是相同的),利用这个特性我们可以利用redis来实现排行榜。也可以很快速的获取到一个区间内的节点。
SortedSet的底层是hash和跳表(一个很典型的数据机构,牺牲空间来换取时间)。hash的作用是存储每个节点和权重,跳表的作用是用来快速获取一个区间里的节点。

常用指令

127.0.0.1:6379> zadd myZset 3.0 value1 # 添加元素到 sorted set 中 3.0 为权重
(integer) 1
127.0.0.1:6379> zadd myZset 2.0 value2 1.0 value3 # 一次添加多个元素
(integer) 2
127.0.0.1:6379> zcard myZset # 查看 sorted set 中的元素数量
(integer) 3
127.0.0.1:6379> zscore myZset value1 # 查看某个 value 的权重
"3"
127.0.0.1:6379> zrange  myZset 0 -1 # 顺序输出某个范围区间的元素,0 -1 表示输出所有元素
1) "value3"
2) "value2"
3) "value1"
127.0.0.1:6379> zrange  myZset 0 1 # 顺序输出某个范围区间的元素,0 为 start  1 为 stop
1) "value3"
2) "value2"
127.0.0.1:6379> zrevrange  myZset 0 1 # 逆序输出某个范围区间的元素,0 为 start  1 为 stop
1) "value1"
2) "value2"

使用场景

需要对数据根据某个权重进行排序的场景。比如在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息。

6、Geospatial

地理位置的缩写,可以表示一个区域的二维坐标,redis提供了经纬度设置,查询,范围查询,距离查询,经纬度hash等操作。

常用指令

geoadd key longitude latitude member [longitude latitude member …]
geoadd 添加地理位置,可以将指定的地理空间位置(经度、纬度、名称)添加到指定的 key 中。
geoadd china:city 116.405285 39.904989 beijing

geopos key member [member …]
geopos 获取指定城市的地理位置经纬度,可以从 key 里返回所有给定地理位置的经纬度。
geopos china:city beijing

geodist key member1 member2 [unit]
geodist 返回两个坐标之间的距离。如果两个位置之间的其中一个不存在,则会返回空值。指定单位的参数 unit 必须是以下单位的其中之一:
m 表示单位为米(默认)
km 表示单位为千米
mi 表示单位为英里
ft 表示单位为英尺
geodist china:city  beijing shanghai km :返回北京和上海之间的距离,单位 km。

georadius key lopngitude latitude radius unit[WITHCOORD] [WITHDIST] [COUNT count] [ASC|DESC]
georadius 以给定的经纬度为中心,返回与中心的距离不超过给定最大距离的所有位置元素。
georadius  china:city 116.405285 39.904989 1100km 找出离北京 1100km 的地方
加上 WITHCOORD 可以返回经纬度
加上 WITHDIST 可以显示到中心的距离
加上 COUNT 可以只返回指定数量结果:COUNT 2 返回两条
加上 ASC 可以按距离升序排序,加上 DESC 可以按距离降序排序

7、BloomFilter(布隆过滤器)

布隆过滤器是一段很长的二进制向量和一系列随机映射函数,用来快速检索一个元素是否在一个集合里。但是他的准确率不是百分之百,有可能判断失误。因此他不适合零失误的场景。
优点:1,支持海量数据场景下,判断元素是否存在。
2,存储空间占用量小,不存储数据本身,存储的是hash值
3,不存储数据本身,可以用来存储加密数据
缺点:不支持计数,同一个元素可以多次插入,而且效果是相同的。

你可能感兴趣的:(redis,数据结构,java)