Redis
基础
什么是Redis
?
Redis
是一个基于 C 语言开发的开源数据库(BSD 许可),被频繁用于分布式缓存,与传统数据库不同的是 Redis
的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,Redis
存储的是 KV 键值对数据。
为了满足不同的业务场景,Redis
内置了多种数据类型实现(比如 String、Hash、Sorted Set、Bitmap)。并且,Redis
还支持事务 、持久化、Lua 脚本、多种开箱即用的集群方案(Redis Sentinel
、Redis Cluster
)。
Redis
没有外部依赖,Linux 和 OS X 是 Redis
开发和测试最多的两个操作系统,官方推荐生产环境使用 Linux 部署 Redis
。
为什么Redis
快?
Redis
基于内存,内存的访问速度是磁盘的上千倍;Redis
基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用;Redis
内置了多种优化过后的数据结构实现,性能非常高。
为什么要用Redis
/缓存?
-
高性能 如果将高频热点数据存入缓存中,在需要读取得时候就可以直接操作缓存而不用访问数据库,操作缓存就是直接操作内存,所以速度相当快
-
高并发 一般像 MySQL 这类的数据库的 QPS 大概都在 1w 左右(4 核 8g) ,但是使用
Redis
缓存之后很容易达到 10w+,甚至最高能达到 30w+(就单机Redis
的情况,Redis
集群的话会更高)。由此可见,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而,我们也就提高了系统整体的并发。 -
此外,如果问到问什么不用本地缓存?可以往微服务项目上代,比如我前台系统和后台系统分别部署在两台服务器上,但是想共用同一套缓存和数据库,那么分布式缓存
redis
就可以轻松满足需求,而本地缓存比如hashMap
显然是无法做到的Redis
除了缓存,还能干啥?分布式锁 : 通过
Redis
来做分布式锁是一种比较常见的方式。通常情况下,我们都是基于Redisson
来实现分布式锁。可限流 :一般是通过
Redis
+ Lua 脚本的方式来实现限流。消息队列 :
Redis
自带的 list 数据结构可以作为一个简单的队列使用。Redis 5.0
中增加的 Stream 类型的数据结构更加适合用来做消息队列。它比较类似于 Kafka,有主题和消费组的概念,支持消息持久化以及 ACK 机制。复杂业务场景 :通过
Redis
以及Redis
扩展(比如Redisson
)提供的数据结构,我们可以很方便地完成很多复杂的业务场景比如通过 bitmap 统计活跃用户、通过 sorted set 维护排行榜。
Redis
数据结构
常见的数据结构有哪些?
5 种基础数据结构 :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset
(有序集合)。
3 种特殊数据结构 :HyperLogLogs
(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。
1.String
String 是 Redis
中最简单同时也是最常用的一个数据结构。
String 是一种二进制安全的数据结构,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(图片的 base64 编码或者解码或者图片的路径)、序列化后的对象。
虽然 Redis
是用 C 语言写的,但是 Redis
并没有使用 C 的字符串表示,而是自己构建了一种 简单动态字符串(Simple Dynamic String,SDS)。相比于 C 的原生字符串,Redis
的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis
的 SDS API 是安全的,不会造成缓冲区溢出。
2.List
许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList
,但是 C 语言并没有实现链表,所以 Redis
实现了自己的链表数据结构。Redis
的 List 的实现为一个 双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
应用场景:
信息流展示
- 举例 :最新文章、最新动态。
- 相关命令 :
LPUSH
、LRANGE
。
消息队列
Redis
List 数据结构可以用来做消息队列,只是功能过于简单且存在很多缺陷,不建议这样做。
相对来说,Redis
5.0 新增加的一个数据结构 Stream
更适合做消息队列一些,只是功能依然非常简陋。和专业的消息队列相比,还是有很多欠缺的地方比如消息丢失和堆积问题不好解决。
3. Hash
Redis
中的 Hash 是一个 String 类型的 field-value(键值对) 的映射表,特别适合用于存储对象,后续操作的时候,你可以直接修改这个对象中的某些字段的值。
Hash 类似于 JDK1.8 前的 HashMap
,内部实现也差不多(数组 + 链表)。不过,Redis
的 Hash 做了更多优化
应用场景:
对象数据存储场景
- 举例 :用户信息、商品信息、文章信息、购物车信息。
- 相关命令 :
HSET
(设置单个字段的值)、HMSET
(设置多个字段的值)、HGET
(获取单个字段的值)、HMGET
(获取多个字段的值)。
4. Set(集合)
Redis
中的 Set 类型是一种无序集合,集合中的元素没有先后顺序但都唯一,有点类似于 Java 中的 HashSet
。当你需要存储一个列表数据,又不希望出现重复数据时,Set 是一个很好的选择,并且 Set 提供了判断某个元素是否在一个 Set 集合内的重要接口,这个也是 List 所不能提供的。
你可以