redis rua解决库存问题_【150期】面试官:Redis的各项功能解决了哪些问题?

点击上方“Java面试题精选”,关注公众号

面试刷图,查缺补漏

>>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅

阶段汇总集合:一百期面试题汇总

先看一下Redis是一个什么东西。

官方简介解释到:Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用。

同时支持strings,lists,hashes,sets,sorted sets,bitmaps,hyperloglogs和geospatial indexes等数据类型。

它还内建了复制,lua脚本,LRU,事务等功能,通过redis sentinel实现高可用,通过redis cluster实现了自动分片。以及事务,发布/订阅,自动故障转移等等。

综上所述,Redis提供了丰富的功能,初次见到可能会感觉眼花缭乱,这些功能都是干嘛用的?都解决了什么问题?什么情况下才会用到相应的功能?那么下面从零开始,一步一步的演进来粗略的解释下。

1 从零开始

最初的需求非常简单,我们有一个提供热点新闻列表的api:http://api.xxx.com/hot-news,api的消费者抱怨说每次请求都要2秒左右才能返回结果。

随后我们就着手于如何提升一下api消费者感知的性能,很快最简单粗暴的第一个方案就出来了:为API的响应加上基于HTTP的缓存控制 cache-control:max-age=600 ,即让消费者可以缓存这个响应十分钟。

如果api消费者如果有效的利用了响应中的缓存控制信息,则可以有效的改善其感知的性能(10分钟以内)。但是还有2个弊端:第一个是在缓存生效的10分钟内,api消费者可能会得到旧的数据;第二个是如果api的客户端无视缓存直接访问API依然是需要2秒,治标不治本呐。

2 基于本机内存的缓存

为了解决调用API依然需要2秒的问题,经过排查,其主要原因在于使用SQL获取热点新闻的过程中消耗了将近2秒的时间,于是乎,我们又想到了一个简单粗暴的解决方案,即把SQL查询的结果直接缓存在当前api服务器的内存中(设置缓存有效时间为1分钟)。

后续1分钟内的请求直接读缓存,不再花费2秒去执行SQL了。假如这个api每秒接收到的请求时100个,那么一分钟就是6000个,也就是只有前2秒拥挤过来的请求会耗时2秒,后续的58秒中的所有请求都可以做到即使响应,而无需再等2秒的时间。

其他API的小伙伴发现这是个好办法,于是很快我们就发现API服务器的内存要爆满了。。。

3 服务端的Redis

在API服务器的内存都被缓存塞满的时候,我们发现不得不另想解决方案了。最直接的想法就是我们把这些缓存都丢到一个专门的服务器上吧,把它的内存配置的大大的。然后我们就盯上了redis。。。

至于如何配置部署redis这里不解释了,redis官方有详细的介绍。随后我们就用上了一台单独的服务器作为Redis的服务器,API服务器的内存压力得以解决。

3.1 持久化(Persistence)

单台的Redis服务器一个月总有那么几天心情不好,心情不好就罢工了,导致所有的缓存都丢失了(redis的数据是存储在内存的嘛)。虽然可以把Redis服务器重新上线,但是由于内存的数据丢失,造成了缓存雪崩,API服务器和数据库的压力还是一下子就上来了。

所以这个时候Redis的持久化功能就派上用场了,可以缓解一下缓存雪崩带来的影响。redis的持久化指的是redis会把内存的中的数据写入到硬盘中,在redis重新启动的时候加载这些数据,从而最大限度的降低缓存丢失带来的影响。

3.2 哨兵(Sentinel)和复制(Replication)

Redis服务器毫无征兆的罢工是个麻烦事。那么怎办办?答曰:备份一台,你挂了它上。那么如何得知某一台redis服务器挂了,如何切换,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要Sentinel和Replication出场了。

Sentinel可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转移的功能;Replication则是负责让一个Redis服务器可以配备多个备份的服务器。Redis也是利用这两个功能来保证Redis的高可用的。此外,Sentinel功能则是对Redis的发布和订阅功能的一个利用。

3.3 集群(Cluster)

单台服务器资源的总是有上限的,CPU资源和IO资源我们可以通过主从复制,进行读写分离,把一部分CPU和IO的压力转移到从服务器上。但是内存资源怎么办,主从模式做到的只是相同数据的备份,并不能横向扩充内存;单台机器的内存也只能进行加大处理,但是总有上限的。

所以我们就需要一种解决方案,可以让我们横向扩展。最终的目的既是把每台服务器只负责其中的一部分,让这些所有的服务器构成一个整体,对外界的消费者而言,这一组分布式的服务器就像是一个集中式的服务器一样(之前在解读REST的博客中解释过分布式于基于网络的差异:基于网络应用的架构)。

在Redis官方的分布式方案出来之前,有twemproxy和codis两种方案,这两个方案总体上来说都是依赖proxy来进行分布式的,也就是说redis本身并不关心分布式的事情,而是交由twemproxy和codis来负责。

而redis官方给出的cluster方案则是把分布式的这部分事情做到了每一个redis服务器中,使其不再需要其他的组件就可以独立的完成分布式的要求。我们这里不关心这些方案的优略,我们关注一下这里的分布式到底是要处理那些事情?也就是twemproxy和codis独立处理的处理分布式的这部分逻辑和cluster集成到redis服务的这部分逻辑到底在解决什么问题?

如我们前面所说的,一个分布式的服务在外界看来就像是一个集中式的服务一样。那么要做到这一点就面临着有一个问题需要解决:既是增加或减少分布式服务中的服务器的数量,对消费这个服务的客户端而言应该是无感的;那么也就意味着客户端不能穿透分布式服务,把自己绑死到某一个台的服务器上去,因为一旦如此,你就再也无法新增服务器,也无法进行故障替换。

解决这个问题有两个路子:

第一个路子最直接,那就是我加一个中间层来隔离这种具体的依赖,即twemproxy采用的方式,让所有的客户端只能通过它来消费redsi服务,通过它来隔离这种依赖(但是你会发现twermproxy会成为一个单点),这种情况下每台redis服务器都是独立的,它们之间彼此不知对方的存在;

第二个路子是让redis服务器知道彼此的存在,通过重定向的机制来引导客户端来完成自己所需要的操作,比如客户端链接到了某一个redis服务器,说我要执行这个操作,redis服务器发现自己无法完成这个操作,那么就把能完成这个操作的服务器的信息给到客户端,让客户端去请求另外的一个服务器,这时候你就会发现每一个redis服务器都需要保持一份完整的分布式服务器信息的一份资料,不然它怎么知道让客户端去找其他的哪个服务器来执行客户端想要的操作呢。

上面这一大段解释了这么多,不知有没有发现不管是第一个路子还是第二个路子,都有一个共同的东西存在,那就是分布式服务中所有服务器以及其能提供的服务的信息。这些信息无论如何也是要存在的,区别在于第一个路子是把这部分信息单独来管理,用这些信息来协调后端的多个独立的redis服务器;第二个路子则是让每一个redis服务器都持有这份信息,彼此知道对方的存在,来达成和第一个路子一样的目的,优点是不再需要一个额外的组件来处理这部分事情。

Redis Cluster的具体实现细节则是采用了Hash槽的概念,即预先分配出来16384个槽:在客户端通过对Key进行CRC16(key)% 16384运算得到对应的槽是哪一个;在redis服务端则是每个服务器负责一部分槽,当有新的服务器加入或者移除的时候,再来迁移这些槽以及其对应的数据,同时每个服务器都持有完整的槽和其对应的服务器的信息,这就使得服务器端可以进行对客户端的请求进行重定向处理。

4 客户端的Redis

上面的第三小节主要介绍的是Redis服务端的演进步骤,解释了Redis如何从一个单机的服务,进化为一个高可用的、去中心化的、分布式的存储系统。这一小节则是关注下客户端可以消费的redis服务。

4.1 数据类型

redis支持丰富的数据类型,从最基础的string到复杂的常用到的数据结构都有支持:

  • string:最基本的数据类型,二进制安全的字符串,最大512M。

  • list:按照添加顺序保持顺序的字符串列表。

  • set:无序的字符串集合,不存在重复的元素。

  • sorted set:已排序的字符串集合。

  • hash:key-value对的一种集合。

  • bitmap:更细化的一种操作,以bit为单位。

  • hyperloglog:基于概率的数据结构。

这些众多的数据类型,主要是为了支持各种场景的需要,当然每种类型都有不同的时间复杂度。其实这些复杂的数据结构相当于之前我在《解读REST》这个系列博客基于网络应用的架构风格中介绍到的远程数据访问(Remote Data Access = RDA)的具体实现,即通过在服务器上执行一组标准的操作命令,在服务端之间得到想要的缩小后的结果集,从而简化客户端的使用,也可以提高网络性能。比如如果没有list这种数据结构,你就只能把list存成一个string,客户端拿到完整的list,操作后再完整的提交给redis,会产生很大的浪费。

4.2 事务

上述数据类型中,每一个数据类型都有独立的命令来进行操作,很多情况下我们需要一次执行不止一个命令,而且需要其同时成功或者失败。redis对事务的支持也是源自于这部分需求,即支持一次性按顺序执行多个命令的能力,并保证其原子性。

4.3 Lua脚本

在事务的基础上,如果我们需要在服务端一次性的执行更复杂的操作(包含一些逻辑判断),则lua就可以排上用场了(比如在获取某一个缓存的时候,同时延长其过期时间)。redis保证lua脚本的原子性,一定的场景下,是可以代替redis提供的事务相关的命令的。相当于基于网络应用的架构风格中介绍到的远程求值(Remote Evluation = REV)的具体实现。

4.4 管道

因为redis的客户端和服务器的连接时基于TCP的, 默认每次连接都时只能执行一个命令。管道则是允许利用一次连接来处理多条命令,从而可以节省一些tcp连接的开销。管道和事务的差异在于管道是为了节省通信的开销,但是并不会保证原子性。

4.5 分布式锁

官方推荐采用Redlock算法,即使用string类型,加锁的时候给的一个具体的key,然后设置一个随机的值;取消锁的时候用使用lua脚本来先执行获取比较,然后再删除key。具体的命令如下:

SET resource_name my_random_value NX PX 30000

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

总结

本篇着重从抽象层面来解释下redis的各项功能以及其存在的目的,而没有关心其具体的细节是什么。从而可以聚焦于其解决的问题,依据抽象层面的概念可以使得我们在特定的场景下选择更合适的方案,而非局限于其技术细节。

以上均是笔者个人的一些理解,如果不当之处,欢迎指正。

参考

Redis 文档:https://github.com/antirez/redis-doc

Redis 简介:https://redis.io/topics/introduction

Redis 持久化(Persistence):https://redis.io/topics/persistence

Redis 发布/订阅(Pub/Sub):https://redis.io/topics/pubsub

Redis 哨兵(Sentinel):https://redis.io/topics/sentinel

Redis 复制(Replication):https://redis.io/topics/replication

Redis 集群(cluster):https://redis.io/topics/cluster-tutorial

RedIs 事务(Transaction):https://redis.io/topics/transactions

Redis 数据类型(data types):https://redis.io/topics/data-types-intro

Redis 分布式锁:https://redis.io/topics/distlock

Redis 管道(pipelining ):https://redis.io/topics/pipelining

Redis Lua Script:https://redis.io/commands/eval

来源:https://www.cnblogs.com/linianhui/

与其在网上拼命找题? 不如马上关注我们~

7ff271704d8bb4879ada08d4547ee18d.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

启动盘Linux windows,Linux 中创建 USB 启动盘来拯救 Windows 用户

人们经常要求我帮助他们恢复被锁死或损坏的 Windows 电脑。有时,我可以使用 Linux USB 启动盘来挂载 Windows 分区,然后从损坏的系统中传输和备份文件。有的时候,客户丢失了他们的密码或以其他方式锁死了他们的登录账户凭证。解锁账户的一种方…

vue验证整数_前端Vue中常用rules校验规则

前端Vue中常用rules校验规则1、是否合法IP地址export function validateIP(rule, value,callback) {if(value||valueundefined||valuenull){callback();}else{const reg /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\![](https://user-gold-cdn.xit…

linux make编译报错 mv,Linux下安装redis

1:首先下载redis http://redis.io/download2: 需要Linux安装gcc依赖3:进行解压 tar -zxvf redis-3.0.0-rc2.tar.gz4:进入到redis-3.0.0目录下,进行编译 make (如果make编译报错 可直接用 make MALLOClibc 解决)5:…

c#中connect函数_C#.NET 各种连接字符串

1.C#连接连接Access程序代码:using System.Data;using System.Data.OleDb;..string strConnection"ProviderMicrosoft.Jet.OleDb.4.0;";strConnection"Data SourceC:BegASPNETNorthwind.mdb";OleDbConnection objConnectionnew OleDbConnectio…

echarts里面的参数解释_Echarts适用小技巧:适用参数详细说明及示例-TS文件

点击右上方红色按钮关注“web秀”,让你真正秀起来前言前面有文章,讲述了Vue中封装Echarts组件,但都是直接上代码,没有具体对代码进行讲述。今天我们就来看看,如何使Echarts图表更美观,都是那部分属性使其更…

linux桌面版自动更新关闭了,桌面应用|开启 Ubuntu 系统自动升级

在学习如何开启Ubuntu系统自动升级之前,先解释下为什么需要自动升级。默认情况下,ubuntu每天一次检查更新。但是一周只会弹出一次软件升级提醒,除非当有安全性升级时,才会立即弹出。所以,如果你已经使用Ubuntu一段时间…

做自适应网站专业乐云seo_什么叫网站优化-网站建设-SEO优化

公司致力于企业品牌营销策划、网站建设、网站优化、五网竞价推广、商城建设、小程序开发、搜索引擎推广、SEO及企业品牌整合营销、全网整合营销霸屏推广等专业一站式网络全包服务。为不同企业品牌量身定制合适的设计方案,提供专业一站式网站服务平台、网络广告投放平…

linux native分区,怎么将硬盘格式分区为Linux Native格式的

根据目前流行的操作系统来看,常用的分区格式有四种,分别是FAT16、FAT32、NTFS和Linux。资格最老的当然就是FAT16啦,这是MS-DOS和最早期的Windows 95操作系统中最常见的磁盘分区格式。它采用16位的文件分配表,而且是目前…

跨域会报40几_关于跨域,以及跨域的几种方式

首先我们来想一想为什么会有跨域这个名词的出现呢?跨域又是什么呢?为何要跨域?浏览器的同源策略又是什么?怎么解决?jsonp又是什么?跨域的原理又是什么呢?名词解释:跨域:浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和…

linux用户的配置文件保存在哪里,使用配置文件(.settings、.config)存储应用程序配置...

引言我不知大家早先是如何保存应用程序配置,以备下次打开时使用的,反正我开始学.Net的时候就去研究序列化,以二进制或XML格式的序列化来保存应用程序配置。这样每次都要建立单独的配置类,并书写读写配置代码,相当麻烦。…

python如何画图设置坐标轴_python matplotlib坐标轴设置的方法

在使用matplotlib模块时画坐标图时,往往需要对坐标轴设置很多参数,这些参数包括横纵坐标轴范围、坐标轴刻度大小、坐标轴名称等在matplotlib中包含了很多函数,用来对这些参数进行设置。我们可以对坐标轴进行设置,设置坐标轴的范围…

linux比较厉害的运维项目,Linux运维项目实战系列

ORACLE 博客文章目录(2015-05-27更新)从接触ORACLE到深入学习,已有好几年了,虽然写的博客不多,质量也参差不齐,但是,它却是成长的历程的点点滴滴的一个见证,见证了我在这条路上的寻寻觅觅,朝圣的心路历程,现在将ORACLE方面的博客整理 ...Login控件尝试新建we…

awk 内嵌正则 提取字符串_使用awk提取字符串中的数字或字母

1.提取字符串中的数字$ echo dsFUs34tg*fs5a%8ar%$# |awk -F "" {for(i1;i<NF;i){if ($i ~ /[[:digit:]]/){str$istr1(str1 str)}}print str1}输出3458或$ echo dsFUs34tg*fs5a%8ar%$# |awk -F "" {for(i1;i<NF;i){if ($i ~ /[0-9]/){str$istr1(str1…

mysql中字符串拼接函数_MySQL字符串连接函数

一、CONCAT(str1,str2,…)返回结果为连接参数产生的字符串。如有任何一个参数为NULL &#xff0c;则返回值为 NULL。select concat(s_id, "--", s_bar_code) from t_storage_order_detail WHERE s_sn LIKE %R2016091200002% LIMIT 0, 1000;-------------------------…

云终端linux系统,让同方安全的云终端运行于Linux系统之上(二)

4、显示驱动与云终端显示相关的硬件包括多层控制器(MLC)及显示控制器(DPC)。MLC对应的修改的程序是mlc.c、mlc.h、main.c,DPC对应修改的程序为dpc_config.h、dpc_ioctl.h及main.c。修改主要涉及MLC顶层的初始设置、显示LOGO设置、及系统默认显示分辨率的设置、及与Pollux硬件相…

4列变成5列 datatable_云南美食界“5巨头”,谁才是NO.1?你家乡的那道菜也在列...

每个城市都有自己盛产的食材&#xff0c;最终也被制作成几代都传延至今的美食&#xff0c;这便是美食的传承。今天小编就来说说云南美食&#xff0c;下面这云南美食界“5巨头”&#xff0c;谁才是你心里的NO.1&#xff1f;你家乡的那道菜也在列哦~云南大理&#xff1a;白族泥鳅…

linux+基因组字符替换,liftover基因组版本直接的coordinate转换

下载地址:http://hgdownload.cse.ucsc.edu/admin/exe/使用方法:【从hg38转到hg19】因为主流的基因组版本还是hg19&#xff0c;但是时代在进步&#xff0c;已经有很多信息都是以hg38的形式公布出来的了。比如&#xff0c;我下载了pfam.df这个protein domain注释文件&#xff0c;…

elinput内容过长显示悬浮框_excel中一直被忽视的名称框,用好了也能提高效率

在excel左上角功能区下方&#xff0c;有一个名称框(下图红框中的部分)。大部分朋友应该没注意过这个地方有什么作用&#xff0c;或者仅仅知道名称框中会显示单元格的位置&#xff0c;因此在操作中这项功能无法表现出其真正的效果。本文就为大家介绍一下关于名称框的一些实用功能…

linux 漏洞 poc,CVE-2017-11176: 一步一步linux内核漏洞利用 (二)(PoC)

使第二次循环中的fget()返回NULL到目前为止&#xff0c;在用户态下满足了触发漏洞的三个条件之一。TODO:使netlink_attachskb()返回1[DONE]exp线程解除阻塞使第二次fget()调用返回NULL在本节中&#xff0c;将尝试使第二次fget()调用返回NULL。这会使得在第二个循环期间跳到“退…

同步轨道进入过程_“收官之星”定点成功!北斗三号卫星全部进入长管模式

◎ 徐新芳 科技日报记者 付毅飞6月30日14时15分&#xff0c;北斗三号全球卫星导航系统最后一颗组网卫星成功定点于距离地面约36000公里的地球同步轨道&#xff0c;顺利进入长期运行管理模式。卫星有效载荷已完成开通&#xff0c;经过遥测数据判读&#xff0c;星载基准频率合成器…