Redis学习专题(一)配置和持久化

目录

一.配置Redis

1.配置application.properties

2. 配置Config

3.测试连接redis

二、Redis持久化

持久化方案

RDB:

1、RDB基础认识

1、具体流程如下:

3、小结:

3、Fork&Copy-On-Write

4、RDB的配置

5、默认快照的配置

6、save VS bgsave

7、flushall

8、save

9、stop-writes-on-bgsave-error

10、rdbcompression

11、rdbchecksum

12、动态停止RDB

2、RDB备份和恢复:

3、RDB小结

2、AOF

1、开启AOF

2、修复和恢复

3、同步频率设置

4、rewrite压缩

5、AOF小结

3、选择RDB还是AOF?


一.配置Redis

1.配置application.properties

# Redis 服务器地址
spring.redis.host=127.0.0.1
# Redis 服务器连接端口
spring.redis.port=6379
# Redis 密码(如果没有密码,直接删除这一行)
spring.redis.password=
# Redis 数据库索引(默认 0)
spring.redis.database=2
# 连接超时时间(毫秒)
spring.redis.timeout=1800000
# 连接池最大连接数(使用负数表示无限制)
spring.redis.lettuce.pool.max-active=20
# 最大阻塞等待时间(负数表示无限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=5
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0

2. 配置Config

里面包含两个方法

1.redisTemplate

2.CacheManager

@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template =new RedisTemplate<>();System.out.println("template=>" + template);//这里可以验证..RedisSerializer<String> redisSerializer =new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.WRAPPER_ARRAY);jackson2JsonRedisSerializer.setObjectMapper(om);template.setConnectionFactory(factory);//key序列化方式template.setKeySerializer(redisSerializer);//value序列化template.setValueSerializer(jackson2JsonRedisSerializer);//value hashmap序列化template.setHashValueSerializer(jackson2JsonRedisSerializer);return template;}@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer<String> redisSerializer =new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);//解决查询缓存转换异常的问题ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.WRAPPER_ARRAY);jackson2JsonRedisSerializer.setObjectMapper(om);// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;}
}

3.测试连接redis

@RestController
@RequestMapping("/redisTest")
public class RedisTestController {//装配RedisTemplate@Resourceprivate RedisTemplate redisTemplate;//编写第一个测试方法//演示设置数据和获取数据@GetMapping("/t1")public String t1() {//设置值到redisredisTemplate.opsForValue().set("book", "天龙八部~");//从redis获取值String book = (String) redisTemplate.opsForValue().get("book");return book;}

通过上面的api来访问,就会得到:

以及

 这样我们就测试成功了

注意:

如果是通过客户端添加的数据,我们用redisTemplate的时候也会做反序列化,但是客户端set是不会做序列化的,所以会报错

解决方案就是用服务端的程序重新set一下就好了 

二、Redis持久化

Redis 持久化是指 ​​将内存中的数据保存到磁盘​​,确保即使 Redis 服务重启或崩溃,数据也不会丢失。由于 Redis 是 ​​内存数据库​​(数据默认存储在内存中),持久化机制可以防止数据因断电、宕机等情况而丢失。

在线文档 :https://redis.io/topics/persistence

持久化方案

RDB和AOP

RDB:

1、RDB基础认识

在指定时间内将内存的数据集快照写入磁盘中,也就是Snapshot快照,恢复时将快照文件读到内存

​RDB 持久化是通过生成数据快照来实现的

流程图:

1、具体流程如下:

1、redis 客户端执行bgsave命令或者自动触发bgsave命令;

2、主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回;

3、如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作;  

4、子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件;

5、同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息

3、小结:

1.整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 。

2.如果需要进行大规模数据的恢复, 且对于数据恢复的完整性不是非常敏感,那RDB方式 要比AOF方式更加的高效 。 

3.RDB 的缺点是最后一次持久化后的数据可能丢失:如果你是正常关闭Redis,也就是正常shutdown时仍然会进行持久化, 不会造成数据丢失。如果是Redis 异常终止/宕机, 就可能造成数据丢失,具体流程如下:

  1. 收到 SHUTDOWN 命令。
  2. Redis 立即执行一次 ​​阻塞式 SAVE​(确保数据完整)。
  3. 将最新数据写入 dump.rdb
  4. 关闭进程。

默认是SAVE

3、Fork&Copy-On-Write

1、Fork 的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、 程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程

2、在Linux 程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,出于效率考虑,Linux中引入了"写时复制技术 即:copy-on-write", 有兴 韩顺平Java 工程师 趣的参考:https://blog.csdn.net/Code_beeps/article/details/92838520

3、一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程,也就是说:
当我用父进程操作一块物理内存,fork了一个子进程,此时父进程和子进程都在同一块物理内存,因为数据是一致的,当父进程对物理内存进行操作了,就会创建一个新的物理内存,此时父线程就到新的内存区域了,子线程在旧的内存区域。

4、RDB的配置

在redis.conf中配置文件名称,默认为dump.rdb,可以自定义

如何配置:

1、默认为Redis启动时命令行所在的目录下

进入到/usr/local/bin 目录下, 启动 Redis, 这个 ./ 就是 /usr/local/bin , 如果你在 /root/ 目录下启动 Redis, 那么 ./ 就是 /root/ 下了。如果之前在root目录下启动的redis,数据自动保存在这个目录下的dump.rdb,当年第二天打开,数据也从这个目录下的dump.rdb里恢复回来,也就是说,如果你从其他目录打开是没有数据的,因为没有对应的dump.rdb

2、rdb 文件的保存路径, 也可以修改, 比如: dir"/root/"  

把dit ./改成dir /root/  ,这样一来无论从哪打开redis都会统一走同一个持久化文件

5、默认快照的配置

这是后台机制

1.

2.注意理解这个时间段的概念:

时间是独立的一段一段时间,下一个60秒会刷新统计

3.如果我们没有开启save注释,那么在退出Redis的时候也会再进行备份,更新dump.rdb(执行一次 ​​阻塞式 SAVE​)

4.如果再规定时间内没有达到指定的key值变化,那么30秒后不做持久化

例子:save 30 10:

如果再规定时间内没有达到指定的key值变化,那么30秒后不做持久化,但是时间是独立的一段一段时间,下一个30秒会刷新统计,那我上一个30秒修改的key不做保存,就丢失了。除非shutdown

6、save VS bgsave

1、save :save时只管保存,其它不管,全部阻塞。手动保存, 不建议

2、bgsave:Redis 会在后台异步进行快照操作, 快照同时还可以响应客户端请求。

3、可以通过lastsave 命令获取最后一次成功执行快照的时间(unix时间戳), 可以使用工具转换时间戳(Unix timestamp)转换工具 - 在线工具

7、flushall

1、执行flushall 命令,会把内存的数据全部拿掉,同时把数据再次持久化,所以dump.rdb文件数据为空.

2、Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key)

内存92相当于是初始化的内存大小

8、save

save 秒钟 写操作次数

禁用: 给save传入空字符串

RDB是整个内存的压缩过的Snapshot,RDB的数据结构,可以配置复合的快照触发条

9、stop-writes-on-bgsave-error

当Redis无法写入磁盘的话(比如磁盘满了), 直接关掉Redis的写操作。推荐yes

10、rdbcompression

1、对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用 LZF 算法进行压缩。

2、如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能, 默认yes

11、rdbchecksum

1、在存储快照后, 还可以让redis使用CRC64算法来进行数据校验,保证文件是完整的

2、但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭 此功能, 推荐yes

12、动态停止RDB

1、动态停止RDB:redis-cli config set save"",不需要重启redis

2、说明:save后给空值,表示禁用保存策略

2、RDB备份和恢复:

1、Redis可以充当缓存, 对项目进行优化, 因此重要/敏感的数据建议在Mysql 要保存一份

2、从设计层面来说,Redis的内存数据, 都是可以重新获取的(可能来自程序, 也可能来自 Mysql)

3、因此我们这里说的备份&恢复主要是给大家说明一下 Redis启动时, 初始化数据是从 dump.rdb 来的, 这个机制.

config get dir 查询 rdb 文件的目录

将dump.rdb 进行备份, 如果有必要可以写shell脚本来定时备份 网课: https://www.bilibili.com/video/BV1Sv411r7vd?p=105

参考韩顺平老师的演示:

最终结果:

3、RDB小结

优势:

1、适合大规模的数据恢复

2、对数据完整性和一致性要求不高更适合使用

3、节省磁盘空间

4、恢复速度快

劣势:

1、虽然Redis在fork时使用了写时拷贝技术(Copy-On-Write), 但是如果数据庞大时还是比较消耗性能

2、在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话(如果正常 关闭Redis, 仍然会进行RDB备份, 不会丢失数据), 就会丢失最后一次快照后的所有修改

2、AOF

官方资料 在线文档 :https://redis.io/topics/persistence

1、AOF(Append Only File)

2、以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(比 如 set/del 操作会记录, 读操作get不记录)

3、只许追加文件但不可以改写文件

4、redis 启动之初会读取该文件重新构建数据

5、redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

持久化流程图

1) 客户端的请求写命令会被append追加到AOF缓冲区

2) AOF 缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件

3) AOF 文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量

4) Redis 服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的

1、开启AOF

1、在redis.conf 中配置文件名称,默认为 appendonly.aof

2、AOF文件的保存路径,同RDB的路径一致

3、AOF和RDB同时开启,系统默认取AOF的数据

4、老韩实验, 当开启AOF后,Redis从AOF文件取数据.

后续:

当我们开启AOF之后再去写操作,这时候appendonly.aof就有数据了

2、修复和恢复

AOF的备份机制和性能虽然和RDB不同, 但是备份和恢复的操作同RDB一样, 都是拷贝备份文件, 需要恢复时再拷贝到Redis工作目录下,启动系统即加载

一、正常恢复

1、修改默认的appendonlyno,改为yes

2、将有数据的aof文件定时备份, 需要恢复时, 复制一份保存到对应目录(查看目录:config get dir)

3、恢复:重启redis然后重新加载

4、和前面RDB备份/恢复机制类似  .bak

二、异常恢复

1、如遇到AOF文件损坏,通过/usr/local/bin/redis-check-aof --fix appendonly.aof 进行恢复

2、建议先: 备份被写坏的AOF文件

3、恢复:重启redis,然后重新加载

可能会造成数据丢失,但是总比没有好,而且当文件损坏之后是连接不上了,根本就没有redis服务

开始修复文件:

成功了

3、同步频率设置

AOF 缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中,其中[always,everysec,no]就是同步频率设置

1.配置位置

1) appendfsync always 始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好

2) appendfsync everysec 每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。

3) appendfsync no redis不主动进行同步,把同步时机交给操作系统 https://baijiahao.baidu.com/s?id=1740774723808931509&wfr=spider&for=pc

4、rewrite压缩

一、rewrite 重写介绍

1) AOF 文件越来越大,需要定期对AOF文件进行重写达到压缩

2) 旧的AOF文件含有无效命令会被忽略,保留最新的数据命令 , 比如 :set a a1 ; set a b1; set a c1; 保留最后一条指令就可以了

3) 多条写命令可以合并为一个 , 比如把上面的指令改成: set a c1 b b1 c c1

4) AOF 重写降低了文件占用空间

5) 更小的AOF文件可以更快的被redis加载

二、重写触发配置

1) 手动触发 直接调用bgrewriteaof 命令

2) 自动触发

 auto-aof-rewrite-min-size: AOF 文件最小重写大小, 只有当 AOF 文件大小大于该值时候才能 auto-aof-rewrite-percentage, 默认配置64MB

auto-aof-rewrite-percentage: 当前 AOF 文件大小和最后一次重写后的大小之间的比率等于或者大于指定的增长百分比,如100代表当前AOF文件是上次重写的两倍时候才重写

系统载入时或者上次重写完毕时,Redis会记录此时AOF大小,设为 base_size。

如果Redis的AOF当前大小>=base_size+base_size*100%(默认) 且 当前 大小>=64mb(默认)的情况下,Redis会对AOF进行重写。比如base_size是64m,那么下一次就是128m,没有到达128就不会重写。

5、AOF小结

优势:
1、备份机制更稳健,丢失数据概率更低,数据一致性比RDB好。

2、可读的日志文本,通过操作AOF稳健,可以处理误操作

劣势:

1、比起RDB占用更多的磁盘空间

        只记录有哪些key

2、恢复备份速度要慢

        因为记录的全是一些写指令,要重新执行一遍

3、每次读写都同步的话,有一定的性能压力 

3、选择RDB还是AOF?

官方文档地址:https://redis.io/topics/persistence

       官方推荐两个都启用

如果只做缓存:如果你只希望你的数据在服务器运行的时候存在, 你也可以不使用任何持久化方式

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

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

相关文章

[ctfshow web入门] web77

信息收集 上一题的读取flag方式不能用了&#xff0c;使用后的回显是&#xff1a;could not find driver 解题 同样的查目录方法 cvar_export(scandir("glob:///*"));die();cforeach(new DirectoryIterator("glob:///*") as $a){echo($a->__toString…

每日算法刷题Day8 5.16:leetcode定长滑动窗口4道题,用时1h

5. 2379.得到k个黑块的最少涂色次数(简单) 2379. 得到 K 个黑块的最少涂色次数 - 力扣&#xff08;LeetCode&#xff09; 思想 1.返回至少出现 一次 连续 k 个黑色块的 最少 操作次数 2.还是定长k&#xff0c;统计量就是把白色变成黑色的操作次数&#xff0c;无需记录当前有…

很啰嗦,再次总结 DOM

DOM (文档对象模型) 详解 一、DOM 基础概念 1. 定义与作用 DOM&#xff08;Document Object Model&#xff09;即文档对象模型&#xff0c;是一种用于 HTML 和 XML 文档的编程接口。它将文档解析为一个由节点和对象组成的树状结构&#xff0c;允许程序和脚本动态访问、修改文…

ES6 (ECMAScript 2015) 详解

文章目录 一、ES6简介1.1 什么是ES6&#xff1f;1.2 为什么要学习ES6&#xff1f;1.3 浏览器支持情况 二、let和const关键字2.1 let关键字2.2 const关键字2.3 var、let和const的选择 三、箭头函数3.1 基本语法3.2 箭头函数的特点3.3 何时使用箭头函数 四、模板字符串4.1 基本语…

LeetCode 746 使用最小花费爬楼梯

当然可以&#xff01;LeetCode 746 是一道经典的动态规划入门题&#xff0c;我来用 C 为你详细解释。 题目描述 给定一个整数数组 cost&#xff0c;其中每个元素 cost[i] 表示从第 i 个台阶向上爬需要支付的费用。一旦支付费用&#xff0c;你可以选择向上爬 1 步 或 2 步。 你…

6.1.1图的基本概念

基本概念 图&#xff1a; 顶点集边集 顶点集&#xff1a;所有顶点的集合&#xff0c;不能为空&#xff08;因为图是顶点集和边集组成&#xff0c;其中一个顶点集不能为空&#xff0c;则图肯定不为空&#xff09; 边集&#xff1a;所有边的集合&#xff0c;边是由顶点集中的2…

WeakAuras Lua Script [TOC BOSS 5 - Anub‘arak ]

WeakAuras Lua Script [TOC BOSS 5 - Anubarak ] 阿努巴拉克 - 小强中虫范围 插件 !WA:2!DE1B0Xrvv8UmuRmIqZwiaXQmgKycwsYUPjPLZPTz3nBYULKnBNDtlYP6o)7T7mMzNz6BMnnBefBqGacIUOsXIkSIki)rCbLkIhLi6h8t3to6h9G2dXt4R9d(rR33mt2MyepQ75KSV3BUZ9FV7VF37g54rDvgU)yX7)GrRgvlQ2Y…

【C/C++】深度探索c++对象模型_笔记

1. 对象内存布局 (1) 普通类&#xff08;无虚函数&#xff09; 成员变量排列&#xff1a;按声明顺序存储&#xff0c;但编译器会根据内存对齐规则插入填充字节&#xff08;padding&#xff09;。class Simple {char a; // 1字节&#xff08;偏移0&#xff09;int b; …

湖北理元理律师事务所:债务优化中的双维支持实践解析

在债务压力与生活质量失衡的社会议题下&#xff0c;法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式&#xff0c;探索债务优化与生活保障的平衡路径&#xff0c;其方法论或为行业提供实践参考。 法律框架&…

Python uv包管理器使用指南:从入门到精通

Python uv包管理器使用指南&#xff1a;从入门到精通 作为一名Python开发者&#xff0c;你是否曾经为虚拟环境管理和依赖包安装而头疼&#xff1f;今天我要向大家介绍一个强大的工具——uv包管理器&#xff0c;它将彻底改变你的Python开发体验。 什么是uv包管理器&#xff1f…

Windows系统安全加固

掌握的加固点&#xff1a; 用户系统检查 口令策略检查 日志审计检查 安全选项检查 信息保护检查 2.2.1 用户系统检查 #检查系统版本内核 判断依据&#xff1a;无 检查方式&#xff1a;命令 msinfo32 dxdiag查看 #检查Administrator账号是否停用 判断依据&#xff1a;禁…

小蜗牛拨号助手用户使用手册

一、软件简介 小蜗牛拨号助手是一款便捷实用的拨号辅助工具&#xff0c;能自动识别剪贴板中的电话号码&#xff0c;支持快速拨号操作。最小化或关闭窗口后&#xff0c;程序将在系统后台运行&#xff0c;还可设置开机自启&#xff0c;方便随时使用&#xff0c;提升拨号效率。 …

c/c++消息队列库RabbitMQ的使用

RabbitMQ C 消息队列组件设计与实现文档 1. 引言 1.1. RabbitMQ 简介 RabbitMQ 是一个开源的消息代理软件&#xff08;也称为面向消息的中间件&#xff09;&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;。RabbitMQ 服务器是用 Erlang 语言编写的&#…

线程(二)OpenJDK 17 中线程启动的完整流程用C++ 源码详解之主-子线程通信机制

深入解析OpenJDK 17中Java线程的创建与主-子线程通信机制 引言 在Java中&#xff0c;线程的创建与启动通过Thread.start()实现&#xff0c;但底层是JVM与操作系统协作完成的复杂过程。本文基于OpenJDK 17的C源码&#xff0c;揭秘Java线程创建时主线程与子线程的通信机制&…

多线程爬虫语言选择与实现

之前文中有人提到&#xff1a;想要一个简单易用、能快速实现多线程爬虫的方案&#xff0c;而且目标是小网站&#xff0c;基本可以确定对反爬虫措施要求不高&#xff0c;这些就比较简单了。 以往我肯定要考虑常见的编程语言中哪些适合爬虫。Python、JavaScript&#xff08;Node…

AMD Vivado™ 设计套件生成加密比特流和加密密钥

概括 重要提示&#xff1a;有关使用AMD Vivado™ Design Suite 2016.4 及更早版本进行 eFUSE 编程的重要更新&#xff0c;请参阅AMD设计咨询 68832 。 本应用说明介绍了使用AMD Vivado™ 设计套件生成加密比特流和加密密钥&#xff08;高级加密标准伽罗瓦/计数器模式 (AES-GCM)…

Unity3D仿星露谷物语开发44之收集农作物

1、目标 在土地中挖掘后&#xff0c;洒下种子后逐渐成长&#xff0c;然后使用篮子收集成熟后的农作物&#xff0c;工具栏中也会相应地增加该农作物。 2、修改CropStandard的参数 Assets -> Prefabs -> Crop下的CropStandard&#xff0c;修改其Box Collider 2D的Size(Y…

list重点接口及模拟实现

list功能介绍 c中list是使用双向链表实现的一个容器&#xff0c;这个容器可以实现。插入&#xff0c;删除等的操作。与vector相比&#xff0c;vector适合尾插和尾删&#xff08;vector的实现是使用了动态数组的方式。在进行头删和头插的时候后面的数据会进行挪动&#xff0c;时…

CE17.【C++ Cont】练习题组17(堆专题)

目录 1.P2085 最小函数值 题目 分析 方法1:暴力求解 方法2:二次函数的性质(推荐!) 代码 提交结果 2.P1631 序列合并 分析 方法1:建两个堆 第一版代码 提交结果 第二版代码 提交结果 第三版代码 提交结果 方法2:只建一个堆 代码 提交结果 1.P2085 最小函数值…

题单:表达式求值1

题目描述 给定一个只包含 “加法” 和 “乘法” 的算术表达式&#xff0c;请你编程计算表达式的值。 输入格式 输入仅有一行&#xff0c;为需要计算的表达式&#xff0c;表达式中只包含数字、加法运算符 和乘法运算符 *&#xff0c;且没有括号。 所有参与运算的数字不超过…