Spring Cloud之Sentinel的简单学习

目录

雪崩问题

超时处理

线程隔离

熔断降级

流量控制

服务对比

安装Sentinel控制台

案例

簇点链路

限流规则

流控模式

直接模式

关联模式

链路模式

流控效果

Warm up

排队等待

热点参数限流

隔离与降级

Feign整合Sentinel

线程隔离

规则设置

熔断降级

慢调用

规则设置

异常比例、异常数

规则设置

授权规则

案例实现

规则设置

自定义异常结果

规则持久化

原始模式

Pull模式

Push模式

实现持久化


雪崩问题

在微服务中,当服务D宕机,服务A去调用服务D时,由于服务A等待服务D的返回结果而阻塞,在阻塞期间不会释放tomcat的连接资源,当持续的调用服务D请求发送,tomcat的资源总会被耗尽。这时调用服务B与C的请求也会阻塞在服务A中,导致服务A也宕机。

解决雪崩问题有如下四种解决方案

超时处理

设置超时时间,请求超过一定时间没有响应就返回错误信息,不会阻塞。

但这只是缓解了雪峰问题,当每秒请求量大于每秒释放量时,还是会占用很多tomcat资源。

线程隔离

限定每个业务能使用的线程个数,避免耗尽整个tomcat的资源。

虽然解决了雪崩问题,但还是存在资源浪费,如果服务C真的宕机,那么请求C的资源就被浪费了。

熔断降级

由断路器统计业务执行的异常比例如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。

是一种比较好的解决雪崩问题的一种方式

流量控制

限制业务访问的QPS(每秒钟处理的请求数量),避免业务因流量的突增而故障

属于预防雪崩问题的发生,通过Sentinel控制向服务发起请求的频率

服务对比

Sentinel

Hystrix

隔离策略

信号量隔离

线程池隔离/信号量隔离

熔断降级策略

基于慢调用比例或异常比例

基于失败比率

实时指标实现

滑动窗口

滑动窗口(基于RxJava)

规则配置

支持多种数据源

支持多种数据源

扩展性

多个扩展点

插件的形式

基于注解的支持

支持

支持

限流

基于QPS,支持基于调用关系的限流

有限的支持

流量整形

支持慢启动、匀速排队模式

不支持

系统自适应保护

支持

不支持

控制台

开箱即用,可配置规则、查看秒级监控、机器发现等

不完善

常见框架的适配

Servlet、Spring cloud、Dubbo、gRPC 等

Servlet、Spring Cloud Netflix

  • 线程池隔离:对每个服务创建一个独立线程池,会存在线程数量大于CPU核数的情况,而线程切换又占用CPU资源,性能存在损失
  • 信号量隔离:只有一个线程池,对业务已经使用的线程进行统计,当到达一定数量后,不会对该业务分配更多的线程。
  • 慢调用比例:某个业务的请求耗时量久的数量与该业务总请求数量的比例

安装Sentinel控制台

下载地址:https://github.com/alibaba/Sentinel/releases

下载好后,放在无中文目录下启动

Java -jar sentinel-dashboard-你的版本.jar

访问8080端口,默认账号密码均为sentinel。

如果需要修改默认端口或是账号密码,需要添加启动参数

配置项

默认值

说明

server.port

8080

服务端口

sentinel.dashboard.auth.username

sentinel

默认用户名

sentinel.dashboard.auth.password

sentinel

默认密码

java -Dserver.port=8088 -jar sentinel-dashboard-你的版本.jar

更多配置请参考Sentinel文档

案例

demo下载地址:day01微服务保护

下载完demo之后,启动nacos服务。

引入sentinel依赖

        <!--引入sentinel依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

添加配置内容

spring:cloud:sentinel:transport:dashboard: localhost:你的sentinel启动端口

启动服务并访问地址:localhost:8080/order/101

观察sentinal的控制台出现如下界面

簇点链路

就是项目中的调用链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(可以理解为Controller的每个方法),因此SpringMVC的每一个端点就是调用链路中的一个资源。

限流规则

流控模式

流控的三种模式

  • 默认是直接模式。也就是说,当前资源到达阈值时,对当前资源限流。
  • 关联模式:统计与当前资源相关联的另一个资源,当触发阈值时,对关联的资源进行限流
  • 链路模式:统计从指定链路访问到本地资源的请求,触发阈值时,对指定链路限流。

直接模式

超出阈值的请求会被拦截并报错。

这里我们将阈值设置为5。同时使用jemter模拟并发问题

启动查看运行结果

成功5次。失败5次。查看Sentinel的控制台

关联模式

使用场景:当用户支付时需要修改订单状态,同时也要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是支付和更新订单信息。支付的优先级要高于更新订单,因此当修改订单业务触发阈值时,需要对查询订单业务限流。

当update方法到达阈值后,会对query方法限流。

update与query方法的代码如下

    @GetMapping("/query")public String queryOrder(){return "查询订单成功";}@GetMapping("/update")public String updateOrder(){return "修改订单成功";}

接下来,对update进行压测,同时访问query方法。

可以看到,updata请求全都可以进行访问。但query方法被限流

使用条件:

  • 一个优先级高,一个优先级低
  • 两个有竞争关系的资源

链路模式

使用场景:查询订单和创建订单业务,两者都需要查询商品,当查询订单并发较大时,也会影响创建订单的业务。因此可以针对从查询订单进入到查询商品的请求统计,并设置限流。

Controller代码如下

    @GetMapping("/query")public String queryOrder(){orderService.queryGoods();return "查询订单成功";}@GetMapping("/save")public String saveOrder(){orderService.queryGoods();return "创建订单";}

Service代码如下

	@SentinelResource("goods")public String queryGoods() {return "查询商品";}

访问两个接口查看Sentinel控制台

发现goods只在save链路上,而query中不存在goods。这是因为Sentinel对Controller进行了context整合,Sentinel将/query与/save整合到sentinel_spting_web_context同一链路下,goods无法在同一链路下出现两次。因此导致链路模式的限流失效。

解决方案,添加配置内容

spring:cloud:sentinel:web-context-unify: false

重启项目,再次访问两个接口。

添加流控规则

使用jmeert进行测试

前者为save链路的请求结果,后者为query的请求结果。

说明:

  • Sentinel默认只会监控Controller中的资源。如果需要对Service中的资源进行监控需要添加注解@SentinelResource
  • 在Sentinel的1.6.3版本开始,Sentinel Web filter默认收敛所有的URL入口context,导致链路限流不生效。但在1.7.0本版开始,在CommonFilter引入了WEB_CONTEXT_UNIFY参数,用于控制是否收敛context。

流控效果

流控效果是指,当请求达到流量阈值时的采取措施。包括三种:

  • 快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowExeception异常。是默认的处理方式。
  • warm up:预热模式。对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大值。
  • 排队等待:让所有请求按照先后次序排队执行,两个请求的间隔不能小于指定时长。

Warm up

是应对服务冷启动的一种方案,请求阈值初始值是【最大阈值/冷启动因子】,持续指定时长后,主键提高到最大阈值,默认冷启动因子为3。

例如最大阈值为10,预热时间为5s。那么初始阈值为10/3。然后再5内后逐渐增长到10

案例实现:

添加流控效果

启动jmeter测试

观察Sentinal控制台

可以看到随着时间增加不断增加通过QPS数量。

排队等待

让所有请求进入一个队列,按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。

例如QPS等于5,那么每200ms处理队列中的一个请求,timeout=2000,意味着预期等待超过2秒的请求会被拒绝并抛出异常

案例实现:

编辑流控规则如下

启动jmeter进行测试

观察Sentinel控制台

可以看到。随着时间的增加,响应时间也逐渐增加,同时也出现超过最大等待时间的请求被拒绝。

热点参数限流

统计参数值相同的请求,判断其QPS是否超过了阈值

上图的配置含义为:对hot资源的第一个参数做统计,每秒相同参数值的请求数量不能超过5。

需要注意的是,热点参数对默认的SpringMVC资源无效。(Sentinel的热点参数功能是针对特定的接口和方法的,它通过统计接口的调用次数、流量控制、熔断降级等功能来保护服务的稳定性和可靠性。然而,默认的 SpringMVC 资源(例如 @RequestMapping 注解)并不是针对特定接口和方法的,而是针对整个 URL 的)

需要添加@SentimentResource注解

@SentinelResource("hot")
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId, @RequestHeader(value = "gateway", required = false) String str) {// 根据id查询订单并返回return orderService.queryOrderById(orderId);
}

热点规则的高级设置需要自己新建。

启动jmeter测试

观察Sentinel控制台

隔离与降级

Feign整合Sentinel

之所以使用Feign来整合Sentinel是因为无论是隔离还是降级都是保护调用方的服务能够正常运行。因此可以在调用方添加保护。

案例实现

引入依赖

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>

配置文件

feign:sentinel:enabled: true

编写FeignClient编写失败后的降级逻辑

  • FallbackClass:无法对远程调用的异常做处理
  • FallbackFactory:可以对远程调用的异常做处理。通常使用这种。

编写FallbackFactory代码

@Slf4j
public class UserClientFallback  implements FallbackFactory<UserClient> {@Overridepublic UserClient create(Throwable throwable) {return new UserClient() {@Overridepublic User queryByUserId(Long id) {//编写降级逻辑log.info("查询用户失败:",throwable);//返回默认值或空值return new User();}};}
}

对Client指定对应的降级类

@FeignClient(value = "user-server",fallbackFactory = UserClientFallback.class)
public interface UserClient{@GetMapping("/user/{id}")User queryByUserId(@PathVariable("id")Long id);
}

将UserClientFallback加载为

启动并访问地址:localhost:8080/order/101。

观察Sentinel控制台。

线程隔离

  • 线程池隔离
  • 信号量隔离(Sentinel的默认实现)

两种隔离方式对比

  • 线程池隔离支持主动超时(通过线程的超时时间控制),支持异步调用。信号量隔离不支持主动超时,不支持异步调用
  • 线程池隔离线程的额外开销较大。而信号量隔离则比较轻量,无额外开销。
  • 线程池隔离适用于低扇出(该服务能够调用的其他服务较少)。信号量隔离适用于高频调用,高扇出

规则设置

使用jmeter进行测试

虽然测试全部通过,但是有些响应是通过降级逻辑返回。

熔断降级

熔断降级的思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。当服务恢复正常则会放行该服务的请求。

断路器的三种状态:

  • Closed:关闭状态,统计异常比例
  • Open:当达到失败阈值后由closed状态转为open状态。
  • Half-Open:当熔断时间结束,进入半开状态,放行一次请求,如果失败则回到Open状态,成功则进入Closed状态。

慢调用

响应时长大于指定时长的请求被认为慢调用。在指定时间内,如果请求数量超过设定的最小数量,且慢调用比例到达阈值就会触发断路器。

规则设置

修改代码,让线程休眠60ms

    @GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) throws InterruptedException {if (id == 1) {Thread.sleep(60);}return userService.queryById(id);}

对id为1的请求快速访问5次,接着访问id为2的请求。

可以看到,id为2的用户也查询不到数据了。等待五秒后再次访问id为2的请求

异常比例、异常数

统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常的比例达到设定的比例阈值(或超过指定异常数),则触发熔断。

规则设置

修改代码如下


    @GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) throws InterruptedException {if (id == 1) {Thread.sleep(60);}if (id ==2){throw new RuntimeException("抛出错误");}return userService.queryById(id);}

快速访问id为2的请求5次,然后访问id为3的请求发现,也无法查询到数据

等待5秒后再次访问可以正常访问。

授权规则

对请求者身份进行判断。在白名单的调用者可以访问,在黑名单的调用者不允许访问

与Gateway的区别:Gateway是对网关端口访问的身份校验。不对服务器访问者的身份进行校验。Sentinel是对当外部通过直接访问服务器地址的身份校验。通常来讲,我们只会在白名单中设置gateway的地址。

案例实现

Sentinel是通过RequestOriginParser这个接口的parseOrigin来获取请求的来源。由于Gateway与浏览器发起的请求来源默认都是default,因此,Sentinel无法识别哪些请求来自网关,哪些请求来自浏览器。对此,我们要实现该接口,对网关请求与浏览器请求进行区分。

在Gateway中,可以通过添加过滤器,对每个经过网关的请求添加请求头

spring:cloud:gateway:routes: # 路由地址- id: order-service # 路由唯一标识uri: lb://order-service #路由目标地址predicates: # 路由断言。判断请求是否符合规则- Path=/order/**filters:- AddRequestHeader=origin,gateway

添加请求来源处理器

@Component
public class HandlerOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {String origin = httpServletRequest.getHeader("origin");if (StringUtils.isEmpty(origin)){origin = "blank";}return origin;}
}

规则设置

访问8080服务器端口,发现无法正常访问。

访问10010网关端口。可以正常访问

自定义异常结果

无论是流控还是熔断又或是热点与授权管理,得到的都是限流异常(flow limiting)。这对用户来说不很友好,我们需要针对不同异常返回不同的异常结果。具体实现思路是实现BlockExceptionHandler接口。

常见的BlockException有如下五类

异常

说明

FlowException

限流异常

ParamFlowException

热点参数限流的异常

DegradeException

降级异常

AuthorityException

授权规则异常

SystemBlockException·

系统规则异常

实现代码如下

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {String msg = "未知异常";int status = 429;if (e instanceof FlowException){msg = "请求被限流";}else if (e instanceof ParamFlowException){msg ="热点参数请求被限流";}else if (e instanceof DegradeException){msg = "请求被降级";}else if (e instanceof AuthorityException){msg = "没有权限访问";status = 401;}httpServletResponse.setContentType("application/json;charset=utf-8");httpServletResponse.setStatus(status);httpServletResponse.getWriter().println("{\"msg\":"+msg+",\"status\":"+status+"}");}
}

规则持久化

Sentinel默认将规则保存在内存当中。因此每次重启服务后都需要重新设置规则。Sentinel控制台规则管理有如下三种模式

原始模式

Sentinel默认的模式,将规则保存在内存当中,重启后服务丢失

Pull模式

控制台将配置的规则推送到Sentinel的客户端,客户端会将规则保存在本地文件或数据库中。微服务会定时去本地文件或数据库中查询规则是否改变。来更新本地规则。

缺点:时效性比较差。在集群中,存在一个服务器更改规则而其他服务器还没有进行更改的情况。

Push模式

控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配置变更的推送消息,完成本地更新。这是推荐的一种实现方案

实现持久化

引入依赖

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

配置nacos

spring:cloud:sentinel:datasource:flow:nacos:server-addr: localhost:8848 # nacos地址dataId: orderservice-flow-rulesgroupId: SENTINEL_GROUPrule-type: flow # 还可以是:degrade、authority、param-flow

接下来修改Sentinel的源码。下载Sentinel的源代码文件

下载地址:https://github.com/alibaba/Sentinel/tags

下载好后使用IDEA打开(时间较久),修改模块sentinel-dashboard中的pom文件

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><!--<spoce>test</spoce> 注释掉-->
</dependency>

添加nacos的支持。sentinel-dashboard模块下的test文件夹下已经编写好对nacos的支持,我们需要拷贝到main下

修改nacos地址

修改nacos数据源

修改前端页面

注释打开并修改其中内容

打包

运行启动

访问Sentinel端口并进行清除缓存刷新。

点击F12后,右键刷新键

测试

在新出现的选项中添加流控规则。

点击新增,后观察nacos的控制台。出现如下配置文件

现在即使重启服务器。Sentinel的信息也不会丢失。

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

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

相关文章

RK3568外部IO中断示例

外部IO中断介绍 本篇文章以万象奥科HD-RK3568-IOT评估板中GPIO30为例&#xff0c;介绍Linux内核中断的注册方法&#xff0c;使用中断的方式检测GPIO30是否出现上升沿信号。中断在linux、设备驱动开发里使用的都非常多&#xff0c;可以更加实时的检测GPIO30的状态。 Linux内核…

高等数学教材重难点题型总结(九)多元函数微分法及其应用

第九章习题总结完毕&#xff0c;最难的应该就是方程组求解隐函数中的雅可比行列式了&#xff0c;其他方面无论是期末还是考研都不会出太多难题。对于多元极限和连续性质要理解得更深刻一些&#xff0c;而方向导数、梯度等公式&#xff0c;应该熟练掌握~ 1. 写出多元函数的定义域…

TypeScript 第一站概念篇

前言 &#x1f52e; 好长一段时间没有写文章了&#xff0c;原因是经历了一次工作变动&#xff0c;加入了一个有一定规模的开发团队&#xff0c;前端算上我有四个人&#xff0c;很欣慰&#xff0c;体验一下团队配合的感觉&#xff0c;在我之上有一个组长&#xff0c;比我年长四…

Azure 机器学习 - 使用 AutoML 和 Python 训练物体检测模型

目录 一、Azure环境准备二、计算目标设置三、试验设置四、直观呈现输入数据五、上传数据并创建 MLTable六、配置物体检测试验适用于图像任务的自动超参数扫描 (AutoMode)适用于图像任务的手动超参数扫描作业限制 七、注册和部署模型获取最佳试用版注册模型配置联机终结点创建终…

Spark的主要概念

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f34a; 1. RDD&#x1f34a; 2. Spark SQL&#x1f34a; 3. Spark Streaming&#x1f34a; 4. MLlib&#x1f34a; 5. GraphX&#x1f34a; 总结 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍…

ubuntu20.04配置解压版mysql5.7

目录 1.创建mysql 用户组和用户2.下载 MySQL 5.7 解压版3.解压 MySQL 文件4.将 MySQL 移动到适当的目录5.更改mysql目录所属的用户组和用户&#xff0c;以及权限6.进入mysql/bin/目录&#xff0c;安装初始化7.编辑/etc/mysql/my.cnf配置文件8.启动 MySQL 服务&#xff1a;9.建立…

在Linux上编译gdal3.1.2指南

作者:朱金灿 来源:clever101的专栏 为什么大多数人学不会人工智能编程?>>> 以Ubuntu 18编译gdal3.1.2为例,编译gdal3.1.2需要先编译proj库和geos库(可选)。我选择的proj库版本为proj-7.1.0,编译proj-7.1.0需要先编译tiff库和sqlite3。我选择的sqlite3的版本为…

Unity的live2dgalgame多语言可配置剧情框架

这段代码用于读取表格 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using OfficeOpenXml; using System.IO; using UnityEngine.Networking; using UnityEngine.UI; using Random UnityEngine.Random;public class Plots…

工业5G路由器;小体积 千兆高速通信组网

计讯物联工业路由器TR232&#xff0c;5G高速网络&#xff0c;超低时延、高可靠性&#xff0c;小体积、易安装、强兼容&#xff0c;串口/网口多设备接入联网&#xff0c;为用户提供高速稳定的数据传输通道 。    小体积5G工业路由器TR323&#xff0c;外形1047824mm&#xff0…

系列六、Mybatis的一级缓存

一、概述 Mybatis一级缓存的作用域是同一个SqlSession&#xff0c;在同一个SqlSession中执行两次相同的查询&#xff0c;第一次执行完毕后&#xff0c;Mybatis会将查询到的数据缓存起来&#xff08;缓存到内存中&#xff09;&#xff0c; 第二次执行相同的查询时&#xff0c;会…

ArmSom---SPI开发指南

1. 简介 RK3588从入门到精通本⽂主要介绍在Rockchip平台配置spi接口并且使用的方法开发板&#xff1a;ArmSoM-W3Kernel&#xff1a;5.10.160OS&#xff1a;Debian11 2. SPI接口概述 SPI&#xff08;Serial Peripheral Interface&#xff09;&#xff0c;即串行外围设备接口&…

ElementuiPlus的table组件实现行拖动与列拖动

借助了插件sortablejs。这种方法只适合做非树状table。如果想实现树状table&#xff0c;并且可拖动。可以试一下aggridVue3这个插件 <template><div class"draggable" style"padding: 20px"><el-table row-key"id" :data"t…

RabbitMQ 消息对象 序列化/反序列化 天坑!异常处理方案

目录 1. 报错的背景 2. 问题分析 3. 最佳解决办法 1. 报错的背景 a&#xff09;使用 RabbitMQ 发送消息时&#xff0c;发送消息的类型为 Map<String, Object>&#xff0c;map 里面我 put 了一个 <String, Long> 类型&#xff0c;如下图&#xff1a; b&#xff…

【考研数据结构代码题2】删除单链表倒数第n个结点

题目&#xff1a;删除单链表倒数第n个结点 难度&#xff1a;★ 算法思路&#xff1a; 首先题目没有指明链表的长度&#xff0c;多以首先需要编写一个函数getLength()来求表长&#xff0c;其次删除倒数第n个结点&#xff0c;即删除正数第length-n1个结点&#xff0c;这是二者之间…

更快更准 | YOLOv3算法超详细解析(包括诞生背景+论文解析+技术原理等)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。YOLOv3是一种基于深度学习的目标检测算法&#xff0c;它可以快速而准确地在图像中检测出多个目标。它是由Joseph Redmon和Ali Farhadi在2018年提出的&#xff0c;是YOLO&#xff08;You Only Look Once&#xff09;系列算法…

Linux权限+Shell和Linux的关系

文章目录 1.Shell存在的意义及作用1.1对于Shell的认知过程1.2Shell/图形化界面外壳程序的意义 2.对Linux权限的理解2.1对Linux权限的认知过程2.2对于Linux下ll指令显示的文件属性的认识 1.Shell存在的意义及作用 1.1对于Shell的认知过程 Linux是什么? Linux是一套免费使用和自…

msvcr110.dll丢失的解决方法都有哪些,有效解决msvcr110.dll丢失

今天在使用电脑的时候提示一个和“msvcr110.dll丢失”有关的报错&#xff0c;出现这样的问题小编也是一脸懵&#xff0c;一下也不是知道该怎么处理了&#xff0c;于是小编去了解了一下msvcr110.dll丢失是什么情况&#xff0c;为什么会有这样的问题发生&#xff0c;同时msvcr110…

多模态论文阅读之VLMo

VLMo泛读 TitleMotivationContributionModelExpertimentsSummary Title VLMo:Unified Vision_Langugae Pre-Training with Mixture-of-Modality-Experts Motivation CLIP和ALIGN都采用dual-encoder的方式分别编码图像和文本&#xff0c;模态之间的交互采用cosine similarity…

《C++ Primer》第6章 函数(一)

参考资料&#xff1a; 《C Primer》第5版《C Primer 习题集》第5版 6.1 函数基础&#xff08;P182&#xff09; 典型的函数定义包括&#xff1a;返回类型&#xff08; return type &#xff09;、函数名字、0 个或多个形参&#xff08; parameter &#xff09;组成的列表、函…

Redis常见的全局命令

Redis中最核心的两个命令set和get 两个最核心的命令就是get和set. redis是按照键值对的方式来存储数据的,所以set就表示把key-value存储进去,get表示根据key来查询对应的value. 需要注意的是,必须进入redis客户端才能输入redis命令. 此处的key和value都是字符串类型.对于上述…