最近仔细的啃了一遍redis的官网文档,虽然已经部分被中文翻译,但前后的内容逻辑缺乏连贯性,内容相对比较独立,不便于新手和初学者阅读。
这里想用更易懂的语言和板块,让大家快速理解官方文档的精髓
文章目录
一、redis概述
相信做后端开发,特别是做java的小伙伴,无论目前手里的项目是否用到redis,都或多或少的听说过它的大名。
首先,我们来看一个场景,来初步感知一下,在什么场合下,会使用到redis。
1. 场景举例——验证码
我们来看一个使用非常频繁的场景:验证码。
这里为了照顾基础比较薄弱的同学,我们一步一步的进行衍生,最后再得出我们想要的结论——即redis的使用场景。
单机模式下验证码的实现
这里我们先从简单的入手,讲讲在单机模式下,我们可以如何实现验证码的功能。
我们先看下网页端是如何从我们的web服务器,获取到验证码的图片信息的
分为两步操作:
- web A(可以理解为浏览器)向web server发送一个获取验证码的请求
- web server将请求放入response的body中,返回给客户端
客户端拿到上述2步骤的信息之后,在网页上展示成图片信息。在这里,我们对response的结构、图片是通过什么样的方式呈现在网页上,这两个问题,我们不做过多的阐述,感兴趣的朋友可以去详细的了解下http协议的相关信息
这里强烈给大家安利一本书,《图解http》,本书也是采用了非常浅显易懂的方式,来讲解了整个http协议的来龙去脉,相信看完会很有收货
好了,现在用户的网页上展示了验证码的图片信息。我们现在假设,用户要做登录操作,那么输入完账号、密码、验证码之后,用户点击提交,这时请求中包含了上述的三种信息,如下图所示:
针对用户名和密码,我们非常容易判断是否合规(包括账号是否存在、密码是否正确),无非就是去后台的数据库(假设我们使用的是mysql数据库)去查一查,看输入是否正确(这里为了方便理解,我们不考虑加密、加盐等措施),如下图所示
好了,我们现在发现了一个问题:我并不知道用户传过来的验证码是否合规呀!
我们再来看下之前用户请求验证码图片的时候,web A与web server的交互过程:
发现问题了没?web server仅仅将图片信息返回给了web A,但是并没有记录返回给web A的图片内容所表示的验证码具体是多少!这里我们修正一下上图的交互过程
- web A给web server发送验证码请求
- web server生成一个随机验证码信息(如“9663”)并存储在服务器的内存中
- 将2中生成的验证信息转化为图片
- 将3中的图片信息放入response的body中,返回给客户端
整个流程如下图所示:
将验证码信息转化为图片,在java中有一个工具类kaptcha,感兴趣的同学可以去详细了解下,这里就不展开叙述了。
而在web server中,我们可以通过HashMap的形式,将验证码的信息存储起来。其中的键为web A的IP地址,value为验证码信息
当然,这并不是一种好的形式,因为不同局域网的IP是有可能冲突的,如192.168..。
这里我们只是针对原理做一个阐述,大家不要过多纠结其实现的漏洞,明白意思即可
接下来我们再来看下,针对web A登录请求的处理
好,到目前为止,我们了解了单机模式下验证码的实现
相信看到这里,有同学应该已经发现:在web客户端请求验证码的时候,直接将验证码图片对应的验证码信息存储在服务器上,这种方式仅仅只适用于单机模式!
单机模式实现的问题
在真正的生产环境中,针对一个系统或者模块,我们肯定不能只部署一台服务器,至少要部署两台。这样在其中一台服务器宕机或者关停的情况下,另一台服务器仍然可以运转,保证系统是可用的。部署的服务器越多,可用性就越强
我们假设改系统后端有两台服务器,结构图如下所示:
我们回顾一下单机模式下,账户登录的请求流程:
- web A发送验证码图片请求到服务器上,服务器返回图片信息
- web B发送账号、密码、验证码信息到服务器上,服务器验证后返回相应结果
这里就出现问题了:如果验证码请求信息发给了web server1,而登录信息又发给了web server2,会出现什么样的问题呢,请看下图:
可以看出,当登录的请求信息发给web server2后,web server2在校验验证码的时候,铁定校验失败,因为它压根就没存!
多实例模式下实现验证码方式的探讨
我们仔细想一下上述方案中,方案的问题本质是什么?
数据没有使用公共存储!
当验证码图片请求到web server1的时候,web server1仅仅将数据存到了自己服务器的内存之中。那我们是不是可以找一个公共的第三方,来存储验证码的信息呢?
答案肯定是可以的,而且最容易想到的,也就是我们可以通过将验证码信息存储到mysql中,便能解决问题。
那我们就可以得出下图:
我们将验证码信息的存储,由web server1的内存放入了mysql中;在登录操作时校验验证码的时候,我们将验证码信息的获取,由从本地内存获取,改为了从mysql中获取。
这样,无论我们增加几个web server,只要保证存储验证码的时候把验证码信息存储在mysql中;校验验证码的时候,从mysql中获取验证码信息数据,那么验证码的功能是不是就都没问题了呢
2. 引出redis
大家仔细考虑下上述我们说的方案,是不是就真的完美无瑕,无可挑剔呢?有没有感觉哪里怪怪的?
这里我先给出结论:验证码信息的存与取,均是通过mysql进行的。在我看来,这里存在一个很大的问题:轻量级的数据,却采取了重量级的存储方式!
大家平时的生活和工作中,会不会有这种一种场景:一些在当时比较有用,需要临时存储的文字,大家是不是会直接打开一个记事本,将文本粘贴进去。(至少笔者是如此(✺ω✺))
在我看来,这些文字就属于轻量级的数据:就在那一时比较有用,过后完全可以抛弃的。而记事本,在我看来就是一种轻量级的存储方式:只有那一时存储一下,不会存到硬盘里,数据没用之后,直接关闭记事本即可。
通过上面的例子,我们可以引申一下:
- 轻量级的数据:在某一段时间内有价值,过后就可以直接删除的;或者该数据的丢失对系统影响不大的
- 轻量级的存储方式:不用一直存储,不用保证数据完备性的存储方式
也不知道笔者是否有说明白这两个概念,我们还是拿验证码举例:
- 一个验证码数据,是否需要一直保存?答案肯定是否定的,在用户验证完之后,验证码数据就没用了——总不能用户一直可以通过这个验证码通过验证,对吧?虽然我们也可以通过代码,在验证后手动将对应验证码删除,但问题是:如果用户就请求了验证码信息,但没有登录,那是不是这些存储的验证码数据就成为了垃圾数据了呢?
- 如果验证码数据丢失,会对系统造成很大影响么?答案也是否定的,大不了用户再重新请求一次验证码信息,再重新登录一次
而我们再看看mysql:
- 除非人为手动删除,否则数据会永久存储
- 如果要存储验证码信息,一般我们会想到的方案,就是建一张表。那如果要存储的是手机验证码信息?邮箱验证码信息?是不是每一个类型的都需要建一张表,或者一张表中需要有字段值来区分不同的验证码类型呢?
这里我先引申出我认为的redis的第一个使用场景:存储轻量级信息!
将mysql替换为redis,如下图所示:
本系列后续会推出一篇文章,专门通过代码来实现本文所述的内容。等大家后续入门redis之后,再通过代码,来体会redis的轻量级信息存储是有多么方便。
这里再提一下,redis由于其高性能,还具备第二个使用场景:缓存数据!
这个使用场景,因为需要入门redis后才更方便的去理解它,在大家入门redis后,笔者会结合代码进行更详细的讲解。
本篇文章大家可以先有一个概念,redis的两个使用场景:轻量级的数据存储和缓存数据
以上redis的两个使用场景,均是笔者自己的总结。可能有比较懂redis的小伙伴会说:还有分布式锁呀!因为redis提供的分布式锁方案,其实到目前为止,并没有一个太完美的解决方案,官方提供的方案其实本身也是有缺陷的(后续笔者会针对这一块进行专门的阐述)。所以笔者更倾向于redis的分布式锁解决方案更像是一个对于极端情况的妥协
二、关于redis的官方描述
这里也放一段关于redis的官方描述,大家看看即可,能理解就理解,不能理解的,等看完本篇专栏后,再回过头来看,也是能理解的
Redis 是完全开源免费的,遵守 BSD 协议,是一个灵活的高性能 key-value 数据结构存储,可以用来作为数据库、缓存和消息队列。
Redis 比其他 key-value 缓存产品有以下三个特点:
Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载到内存使用。
Redis 不仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
Redis 支持主从复制,即 master-slave 模式的数据备份。
这里再说一下开源协议
开源协议
相信大家知道在github和gitee上,有很多其他人分享出来的代码,这些代码,有的本意只是拿来做学术交流,却被人直接拿去牟利;而有的代码,作者并不想限制它的使用范围。针对这种情况,公开的代码有几个常用的开源协议,代码作者可以通过给代码设置不同的协议来限制代码的用途
GPL
这个协议可以说是最严格、最具传染性的协议,目的是让全世界所有的软件都免费、开源,使用了GPL协议项目的产品,都有继续遵守GPL协议的义务
LGPL
如果要商用,仅有引用和使用的权限
如果要做修改,则需把修改后的内容开源
Apache
如果要使用,必须在新软件中注明Apache软件许可协议,注明开源软件的作者信息
如果要做修改,发布时需要进行专门的说明
修改后的代码可以不开源,但是要保留Apache版权声明
BSD、MIT
允许开发者自由的使用、修改、发布开源软件代码,只需保留原作者版权信息
BSD协议的特殊要求:在该协议下的原软件修改再发布,不允许借用该项目原作者进行宣传