新公司注册网站,wordpress优雅的暂停,企业网站制作运营,长沙网站建站模板目录 认识Redis分布式系统Redis的特性Redis的应用场景Redis客户端Redis命令 认识Redis 上面一段话是官网给出的对Redis的介绍#xff0c;in-memory data store表明Redis是在内存中存储数据的#xff0c;这和我们接触的其他数据库就有很大的不同#xff0c;比如MySQL#xf… 目录 认识Redis分布式系统Redis的特性Redis的应用场景Redis客户端Redis命令 认识Redis 上面一段话是官网给出的对Redis的介绍in-memory data store表明Redis是在内存中存储数据的这和我们接触的其他数据库就有很大的不同比如MySQL它是将数据存储在磁盘中的但由于MySQL需要与磁盘交互访问速度就比较慢而很多互联网产品又对性能要求比较高这时Redis就可以发挥出它的作用了因为是在内存中存储数据就意味着访问速度远比在磁盘中快极大地提高了程序的性能。
Redis也不是各方面领先于MySQL比如在存储空间上是远小于MySQL的毕竟磁盘的空间要远大于内存
要想存储的数据多访问速度也快就可以考虑将MySQL和Redis结合起来使用因为20%的热点数据能满足80%的访问需求但带来的问题是系统的复杂程度大大提升了而且数据发生修改时还涉及到Redis和MySQL之间的数据同步问题此时Redis被作为cache
Redis的初心就是用来作为一个消息中间件的(消息队列)然而当前很少会直接使用Redis作为消息中间件因为业界有更多更专业的消息中间件使用
为什么要有Redis直接用变量存储不行
在单机程序Redis相对于变量存储数据没有优势可言但在分布式系统中才能发挥威力基于网络可以把自己内存中的变量给别的进程甚至别的主机的进程进行使用
分布式系统
单机架构
如下图是一个单机架构只有一台服务器它负责所有的工作虽然只有一台服务器但现在的硬件非常nice也就意味着一台服务器的性能也很高可以支持非常高的并发和非常大的数据存储所以绝大部分的公司的产品就是这种单机架构 分布式系统的引入
业务进一步增长用户量和数据量都水涨船高一台服务器难以应付如果同一时刻处理的请求多了可能会导致某个硬件资源不够用了即导致服务器处理请求的时间变长甚至于处理出错
而要想解决这个问题无非两种方式第一个是节流在软件上优化但对程序员的水平要求就比较高另一种方式就是引入更多的主机、更多的硬件资源但一台主机的硬件资源是有限的比如就4个内存插槽你也就只能插4条内存条所以就需要引入多台主机此时的系统就可以称为是分布式系统
分布式系统的引入会使得系统的复杂程度会大大提高出现bug的概率也越高则使用的人力成本上也就会越高所以引入分布式是一种无奈之举
应用服务和数据库服务分离
如下图 将应用服务和数据库服务部署在不同的服务器就可以给他们搭配不同的服务器比如应用服务器里面可能会包含很多的业务逻辑可能会吃CPU和内存就采用CPU和内存好的主机而数据服务器需要更大的硬盘空间更快的访问速度就可以配置更大硬盘的主机甚至是SSD硬盘这样就能达到更高的性价比 引入更多的应用服务器节点
如下图应用服务器可能会比较吃CPU和内存如果把CPU和内存吃没了此时应用服务器就顶不住了就需要引入更多的应用服务器来解决上述问题同时也需要引入负载均衡器用户的请求会先到达负载均衡器/网关服务器然后根据负载情况将请求分配给负载相对小的应用服务器尽可能保证每台应用服务器处理的用户请求是均衡的当然这里就会用到负载均衡的相关算法 负载均衡器对于请求量的承担能力是远超过应用服务器的因为负载均衡器就相当于领导负责派发任务而应用服务器则相当于职员负责执行任务。如果出现请求量大到负载均衡器也扛不住了的时候就可以引入更多的负载均衡器即引入多个机房
引入更多的数据库服务器读写分离
如下图当数据量太多一台数据库服务器难以支撑时就需要引入更多的服务器来存储数据而实际的应用场景中读的频率是比写要高的所以一般是一台主服务器多台从服务器主服务器负责写读服务器负责读同时从服务器通过负载均衡的方式让应用服务器进行访问 引入缓存
数据库天然有个问题那就是响应速度是更慢的所以就需要把数据区分“冷热”热点数据存放到缓存中而缓存的访问速度往往比数据要快很多如下图所示
分库分表
当数据量更大时一台服务器已经存不下了就需要多台主机存储同时能对数据库进行进一步的拆分即分库分表。本来一台数据库服务器上有多个数据库(create database)现在引入多台数据库服务器就能每个数据库服务器存储一个或者一部分数据库甚至如果某个表特别大一台主机存不下也可以针对表进行拆分具体分库分表如何实现还要结合实际的业务场景来展开因为业务决定技术。如下图所示 微服务架构
前面的应用服务器里面可能做了很多的业务这就可能导致这个服务器的代码变得非常复杂而为了更方便代码的维护就可以把这样的复杂的服务器拆分成更多的功能更单一的但是更小的服务器同时服务器的种类和数量就增加了如下图所示 注意微服务本质上是在解决人的问题
当应用服务器复杂了就势必需要更多的人来维护当人多了就需要配套的管理把这些人组织好可以划分组织结构分成多个组每个组分别配备领导进行管理分成多个组就需要进行分工而拆分成多组微服务就利于人员的组织结构的分配了
微服务的优势
解决了人的问题 使用微服务可以更方便于功能的复用 可以给不同的服务进行不同的部署
引入微服务付出的代价
系统性能的下降而要想保证性能不下降太多就需要引入更多、更好的硬件资源而拆分出来更多的服务多个功能之间要更依赖网络里通信而如果用的网卡不是很好的那种那网络通信的速度比硬盘还慢 系统复杂程度提高可用性受到影响服务器更多了出现问题的概念就更大了这就需要一系列的手段来保证系统的可用性比如更丰富的监控报警以及配套的运维人员
分布式系统的概念
应用/系统 一个应用就是一个/组服务器程序
模块/组件 一个应用里面有很多个功能每个独立的功能就可以称为是一个模块/组件
分布式 引入多个主机/服务器协调配合完成一系列的工作物理上的多台主机
集群 引入多个主机/服务器协调配合完成一系列的工作逻辑上的多台主机
主/从 分布式系统中一种比较典型的结构多个服务器节点其中一个是主另外的则是从从节点的数据要从主节点这里同步过来
中间件 和业务无关的服务功能更通用的服务比如数据库缓存消息队列
可用性 系统整体可用的时间/总的时间也是一个系统的第一要务
响应时长 衡量服务器的性能越小越好
吞吐 vs 并发 衡量系统的处理请求的能力衡量性能的一种方式
Redis的特性 如上图可以看出Redis是在内存中存储数据的Redis主要是通过键值对的方式来存储组织数据是一种非关系型数据库key都是stringvalue则可以是字符串、哈希表、列表、集合等等 如上图针对Redis的操作可用通过简单的交互式命令进行操作也可以通过一些脚本的方式批量执行一些操作可以带有一些逻辑 如上图Redis提供了一组API可以用C、C和Rust语言在Redis原有的功能基础上再进行扩展即编写动态链接库 如上图为了使Redis存储的数据持久化Redis会把数据存储再硬盘上即内存为主硬盘为辅 如上图Redis作为一个分布式系统的中间件能够支持集群是很关键的这个水平扩展类似于分库分表。 一个Redis能存储的数据是有限的因为内存空间有限就可以引入多台主机部署多个Redis节点每个Redis节点存储数据的一部分 如上图Redis具有高可用特性数据存在冗余/备份Redis自身也是支持主从结构的从节点就相当于主节点的备份了
为什么Redis快
1、Redis数据存在内存中就比访问硬盘的数据库要快很多 2、Redis核心功能都是比较简单的逻辑如比较简单的操作内存的数据结构 3、从网络角度Redis使用了IO多路复用的方式 4、Redis使用的是单线程模型减少了不必要的线程之间的竞争开销因为Redis的核心任务主要是操作内存的数据结构不会吃很多CPU
Redis的应用场景 如上图Redis可以被当作数据库使用虽然在大多数情况下考虑到数据存储优先考虑的是大但是仍然有一些场景考虑的是快比如搜索引擎 如上图Redis存的是部分数据比如热点数据全量数据都是以MySQL为主的哪怕Redis的数据没了还可以从MySQL那里加载回来 如上图Redis可以作为消息队列基于这个可以实现一个网络版本的生产者-消费者模型
如下图在用户浏览某个网站时访问不同的网页负载均衡器有很大的可能将请求打到不同的应用服务器而保存的session的只有一台服务器上有这就会给用户带来不好的体验毕竟要多次重新登录此时有两种方式解决这个问题
1、想办法让负载均衡器把同一个用户的请求始终打到同一台机器上但就不能通过轮询的方式来选择应用服务器而要用userld之类的方式来分配机器 2、把会话单独拎出来放到一台独立的机器上存储Redis Redis客户端
和MySQL一样Redis也是一个客户端-服务器结构的程序它的客户端和服务器可以在同一台主机上也可以在不同主机上
Redis客户端的形态
命令行客户端redis-cli 图形化界面的客户端桌面程序、web程序 基于redis的API自行开发客户端工作中最主要的形态非常类似于MySQL的C语言API和JDBC
Redis命令
get和set命令
set把key和value存储进去 get根据key来获取value set和get也是Redis最核心的两个命令 如下图key和value都是字符串即使没有加“当然加”或’都是可以的 注意Redis中的命令是不区分大小写的 key不存在时会直接返回空 Redis全局命令能够搭配任意一个数据结构来使用的命令
keys命令
keys用来查询当前服务器上匹配的key后面接patternpattern方便查找我们想要的keys类似于Linux中的grep命令 如下图设置下面键值对方便下面的演示 匹配任意一个字符 *匹配0个或多个任意字符 [abcde]只能匹配到a b c d e别的不行相当于给出固定的选项了 [^a]排除a只有a匹配不了其他的都能匹配 [a-b]匹配a-b这个范围内的字符包含两侧边界 注意keys命令的时间复杂度是O(N)所以在生产环境上一般都会禁止使用keys命令尤其是大杀器keys *它会查询出Redis中所有的key。生产环境上的key可能会非常多而Redis是一个单线程的服务器执行keys *的可能性非常长使得Redis服务器被阻塞了就无法给其他客户端提供服务了这样的后果是灾难性的
工作中会涉及到的几种环境
办公环境、开发环境、测试环境、线上环境/生产环境操作线上环境的任何一个设备/程序都要怀着12分的谨慎
exists命令
判断一个或多个key是否存在时间复杂度O(1)返回值key存在的个数redis是按照哈希表的方式来组织的 如上图一次判断多个key比起一次判断一个效率会更高因为redis是一个客户端—服务器结构的程序而客户端与服务端是通过网络进行通信的相对内存而言网络通信很慢所以走一次网络和走多次网络区别很大
del命令
删除指定的key一次可以删除多个时间复杂度O(1)返回值删除掉的key的个数 redis作为缓存时误删了几个数据相对于MySQL而言影响不是很大但如果把所有的数据或者一大半数据一下子干没了影响就大了去了本来redis是帮MySQL负重前行的而redis数据被删了就只能去MySQL中获取数据了很容易把MySQL搞崩 redis作为数据库时哪怕误删一个数据影响都会很大 redis作为消息队列时误删数据影响大不大就需要具体问题具体分析了
expire命令
给指定的key设置过期时间单位是秒时间复杂度O(1)返回值1表示设置成功0表示设置失败 应用场景手机验证码、外卖优惠券 注意必须针对已经存在的key设置过期时间
ttl命令time to live
查看当前key的过期时间还剩多少时间复杂度O(1)-1表示没有关联过期时间-2表示key不存在 redis中key的过期策略
如果直接遍历所有的key显然是行不通的效率太低了 redis整体的策略是定期删除和惰性删除 定性删除每次抽取一部分进行验证过期时间保证这个抽取检查的过程足够快 为什么要对定性删除的时间有明确的要求 因为redis是单线程的程序主要的任务执行命令如果扫描过期key消耗的时间太多了就可能导致正常处理请求命令就被阻塞了类似于keys * 惰性删除当某个key已经到过期时间了但是暂时还没删它key还存在后面又一次访问正好用到了这个key于是这次访问就会让redis服务器触发删除key的操作同时再返回一个nil
过期策略也可以通过定时器来实现
定时器
概念在某个时间达到之后执行指定的任务
基于优先级队列实现定时器
假定现在又很多key都设置了过期时间就可以把这些key加入到一个优先级队列中指定优先级规则过期时间早的先出队列队首元素就是最早要过期的key然后只需要给定时器分配一个线程让这个线程取检查队首元素看看是否过期即可此时扫描线程不需要遍历所有key只需要盯住队首元素即可 在扫描线程检查队首元素过期时间的时候也不能检查太频繁可以根据当前时刻和队首元素的过期时间设置一个等待当时间差不多到了系统再去唤醒这个线程来新任务时唤醒线程重新设置阻塞时间即可
基于时间轮实现定时器 如上图把时间划分成很多小段—划分的粒度看实际需求 每个小段上都挂着一个链表每个链表都代表一个要执行的任务相当于一个函数指针以及对应的参数啥的 给定一个指针指向时间轮中的一个格子让它绕着这个时间轮旋转每走到一个格子就会尝试把这个格子上链表的任务尝试执行一下 注意每个格子是多少时间一共多少格子都是需要根据实际场景灵活调配的
type命令
查看这个key对应value的类型有string、list、set、hash等等时间复杂度O(1)