Redis底层与5大数据类型

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
简介: Redis底层与5大数据类型

主页:写程序的小王叔叔的博客欢迎来访👀

支持:点赞收藏关注


什么是Redis

Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的高性能非关系型(NoSQL)的键值对数据库。

与传统数据库不同的是 Redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作。

Redis 是K-V型的数据库,整个数据库都是用字典来存储的,对Redis数据库的任何增删改查操作,实际上就是对字典中的数据进行增删改查

1. 可以存储海量数据,且可以根据键以O(1) 的时间复杂度取出或插入关联值

2. 键值对中键的类型可以是字符串,整型,浮点型等,且键是唯一的.

3. 键值对中的值类型可以是string, hash ,list, set, sorted set.

Redis的应用场景

image.png

计数器

可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

分布式ID生成

利用自增特性,一次请求一个大一点的步长如 incr 2000 ,缓存在本地使用,用完再请求。

海量数据统计

位图(bitmap):存储是否参过某次活动,是否已读谋篇文章,用户是否为会员, 日活统计。

会话缓存

可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

分布式队列/阻塞队列

List 是一个双向链表,可以通过 lpush/rpush 和 rpop/lpop 写入和读取消息。可以通过使用brpop/blpop 来实现阻塞队列。

分布式锁实现

在分布式场景下,无法使用基于进程的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁。

热点数据存储

最新评论,最新文章列表,使用list 存储,ltrim取出热点数据,删除老数据。

社交类需求

Set 可以实现交集,从而实现共同好友等功能,Set通过求差集,可以进行好友推荐,文章推荐。

排行榜

ZSet 可以实现有序性操作,从而实现排行榜等功能。

延迟队列

使用sorted_set,使用 【当前时间戳 + 需要延迟的时长】做score, 消息内容作为元素,调用zadd来生产消息,消费者使用zrangbyscore获取当前时间之前的数据做轮询处理。消费完再删除任务 rem key member。

Redis 安装

1. Docker 安装

#拉取 redis 镜像$ docker pull redis
#运行 redis 容器$ docker run --name myredis -d-p6379:6379 redis
#执行容器中的 redis-cli,可以直接使用命令行操作 redis$docker exec -it myredis redis-cli


2. 源码安装

#拉取 redis 镜像$ docker pull redis
#运行 redis 容器$ docker run --name myredis -d-p6379:6379 redis
#执行容器中的 redis-cli,可以直接使用命令行操作 redis$docker exec -it myredis redis-cli

快速入门

1. string 字符串

string是Redis 使用最广泛,也是最简单的数据结构,Redis所有的key也是string类型,业务系统中通常会把业务数据序列化成一个json 字符串,然后存储到Redis中缓存起来,下次访问的时候,再取出来,反序列化供业务端使用。


可通过 help 查看字符串操作命令
127.0.0.1:6379> help @string since: 2.6.0

常用命令

K-V 缓存:

指定key, value 完成设置于取值操作:
127.0.0.1:6379> set  name guojia
OK
127.0.0.1:6379> get name
"guojia"127.0.0.1:6379> set  some_key some_value
OK
127.0.0.1:6379> get   some_key
"some_value"


如上操作,至少进行了两次网络请求,网络的利用率不高,如果有多个键值对,可以用如下优化

127.0.0.1:6379> mset name1 zhangsan name2 lisi name3 wangwu
OK
127.0.0.1:6379> mget name1 name2 name3
1) "zhangsan"2) "lisi"3) "wangwu"

默认情况下,没有给key设置过期时间,如果配置了持久化的话,数据将永久存在,可以通过设置过期时间,

# 10s 后, name1 将被失效 127.0.0.1:6379> expire name1 10 (integer) 1

数值计算:

127.0.0.1:6379> set readCount 1OK
127.0.0.1:6379> incr readCount
(integer) 2127.0.0.1:6379> decr readCount
(integer) 1127.0.0.1:6379> incrby readCount 10(integer) 11127.0.0.1:6379> decrby readCount 5(integer) 6

位操作(BitMap)

bitmap通常被用来在极小空间消耗下通过位的运算(AND/OR/XOR/NOT)实现对状态的判断、统计,常见的使用场景例如:

1.通过bitmap来记录用户每天应用登录状态,例如用户登录,就SETBIT login:20200514 uid 1,表示用户uid 在20200514这一天登录了,通过BITCOUNT login:20200514可以得到这一天所有登录过的用户数量;通过对两天的记录求AND,可以判断哪个用户连续两天登录了;通过对两天的记录求OR ,可以判断用户两天内登录至少登录了一次的情况。

2.判断用户是否为VIP,用户是否阅读了谋篇文章,观看了某个视频等。

3.连续登陆加积分

4. 指定时间窗口登陆算活跃数

*还可以对String数据类型做部分运算,如修改其中的某一部分,从字符串尾部添加。

2. LIST 列表

操作列表命令查看

$ help @list

Redis的列表数据结构常用来做异步队列使用。一个线程将任务入队到列表中,另一个线程从这个队列轮询数据进行处理。

1. LIST 的操作很多都以 L 或者 R 开头,分别代表压入或弹出数据的方向,L代表左边,R代表右边, 意味着Redis的LIST 数据类型为一个双端链表, 队头和队尾都可以执行数据的压入和弹出。对同一端执行压入和弹出可以很容易实现一个栈的数据结构,对一端执行压入,另一端执行弹出实现的是队列的数据结构。

2. Redis提供了类似数组通过下标取数据的命令 LINDEX, 由于Redis LIST 数据类型底层采用链表实现,时间复杂度为 O(n),在数据量比较大的场景,不建议使用

3. 使用 blpop 实现阻塞队列

127.0.0.1:6379> rpush list1 1 (integer) 1 127.0.0.1:6379> blpop list1 5 # 队列中有值,立即返回 1) "list1" 2) "1" 127.0.0.1:6379> blpop list1 5# 队列中没有数据, 阻塞等待5s 钟,

另开一个窗口

再5s 内,往队列中添加一个数据,阻塞队列被唤醒

127.0.0.1:6379> rpush list1 2 (integer) 1

127.0.0.1:6379> blpop list1 5 1) "list1" 2) "2"

4. LIST 还提供了 LTRIM 的命令,用来截取指定数据段的数据,指定数据段范围外的数据将被删除。通常可以用来做最新数据的获取,如最新文章,最新帖子

3.HASH字典

操作hash命令查看

127.0.0.1:6379> help @hash

Redis的HASH数据结构使用链表来解决HASH 冲突,是一种 数组+ 链表的结构,Redis HASH数据结构的值只能是字符串,当HASH扩容 rehash时,Redis为了提升性能使用的时渐进性 rehash策略。

rehash 会在rehash的同时,保留两个新旧的hash结构,查询时会同时查询两个hash结构,然后再后续的定时任务中以及hash的子指令中,循序渐进地将旧的内容逐步迁移到新得hash结构中。

HASH 通常用于聚合数据,如商品详情页, 数据来源可能多样, 为了减少复杂查询带来的性能损耗,通常直接把第一次查询的结果聚合到HASH中,提升查询速度,保护db,同时减少了分散多个key,对外层key的消耗【 外层key过多,容易导致频繁的rehash,消耗较大的内存】。

主要操作和string比较类似,需要注意的时 hash不能对field 设置过期时间

4.SET 集合

操作set命令查看

127.0.0.1:6379> help @set

1. 这是一个无序且唯一的集合类型数据结构,自带去重功能,可以用来存储具有唯一约束的数据。

127.0.0.1:6379> SADD some_key a a b b c d e    // 往 some_key 中添加元素

(integer) 5

127.0.0.1:6379> SMEMBERS some_key //查询集合中所有元素,无序的数据,且自动去重
1) "c"2) "b"3) "a"4) "d"5) "e"127.0.0.1:6379> SRANDMEMBER some_key 3  // 随机选择 3 个元素
1) "c"2) "a"3) "b"127.0.0.1:6379> SRANDMEMBER some_key 3 // 随机选择 3 个元素
1) "b"2) "d"3) "e"127.0.0.1:6379> SRANDMEMBER some_key 3 // 随机选择 3 个元素
1) "b"2) "d"3) "e"127.0.0.1:6379>

2. 可以对两个集合执行 并集/交集/差集 操作。

127.0.0.1:6379> SADD some_set1 a b c d 
(integer) 4127.0.0.1:6379> SADD some_set2 c d e f 
(integer) 4127.0.0.1:6379> SUNION some_set1 some_set2   // 并集
1) "c"2) "f"3) "a"4) "b"5) "d"6) "e"127.0.0.1:6379> SINTER some_set1 some_set2  // 交集
1) "c"2) "d"127.0.0.1:6379> SDIFF some_set1 some_set2   // 差集, 差集有顺序要求,SDIFF 
1) "b"                                      // 第一个参数为基准,找出在第一个  
2) "a"                                      // 集合中的元素没有在后面集合中
127.0.0.1:6379>                             // 出现过的元素

SDIFF some_set1 some_set2 // 差集, 差集有顺序要求,

SDIFF

1) "b" // 第一个参数为基准,找出在第一个

2) "a" // 集合中的元素没有在后面集合中 127.0.0.1:6379> // 出现过的元素

5.sorted_set/ zset 有序集合

操作zset 命令查看

127.0.0.1:6379> help @sorted_set

ZSET是个有序,且唯一的集合数据类型。可以用来做排行榜,具有时序需求的场景,如基于zset实现一个延迟队列

延迟队列应用场景

如下单后,30分钟内未付款就自动取消订单; 支付后,24小时未评论自动好评

实现逻辑:

1. 生产者生成 延迟消息 序列化后 放入 zset 中

zadd delay_queue now_time_stamp + 5 min task1 zadd delay_queue now_time_stamp + 5 min task2 zadd delay_queue now_time_stamp + 5 min task3

2.用多个线程轮询 zset 获取到期的任务进行处理。

ZRANGEBYSCORE delay_queue 0 now_time_stamp withscores limit 0 1

3. 处理完消息,删除延迟消息

ZREM delay_queue task1

排行榜

127.0.0.1:6379> zadd rank_board 100 a  101 b 99 c 
(integer) 3127.0.0.1:6379> ZRANGE  rank_board 0-11) "c"2) "a"3) "b"127.0.0.1:6379> ZRANGE  rank_board 0-1  withscores
1) "c"2) "99"3) "a"4) "100"5) "b"6) "101"127.0.0.1:6379> ZINCRBY rank_board  1 a     // 如投票. 给指定元素做数值运算
"101"127.0.0.1:6379> ZRANGE  rank_board 0-1  withscores
1) "c"2) "99"3) "a"4) "101"5) "b"6) "101"127.0.0.1:6379> ZINCRBY rank_board  1 a 
"102"127.0.0.1:6379> ZRANGE  rank_board 0-1  withscores
1) "c"2) "99"3) "b"4) "101"5) "a"6) "102"

⚠️注意 ~

💯本期内容就结束了,如果内容有误,麻烦大家评论区指出!

如有疑问❓可以在评论区💬或私信💬,尽我最大能力🏃‍♀️帮大家解决👨‍🏫!

如果我的文章有帮助到您,欢迎点赞+关注✔️鼓励博主🏃,您的鼓励是我分享的动力🏃🏃🏃~


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
SQL 消息中间件 分布式计算
大数据-124 - Flink State 01篇 状态原理和原理剖析:状态类型 执行分析
大数据-124 - Flink State 01篇 状态原理和原理剖析:状态类型 执行分析
66 5
|
1月前
|
消息中间件 分布式计算 NoSQL
大数据-104 Spark Streaming Kafka Offset Scala实现Redis管理Offset并更新
大数据-104 Spark Streaming Kafka Offset Scala实现Redis管理Offset并更新
38 0
|
6天前
|
存储 消息中间件 NoSQL
使用Java操作Redis数据类型的详解指南
通过使用Jedis库,可以在Java中方便地操作Redis的各种数据类型。本文详细介绍了字符串、哈希、列表、集合和有序集合的基本操作及其对应的Java实现。这些示例展示了如何使用Java与Redis进行交互,为开发高效的Redis客户端应用程序提供了基础。希望本文的指南能帮助您更好地理解和使用Redis,提升应用程序的性能和可靠性。
15 1
|
17天前
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
|
26天前
|
存储 消息中间件 NoSQL
Redis 数据类型
10月更文挑战第15天
36 1
|
27天前
|
消息中间件 存储 监控
redis 的List类型 实现 排行榜
【10月更文挑战第8天】
36 2
|
27天前
|
存储 NoSQL Redis
redis-set类型
【10月更文挑战第6天】
36 1
|
1月前
|
存储 NoSQL 大数据
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
32 3
|
16天前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树
|
1月前
|
消息中间件 NoSQL Kafka
大数据-116 - Flink DataStream Sink 原理、概念、常见Sink类型 配置与使用 附带案例1:消费Kafka写到Redis
大数据-116 - Flink DataStream Sink 原理、概念、常见Sink类型 配置与使用 附带案例1:消费Kafka写到Redis
126 0