Redis简介

2023-10-16 14:33:14 浏览数 (1)

Redis,一个开源的数据结构服务器,最近赢得了越来越高的声誉。为什么 Redis 如此受欢迎?是因为Redis具有高度可扩展的架构、它的高性能、适合用于缓存、消息代理、计数器和队列。Redis 在各种场景下的高性能和易用性让它成为 Web 应用程序的首选。

1、Redis起源
1.1、antirez和他的网站

在 2007 年,有个意大利西西里岛的小哥 Salvatore Sanfilippo(antirez) 和朋友创建了一个访客信息网站:LLOOGG.com。这个网站为其他网站提供各种信息的统计(包括访客 Ip、操作系统、浏览器、使用的搜索关键词、所在地区、访问的网页地址等信息)。

而对信息的收集在概念上并不复杂:多个网站把访客信息连续不断的推送到 LLOOGG.COM 服务器,而 LLOOGG.COM 服务器需要为每个网站保存一定数量的最新页面访问记录,并通过网页将这些记录实时地展示给用户观看。

LLOOGG.COM 可以查看最多 10000 条的最新浏览记录。这样的话,它需要为每一个网站创建一个队列,不同网站的访问记录进入到不同的队列。如果队列的长度超过了用户指定的长度,它需要把最早的记录删除。(先进先出)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dx0djxQa-1691983863594)(/Users/liziheng/Library/Application Support/typora-user-images/image-20230812220050402.png)]

随着 LLOOGG.com 的用户越来越多,LLOOGG.com 要维护的列表数量也越来越多,要执行的推入和弹出操作也越来越多。LLOOGG.com 当时使用 MySQL 数据库,而 MySQL 每次执行推入和弹出操作都要进行硬盘写入和读取,程序的性能严重受制于硬盘 I/O 。 最终 LLOOGG.com 所使用的 MySQL 再也没办法在当时的 VPS 上处理新增的大量负载,因为 LLOOGG.com 当时还没有找到盈利模式,所以为了尽量节约开支,antirez 没有选择直接升级 LLOOGG.com 所使用的 VPS ,而是打算另寻 办法,在现有硬件的基础上,通过提升列表操作的性能来解决负载问题。

1.2、Redis的诞生

为了解决 LLOOGG.com 的负载问题,antirez 决定自己写一个具有列表结构的内存数据库原型。这个数据库原型支持O(1) 复杂的推入和弹出操作,并且将数据储存在内存而不是硬盘,所以程序的性能不会受到硬盘 I/O 限制,可以以极快的速度 执行针对列表的推入和弹出操作。于是 antirez 使用C 语言写了这个内存数据库,并给它加上了持久化功能,2009年2月26日Redis(Remote Dictionary Server 远程字典服务)就此诞生!

在最大负载达到每秒数千条页面记录的情况下,无论我使用什么样的数据库模式(schema),无论我如何进行优化,我所使用的关系数据库都没办法在这个小虚拟机上处理如此大的负载。因为囊中羞涩,我没办法对虚拟机进行升级,并且我觉得应该有更简单的方法来处理一个由推入值组成的列表。最终,我决定自己写一个实验性质的内存数据库原型(prototype),这个数据库使用列表作为基本数据类型,并且能够对列表的两端执行常数时间复杂度的弹出(pop)和推入(push)操作。长话短说吧,这个内存数据库的想法的确奏效了,于是我用 C 语言重写了最初的数据库原型,并给它加上了基于子进程实现的持久化特性,Redis 就这样诞生了。 ———— Salvatore Sanfilippo(antirez)

2、Redis概述
2.1、Redis定义

Redis 全称 Remote Dictionary Server(即远程字典服务),它是一个基于内存实现的键值型非关系(NoSQL)数据库,由意大利人 Salvatore Sanfilippo 使用 C 语言编写。

Redis 官网:https://redis.io/

Redis 官网-中文:http://www.redis.cn/

Redis 遵守 BSD 协议,实现了免费开源,其最新版本是 6.20,常用版本包括 3.0 、4.0、5.0。自 Redis 诞生以来,它以其超高的性能、完美的文档和简洁易懂的源码广受好评,国内外很多大型互联网公司都在使用 Redis,比如腾讯、阿里、Twitter、Github 等等。

与 SQL 型数据库截然不同,Redis 没有提供新建数据库的操作,因为它自带了 16 (0—15)个数据库(默认使用 0 库)。在同一个库中,key 是唯一存在的、不允许重复的,它就像一把“密钥”,只能打开一把“锁”。键值存储的本质就是使用 key 来标识 value,当想要检索 value 时,必须使用与 value 相对应的 key 进行查找。

Redis 数据库没有 “表” 的概念,它通过不同的数据类型来实现存储数据的需求,不同的数据类型能够适应不同的应用场景,从而满足开发者的需求。

2.2、Redis特点

常见的内存型数据库,除 Redis 之外,还有 Oracle Berkeley DB(甲骨文旗下的一款产品)、SQlite(轻量级内存数据库)、Memcache(键值型分布式缓存数据库)、Altibase(基于内存的高性能数据库)。

与其他内存型数据库相比,Redis 具有以下特点:

  • Redis 不仅可以将数据完全保存在内存中,还可以通过磁盘实现数据的持久存储;
  • Redis 支持丰富的数据类型,包括 string、list、set、zset、hash 等多种数据类型,因此它也被称为“数据结构服务器”;
  • Redis 支持主从同步,即 master-slave 主从复制模式。数据可以从主服务器向任意数量的从服务器上同步,有效地保证数据的安全性;
  • Redis 支持多种编程语言,包括 C、C 、Python、Java、PHP、Ruby、Lua 等语言。
2.3、Redis的优势

下面对 Redis 的优势进行了简单总结:

  • 性能极高:因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-Value DB;、
  • 可移植性:Redis 使用用标准 C语言编写的,能够在大多数操作系统上运行,比如 Linux,Mac,Solaris 等;
  • 命令提示功能:Redis 客户端拥有强大的命令提示功能,使用起来非常的方便,降低了学习门槛;
  • 多用途工具:Redis 有很多的用途,比如可以用作缓存、消息队列、搭建 Redis 集群等;
  • 多种附加功能:除了上述功能以外,Redis还提供了键过期、发布订阅、事务、流水线、Lua脚本等附加功能。
2.4、Redis的缺点

Redis 基于内存来实现数据的存储,因此其速度非常快。但是我们知道,计算机的内存是非常珍贵的资源,所以 Redis 不适合存储较大的文件或者二进制数据,否则会出现错误,Redis 适合存储较小的文本信息。理论上 Redis 的每个 key、value 的大小不超过 512 MB。

总得来说,上述数据库各有优势,当我们选用数据库时,也要因地制宜,选择一款与业务场景最相符合的数据库。如果在合适的场景使用好 Redis,它就会像一把瑞士军刀一样所向披靡、无往不利!!!

3、Redis应用

简单来说,Redis 在 Java Web 主要有两个应用场景:

  • 存储缓存用的数据
  • 需要高速读写的场合
3.1、存储缓存用的数据

在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:93:7,所以需要读的可能性是比写的可能大得多的。当我们使用 SQL 语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。

如果我们把数据放在 Redis 中,既直接放在内存之中,让服务端直接去读取内存中的数据,那么这样速度明显就会快上不少,并且会极大减小数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用 Redis 存储一些常用和主要的数据,比如用户登录的信息等。

一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:

  • 业务数据常用吗?命中率如何?如果命中率很低,就没有必要写入缓存;
  • 该业务数据是读操作多,还是写操作多?如果写操作多,频繁需要写入数据库,也没有必要使用缓存;
  • 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没有必要。

在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!

使用 Redis 作为缓存的读取逻辑如下图所示:

从上图我们可以知道以下两点:

  1. 当第一次读取数据的时候,读取 Redis 的数据就会失败,此时就会触发程序读取数据库,把数据读取出来,并且写入 Redis 中;
  2. 当第二次以及以后需要读取数据时,就会直接读取 Redis,读到数据后就结束了流程,这样速度就大大提高了。

从上面的分析可以知道,读操作的可能性是远大于写操作的,所以使用 Redis 来处理日常中需要经常读取的数据,速度提升是显而易见的,同时也降低了对数据库的依赖,使得数据库的压力大大减少。

使用 Redis 作为缓存的写入逻辑如下图所示:

从流程可以看出,更新或者写入的操作,需要多个 Redis 的操作,如果业务数据写次数远大于读次数那么就没有必要使用 Redis。

3.2、高速读/写的场合

在如今的互联网中,越来越多的存在高并发的情况,比如天猫双 11、抢红包、抢演唱会门票等,这些场合都是在某一个瞬间或者是某一个短暂的时刻有成千上万的请求到达服务器,如果单纯的使用数据库来进行处理,就算不崩,也会很慢的,轻则造成用户体验极差用户量流失,重则数据库瘫痪,服务宕机,而这样的场合都是不允许的!

所以我们需要使用 Redis 来应对这样的高并发需求的场合,我们先来看看一次请求操作的流程图:

我们来进一步阐述这个过程:

  1. 当一个请求到达服务器时,只是把业务数据在 Redis 上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速响应的需求;
  2. 但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完 Redis 的读/写之后,会去判断该高速读/写的业务是否结束,这个判断通常会在秒杀商品为 0,红包金额为 0 时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将 Redis 的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。
3.2、Redis使用场景总结

Redis 根据使用数据类型的不同,对应的使用场景有很多,例如:

  1. 缓存(String / Hash 类型):缓存如用户信息,视频信息等;
  2. 分布式锁(String 类型):setnx 方法,「key不存在才插入」,可以用它来实现分布式锁;
  3. 计数器(String 类型):incr/decr 方法,自增自减,由于是原子性,可以用来计数统计浏览数、点赞数等;
  4. 限制请求次数(String 类型):也是利用 incr 方法,限制请求次数访问者的 ip 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false;
  5. 数据共享分布式(String 类型):因为 Redis 是分布式的独立服务,可以在多个应用之间共享,所有可以实现需要例如分布式 Session;
  6. 购物车(Hash 类型):类似存储商品信息,大 key 为商家 id,小 key 是商品 id 即 goodsId,value 为该 goodsId 的详细信息;
  7. 消息队列(List / Stream 类型):二者都可以实现消息队列,而 Redis5.0 新增的 Stream,解决了 List 实现的消息队列不能持久化和不能重复消费的问题;
  8. 点赞、踩、收藏(Set 类型):Set 集合无需、不可重复,可以保证一个用户只能点一个赞;
  9. 共同关注(Set 类型):Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等;
  10. 抽奖活动(Set 类型):存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次;
  11. 排行榜(ZSet 类型):有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序,所以可以用作排行榜功能的实现;
  12. 此外利用 Redis 的特殊数据类型也可以实现一些相应的功能:Bit 位运算用来签到统计、HyperLogLogs 统计基数用来百万级网络 UV,还有 GEO 地理位置、用来打车等

0 人点赞