Tianyi's Blog Tianyi's Blog
首页
  • 计算机网络
  • 操作系统
  • 计算机科学
  • Nginx
  • Vue框架
  • 环境配置
  • Java
  • JVM
  • Spring框架
  • Redis
  • MySQL
  • RabbitMQ
  • Kafka
  • Mirror Sites
  • Dev Tools
  • Docker
  • Jenkins
  • Scripts
  • Windows
  • 科学上网
  • 旅行
  • 网站日记
  • 软件
  • 电子产品
  • 杂野
  • 分类
  • 友情链接
GitHub (opens new window)

Tianyi

一直向前,永不停止
首页
  • 计算机网络
  • 操作系统
  • 计算机科学
  • Nginx
  • Vue框架
  • 环境配置
  • Java
  • JVM
  • Spring框架
  • Redis
  • MySQL
  • RabbitMQ
  • Kafka
  • Mirror Sites
  • Dev Tools
  • Docker
  • Jenkins
  • Scripts
  • Windows
  • 科学上网
  • 旅行
  • 网站日记
  • 软件
  • 电子产品
  • 杂野
  • 分类
  • 友情链接
GitHub (opens new window)
  • Java

  • Golang

  • JVM的奇妙世界

  • Spring

  • Spring增强封装

  • Redis

    • Redis迭代演化
    • Redis安装配置
    • Redis数据结构
      • 常用的数据类型
        • string
        • Hash类型
        • List类型
        • Set类型
        • Sorted set 类型
      • 全局命令
      • 理论知识
        • 事务
        • 内存淘汰机制
        • 删除策略
      • 怎么用?
        • 思考的点
      • 整体总结
    • Spring集成Redis组件
    • Spring Cache
    • Redis持久化
    • Bloom Filter
    • Cluster-主从模式
    • Cluster-Sentinel
    • Cluster-三主三从
    • Redis理论知识
  • MySQL

  • RabbitMQ

  • Kafka

  • 分享

  • 后端
  • Redis
tianyi
2024-03-04
目录

Redis数据结构

# 常用的数据类型

常用的数据类型有5个:使用字符串存储的String类型,代表对象的哈希类型,集合的 set 类型,有序序列的 sorted set 类型,列表(它的底层实现是双向队列)。

常用:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)

# string

命令格式 功能 案例
set key value 将key-value缓存redis中 set name dafei
get key 从redis中获取key对应value值 get name
incr key 将key对应value值 + 1 incr age
decr key 将key对应value值-1 decr age
setex key seconds value 将key-value缓存到redis中,seconds 秒后失效 setex sex 10 man
ttl key 查看key存活时间 ttl sex
del key 从redis中删除key del name
setnx key value 如果key已经存,不做任何操作,如果key不存,直接添加 setnx name xiaofei
  • SET stores a string value.
  • SETNX stores a string value only if the key doesn't already exist. Useful for implementing locks.
  • GET retrieves a string value.
  • MGET retrieves multiple string values in a single operation.

使用场景

  • 缓存查询结果,降低数据库的访问压力。例如搜索某个东西的时候,我们可以把查询条件加上固定 id 作为 key ,查询的结果,作为 value。
  • 缓存视频播放数量,使用 redis 作为视频播放数的计数器
  • 共享 session
    • 当我们的服务器做了负载均衡,我们的请求就会发送到不同的服务器上进行处理
    • 当我们的 a 服务器承受的访问压力较大时,此时负载均衡可能将新进来的访问给到 b 服务器。这个时候,用户刷新一次再进行访问,就可能需要重新登录
    • 为了避免这种不正常的情况,我们可以用 redis 将用户的 session 集中管理。在这种模式下,我们只需要保证 redis 的高可用和拓展性就可以保证每次自己的登录信息都是一致的。每次获取用户更新或者查询的信息时,统一从 redis 中获取即可。

# Hash类型

命令格式 功能 案例
hset key field value 将field value对缓存到redis中hash中,键值为key hset user name dafei
hget key field 从key对应hash列表中获取field字段 hget user name
hexists key field 判断key对应的hash列表是否存在 field字段 hexists user age
hdel key field 删除key对应hash列表中field字段 hdel user age
hincrby key field increment 给key对应hash列表中field字段 + increment hincrby user age 10
hlen key 查看key对应的hash列表field的数量 hlen user
hkeys key 获取key对应的hash列表所有的field值 hkeys user
hvals key 获取key对应的hash列表所有的field对应的value值 kvals user
hgetall key 获取key对应的hash列表中所有的field及其对应的value值 hgetall user

使用场景

  • 跟上面的字符串存储的类型是类似的,但是这种方式更利于内部信息的更改操作。

  • 对于登录信息的缓存有两种方案,

    • 第一种方案是将对象的信息转为 json 格式的字符串存在 redis,这就是 string 的字符串的做法。
    • 第二种方式是将 user 对象转换为哈希对象存储。在 redis 里面,这种方式更侧重于修改、更改信息,但是查询操作相对来说更加麻烦

# List类型

我们从操作 list 命令中就可以看到,它里面有 push 和 pop 命令,猜也能猜到,它就是一个队列。

但实际使用跟猜测的还是有一点出入的。当整个列表的元素数量较小,或者是元素的体积较小时,它会采用一种紧凑的结构,叫做压缩列表。当整个列表的元素较大以及数量较多时,它会采用另外一种数据结构,叫做双向链表。

  • 这样做的好处有很多,当整个列表的元素较小,数量较少时,我们采用压缩列表就可以很大的程度上节省空间。
  • 压缩列表的底层实现是:数字加元素内容(非常紧凑的实现方式)

常用的命令

命令格式 功能 案例
rpush key value 从右边往key集合中添加value值 rpush hobby java
lrange key start stop 从左边开始列表key集合,从start位置开始,stop位置结束 lrange hobby 0 -1
lpush key value 从左边往key集合中添加value值 lpush hobby c++
lpop key 弹出key集合中最左边的数据 lpop hobby
rpop key 弹出key集合中最右边的数据 rpop hobby
llen key 获取列表长度 llen hooby
  • 可以用来存储用户收藏文章的列表,以及关注人列表等等。一些比较多增删改的地方

# Set类型

Set集合是String类型的无序集合,set是通过HashTable实现的,对集合我们可以取交集、并集、差集。

常用的命令

命令格式 功能 案例
sadd key members [....] 往key 集合中添加member元素 sadd myset a b c
smembers key 遍历key集合中所有的元素 smembers myset
srem key members [....] 删除key集合中members元素 srem myset a
spop key count 从key集合中随机弹出count个元素 spop myset 1
  • 去重(set 集合自带的特性)
  • 抽奖(pop随机抽取)

# Sorted set 类型

Sorted set 也称Zset类型,是一种具有排序效果的set集合。它跟set集合一样也是 string 类型元素的集合,且不允许重复的成员。并且要求每个元素都会关联一个double 类型的分数。后续可以通过分数来为集合中的成员进行从小到大的排序。

Sorted set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

命令格式 功能 案例
zadd key score member 往key集合中添加member元素,分数为score zadd players 100 a
zincrby key increment member 将key集合中的member元素 分数 + increment zadd players 100 a
zrange key start stop [withscores] 将key集合中的元素按分数升序排列 [显式分数] zrange players 0 -1 withscores
zrevrange key start stop [withscores] 将key集合中的元素按分数降序排列 [显式分数] zrevrange players 0 -1 withscores
zrank key member 返回member元素在key结合中的正序排名 zrank players a
zrevrank key member 返回member元素在key结合中的倒序排名 zrevrank players a
zcard key 返回key集合元素个数 zcard players
  • 排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。
    • 按照新增时间进行排序、按照操作的新增时间对关注人列表进行排序
127.0.0.1:6379> help set

  SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string
1
2
3
4
5
6

# 全局命令

全局命令针对的是所有的key,大部分用来做运维,做管理的

常用的全局key

命令格式 功能 案例
keys pattern 按照pattern 匹配规则,列表redis中所有的key keys xxx:*
exists key 判断key是否存在 exists name
expire key seconds 给key设置过期时间,超时:seconds expire name 10
persist key 取消key过期时间 persist name
select index 切换数据库,默认是第0个,共有【0,15】个 select 0
move key db 从当前数据库将key移动到指定db库 move name 1
randomkey 随机返回一个key randomkey
rename key newkey 将key改名为newkey rename name newname
echo message 打印message信息 echo message
dbsize 查看key个数 dbsize
info 查看redis数据库信息 info
config get * 查看所有redis配置信息 config get *
flushdb 清空当前数据库 flushdb
flushall 清空所有数据库 flushall

# 理论知识

# 事务

Redis事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED

redis 127.0.0.1:6379> GET book-name
QUEUED

redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED

redis 127.0.0.1:6379> SMEMBERS tag
QUEUED

redis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
   2) "C++"
   3) "Programming"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  1. redis 的事务类似于 bash 的指令集,仅代表批量操作
  2. 批量操作一旦开始,其他现成的操作不能在中间插入
  3. 批量操作一旦开始,中间有错误,不会回滚,会继续向下执行

# 内存淘汰机制

  1. LRU (Least Recently Used):最近最少使用算法。根据数据最近被访问的时间来决定哪些数据将被淘汰。当内存空间不足时,将优先淘汰最近最少被访问的数据。
  2. LFU (Least Frequently Used):最不经常使用算法。根据数据被访问的频率来决定哪些数据将被淘汰。当内存空间不足时,将优先淘汰访问频率最低的数据。
  3. Random:随机删除算法。随机选择一些数据项进行删除。这种方法简单粗暴,但无法保证删除的数据是最不重要的。
  4. TTL (Time To Live):生存时间算法。通过设置数据的过期时间来自动淘汰过期的数据。当数据的过期时间到达时,Redis 会自动将其删除。
  5. Maxmemory Policy:根据策略选择淘汰数据。除了以上几种具体的算法外,Redis 还提供了一种灵活的淘汰策略,允许用户根据具体的需求选择淘汰算法。常见的策略包括:
    • volatile-lru:只对设置了过期时间的键使用 LRU 算法进行淘汰。
    • volatile-ttl:只对设置了过期时间的键进行淘汰,删除剩余时间较短的键。
    • volatile-random:只对设置了过期时间的键进行随机淘汰。
    • allkeys-lru:对所有键使用 LRU 算法进行淘汰。
    • allkeys-random:对所有键进行随机淘汰。
    • noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略;

volatile 意味着变化

在 Redis 中,"volatile" 键表示具有过期时间的键,其 TTL(Time To Live)属性会随着时间的推移而变化。

  • allkeys-xxx 表示从所有的键值中淘汰数据,而 volatile-xxx 表示从设置了过期键的键值中淘汰数据。
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "0"
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
127.0.0.1:6379> config set maxmemory-policy volatile-ttl
OK
1
2
3
4
5
6
7
8

# 删除策略

Redis采用了惰性删除和定期删除的策略来处理过期键。在这种策略下,Redis定期扫描只会检查设置了过期时间的键,而不会扫描所有键。过期键的信息会被存储在一个单独的过期字典(expires)中,以避免全盘扫描的情况发生。

Redis每隔一段时间(默认为100毫秒)会随机抽取过期字典中的键,检查它们是否已经过期,并将过期的键删除。通过这种随机扫描的方式,避免了对所有键进行扫描,从而降低了对服务的影响,避免了可能的不可用情况。

对于已经过期但未被扫描的键,当客户端尝试访问这些键时,Redis会检查其过期状态。如果键已经过期,Redis会在获取键的时候将其删除,并返回null值给客户端。

过期字典中的键是指向实际数据库键空间中键对象的指针,而值则是键的过期时间,以毫秒精度的Unix时间戳表示。通过这种方式,过期字典中的键和实际数据库中的键相互对应,避免了重复对象的出现,同时也最大程度地节省了空间。

typedef struct redisDb {
    dict *dict;     //键空间,存放所有的key-value键值对
    dict *expires;  //设置了过期时间的key到它的过期时间的键值对
} redisDb;
1
2
3
4

# 怎么用?

操作技巧:spring-data-redis api方法名是redis命令的全称

# 思考的点

  1. 该功能点是否需要用缓存?
  2. 直接使用一个 map 能否解决问题?
  3. 设计 redis 的key value
    • 需要排序吗?
    • 不需要排序,推荐使用 string,利用 json object 完成数据存储

# 整体总结

redis概念,定位,优点,缺点,运用

  • redis 定位是一个高性能的缓存,可以帮助减轻数据库的访问压力
  • 优点是速度快!能够满足高性能高并发下的性能要求,显著地降低数据库的存储与访问压力
  • 缺点是不支持 acid 的特性,缺少一些关系性的维护

常用的数据类型,各种命令

我们平常比较常用的数据类型5个,第一个是 string,string 是最简单并且最通用的数据类型,当然,这也是我们平常工作中最常用的数据类型。它可以以文本方式存储字符串、整数以及浮点型的数据,甚至 object 对象也可以存储。第2个是哈希,哈希是用来存储某个特定对象的,类似于字典或者 map,可以将多个键子对存储在一个键里面,适合用来存储对象的属性。第3个是 set,set 就是无序集,它可以用来帮助我们完成去重或者随机抽取的操作。第4个是 sorted set,也叫做 zset,这个集合是根据 score 属性去进行排序的,当我们需要借助 redis 去帮我们完成自动排序,那么我们就需要用到 sorted set。第5个是 list list,它的实现方式有两种,第一个是双向链表,第2个是压缩列表。我们使用的时候只需要理解它是一个队列,并且支持从两端进行元素的插入和删除(仅提供 pop 以及 push api,类似于队列或栈,只能对两端的元素进行操作)

  • 这里需要注意,在List类型中。redis 它这样的设计是为了保证整体的操作性能,并且我们常用的操作也是仅在数据的头和尾进行增删操作,而对中间元素的增删操作比较少见。所以 redis 更倾向于优化对数据的头尾元素的操作,是为了提高整体的性能效率
  • 很多命令我们不知道的可以直接从 redis 里面拿到,其实跟我们 api 里面的操作是非常类似的

redis 全局命令

redis-cli -h 127.0.0.1

redis-cli -h 127.0.0.1 -a test123
1
2
3
dbsize

keys *
keys aa?

del key

expire key 5
ttl key
说明: >=0:表示剩余的过期时间 -1:不存在过期时间(持久存在) -2:找不到这个键,过期了或者不存在
1
2
3
4
5
6
7
8
9
10
完善页面 (opens new window)
Redis安装配置
Spring集成Redis组件

← Redis安装配置 Spring集成Redis组件→

最近更新
01
JDK
02-23
02
BadTasteCode && 优化
09-11
03
Gradle 实践操作指南及最佳实践
09-11
更多文章>
Theme by Vdoing | Copyright © 2021-2025 Tandy | 粤ICP备2023113440号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式