GoLong的学习之路,进阶,Redis

这个redis和上篇rabbitMQ一样,在之前我用Java从原理上进行了剖析,这里呢,我做项目的时候,也需要用到redis,所以这里也将去从怎么用的角度去写这篇文章。

文章目录

  • 安装redis以及原理
  • redis概念
    • redis的应用场景有很多
    • redis常用的数据类型
  • 使用redis
    • 连接
    • 普通连接模式
    • TLS连接模式
    • Redis Sentinel模式
    • Redis Cluster模式
    • 操作数据
      • 特殊
    • 数据结构的处理
    • Pipeline(缓冲读写)
      • 使用`Pipelined` 方法,它会在函数退出时调用` Exec`
    • 事务
      • Watch
    • GET 、SET和WATCH 的示例

安装redis以及原理

安装redis其实很简单,我这里用的是阿里云,所以给出阿里云的安装文件文档,但是在没有用阿里云的时候,其实也有其他的方式。

这里献上,安装redis及其原理的一篇文章,这篇文章是以Java来讲解的,但是本质是没有区别的。想看原理的朋友可以看这里。

redis概念

Redis是一个开源的内存数据库,Redis提供了多种不同类型的数据结构,很多业务场景下的问题都可以很自然地映射到这些数据结构上。除此之外,通过复制、持久化和客户端分片等特性,我们可以很方便地将Redis扩展成一个能够包含数百GB数据、每秒处理上百万次请求的系统。

redis的应用场景有很多

  • 缓存系统,减轻主数据库(MySQL)的压力。
  • 计数场景,比如微博、抖音中的关注数和粉丝数。
  • 热门排行榜,需要排序的场景特别适合使用ZSET。
  • 利用 LIST 可以实现队列的功能。
  • 利用 HyperLogLog 统计UV、PV等数据。
  • 使用 geospatial index 进行地理位置相关查询。
  • 会话存储:保存用户的登录信息,原本的session里存储会话,只支持一次,诺是在分布式下,会使得,用户登录需要将这些分布式服务器都登录才可以,而redis就能很好的解决这个问题。
  • 存储普通缓存:列如详情页等数据的缓存信息存储。
  • 实现分布式锁:redis 可以非常方便的实现微服务选的分布式锁,redis 天然支持分布式服务。也可以使用zookeeper实现分布式锁
  • 简单的消息队列:redis 自身提供的发布订阅模式,可以用来实现简单的消息队列

redis常用的数据类型

  • String:(字符串):
    常见的使用场景是存储session信息,存储缓存信息如详情页缓存,存储整数信息可使用incr实现整数 + 1和使用decr实现整数 - 1。
  • list:(列表类型):
    常见使用场景式简单的消息队列,存储某项列表数据。
  • Hash:(哈希表):
    常见使用场景是存储session信息存储商品的购物车,购物车非常适合用哈希字典表示,使用人员唯一编号作为字典的key value值,可以存储商品的ID和数量等信息,存储详情页信息。
  • Set:(集合):
    一个无序并唯一的兼职集合,它的常见使用场景是实现关注功能,比如关注我的人,我关注的人使用集合存储可以保证人员不重复。
  • Sorted Set :(有序集合):
    相比于set集合类型多了一个排序属性的 score (分值),它的常见使用场景是可以用来存储排名信息,关注列表功能,这样就可以根据关注实现排序展示了。

带范围查询的排序集合(sorted set)、bitmap、hyperloglog、带半径查询的地理空间索引(geospatial index)和流(stream)等数据结构。

使用redis

注意:
redis 7对应 v9redis 6 对应 v8

安装v8版本:

go get github.com/redis/go-redis/v8

导入:

import "github.com/redis/go-redis/v9"

连接

你敢信这东西的链接手法多种多样

普通连接模式

rdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // 密码DB:       0,  // 数据库PoolSize: 20, // 连接池大小
})

使用 redis.ParseURL 函数从表示数据源的字符串中解析得到 Redis 服务器的配置信息

opt, err := redis.ParseURL("redis://<user>:<pass>@localhost:6379/<db>")
if err != nil {panic(err)
}
rdb := redis.NewClient(opt)

TLS连接模式

使用的是 TLS 连接方式,则需要使用 tls.Config 配置

rdb := redis.NewClient(&redis.Options{TLSConfig: &tls.Config{MinVersion: tls.VersionTLS12,// Certificates: []tls.Certificate{cert},// ServerName: "your.domain.com",},
})

Redis Sentinel模式

搭建模式:哨兵模式

下面的命令连接到由Redis Sentinel管理的 Redis 服务器

rdb := redis.NewFailoverClient(&redis.FailoverOptions{MasterName:    "master-name",SentinelAddrs: []string{":9126", ":9127", ":9128"},
})

在这里插入图片描述

Redis Cluster模式

搭建模式:集群模式

命令连接到 Redis Clustergo-redis 支持按延迟或随机路由命令。

rdb := redis.NewClusterClient(&redis.ClusterOptions{Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"},// 若要根据延迟或随机路由命令,请启用以下命令之一// RouteByLatency: true,// RouteRandomly: true,
})

在这里插入图片描述

例子:

package mainimport ("fmt""github.com/go-redis/redis"
)// 声明一个全局的redisDb变量
var redisDb *redis.Client// 根据redis配置初始化一个客户端
func initClient() (err error) {redisDb = redis.NewClient(&redis.Options{Addr:     "localhost:6379", // redis地址Password: "",               // redis密码,没有则留空DB:       0,                // 默认数据库,默认是0})//通过 *redis.Client.Ping() 来检查是否成功连接到了redis服务器_, err = redisDb.Ping().Result()if err != nil {return err}return nil
}func main() {err := initClient()if err != nil {//redis连接错误panic(err)}fmt.Println("Redis连接成功")
}

Options参数详解

  • Network :网络类型 tcp 或者 unix, 默认是 tcp。
  • Addr :redis地址,格式 host:port
  • OnConnect :新建一个redis连接的时候,会回调这个函数
  • Password : redis密码,redis server没有设置可以为空
  • DB : redis数据库,序号从0开始,默认是0,可以不用设置
  • MaxRetries :redis操作失败最大重试次数,默认不重试。
  • MinRetryBackoff :最小重试时间间隔,默认是 8ms ; -1 表示关闭
  • MaxRetryBackoff:最大重试时间间隔,默认是 512ms; -1 表示关闭.
  • DialTimeout :redis连接超时时间,默认是 5 秒.
  • ReadTimeout :socket读取超时时间,默认 3 秒.
  • WriteTimeout :socket写超时时间
  • PoolSize :redis连接池的最大连接数,默认连接池大小等于 cpu个数 * 10
  • MinIdleConns :redis连接池最小空闲连接数。
  • MaxConnAge :redis连接最大的存活时间,默认不会关闭过时的连接.
  • PoolTimeout :从redis连接池获取一个连接之后,连接池最多等待这个拿出去的连接多长时间,默认是等待 ReadTimeout + 1 秒.
  • IdleTimeout :edis连接池多久会关闭一个空闲连接,默认是 5 分钟. -1 则表示关闭这个配置项
  • IdleCheckFrequency :多长时间检测一下,空闲连接,默认是 1 分钟. -1 表示关闭空闲连接检测
  • readOnly :只读设置,如果设置为true, redis只能查询缓存不能更新。

操作数据

redis基本的key/value操作,指的是针对value值的类型为字符串或者数字类型的读写操作

  • Set:给数据库中名称为key的string赋予值value,并设置失效时间,0为永久有效
  • Get:查询数据库中名称为key的value值
  • GetSet:设置一个key的值,并返回这个key的旧值
  • SetNX:如果key不存在,则设置这个key的值,并设置key的失效时间。如果key存在,则设置不生效
  • MGet:批量查询key的值。比如redisDb.MGet(“name1”,“name2”,“name3”)
  • MSet:批量设置key的值。redisDb.MSet(“key1”, “value1”,“key2”, “value2”,“key3”, “value3”)
  • Incr:Incr函数每次加一,key对应的值必须是整数或nil,否则会报错incr key1: ERR value is not an integer or out of range
  • ncrBy:IncrBy函数,可以指定每次递增多少,key对应的值必须是整数或nil
  • IncrByFloat:IncrByFloat函数,可以指定每次递增多少,跟IncrBy的区别是累加的是浮点
  • Decr:Decr函数每次减一,key对应的值必须是整数或nil,否则会报错
  • DecrBy:DecrBy,可以指定每次递减多少,key对应的值必须是整数或nil
  • Del:删除key操作,支持批量删除 redisDb.Del(“key1”,“key2”,“key3”)
  • Expire:设置key的过期时间,单位秒
  • Append:给数据库中名称为key的string值追加value

以上是主要的方法。

例子:

可以尝试先填写数据然后读取。

// doCommand go-redis基本使用示例
func doCommand() {ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)defer cancel()// 执行命令获取结果val, err := rdb.Get(ctx, "key").Result()fmt.Println(val, err)// 先获取到命令对象cmder := rdb.Get(ctx, "key")fmt.Println(cmder.Val()) // 获取值fmt.Println(cmder.Err()) // 获取错误// 直接执行命令获取错误err = rdb.Set(ctx, "key", 10, time.Hour).Err()// 直接执行命令获取值value := rdb.Get(ctx, "key").Val()fmt.Println(value)
}

特殊

任意方法:Do方法
go-redis 还提供了一个执行任意命令或自定义命令的 Do 方法,特别是一些 go-redis 库暂时不支持的命令都可以使用该方法执行。

这个方法的作用是向Redis服务器发送一个命令并返回执行结果。

源码接口

func (c *Client) Do(ctx context.Context, cmd string, args ...interface{}) *Cmd
// doDemo rdb.Do 方法使用示例
func doDemo() {ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)defer cancel()// 直接执行命令获取错误err := rdb.Do(ctx, "set", "key", 10, "EX", 3600).Err()fmt.Println(err)// 执行命令获取结果val, err := rdb.Do(ctx, "get", "key").Result()fmt.Println(val, err)
}

其中:

  • ctx是上下文,用于控制请求的生命周期。
  • cmd是要执行的Redis命令,比如"GET"、"SET"等。
  • args是传递给Redis命令的参数,比如键名、数值等。

Do方法的返回值是一个*Cmd类型,它代表了一个异步执行的命令,并且可以用来获取执行结果。

使用Do方法,你可以向Redis发送各种命令,并通过返回的*Cmd对象获取执行结果,比如获取值、处理错误等。这使得在Golang中使用Redis变得非常方便和灵活。

上面这个例子我是用的官方文档中的。如果有朋友试了,就会发现,这东西只能指向第一个key:value,第二个看存不存在,存在就不报错,不存在就报错,然后第二个直接无法写入。这个主打的就是一个扯淡。真不知这玩意出来时干啥的。

redis.Nil

go-redis 库提供了一个 redis.Nil 错误来表示 Key 不存在的错误。因此在使用go-redis时需要注意对返回错误的判断。在某些场景下我们应该区别处理redis.Nil和其他不为 nil 的错误。

// getValueFromRedis redis.Nil判断
func getValueFromRedis(key, defaultValue string) (string, error) {ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)defer cancel()val, err := rdb.Get(ctx, key).Result()if err != nil {// 如果返回的错误是key不存在if errors.Is(err, redis.Nil) {return defaultValue, nil}// 出其他错了return "", err}return val, nil
}

数据结构的处理

剩下的其实也就是对整这个数据结构的处理,包括string,hash,等集合类的操作。需要详细的说明的可以看这篇:非常详细的方法使用文章

Pipeline(缓冲读写)

Redis Pipeline 允许通过使用单个 client-server-client 往返执行多个命令来提高性能。区别于一个接一个地执行100个命令,你可以将这些命令放入 pipeline 中,然后使用1次读写操作像执行单个命令一样执行它们。这样做的好处是节省了执行命令的网络往返时间(RTT)。

	pipe := rdb.Pipeline()//添加计数器incr := pipe.Incr(cxt, "pipeline_counter")//设置过期时常pipe.Expire(cxt, "pipeline_counter", time.Hour)//Exec是将管道中缓冲的所有命令发送到redis-server。cmds, err := pipe.Exec(cxt)if err != nil {panic(err)}fmt.Println(cmds)fmt.Println(incr.Val())

Exec :Exec是将管道中缓冲的所有命令发送到redis-server。
Expire:设置过期时常
Incr:计数器
Discard:表示丢弃缓存中所有尚未执行的命令
Process:把要执行的命令放入流水线缓冲区中
Do:如果某个Redis命令还不支持,你可以使用Do来执行它。执行任何命令的API
Len:获取管道中尚未执行的命令的数量

使用Pipelined 方法,它会在函数退出时调用 Exec

var incr *redis.IntCmdcmds, err := rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {incr = pipe.Incr(ctx, "pipelined_counter")pipe.Expire(ctx, "pipelined_counter", time.Hour)return nil
})
if err != nil {panic(err)
}// 在pipeline执行后获取到结果
fmt.Println(incr.Val())

我们可以遍历pipeline命令的返回值依次获取每个命令的结果,示例代码中使用pipiline一次执行了100个 Get 命令,在pipeline 执行后遍历取出100个命令的执行结果。

cmds, err := rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {for i := 0; i < 100; i++ {pipe.Get(ctx, fmt.Sprintf("key%d", i))}return nil
})
if err != nil {panic(err)
}for _, cmd := range cmds {fmt.Println(cmd.(*redis.StringCmd).Val())
}

一次性执行多个命令的场景下,就可以考虑使用 pipeline 来优化。

事务

Redis 是单线程执行命令的,因此单个命令始终是原子的,但是来自不同客户端的两个给定命令可以依次执行,例如在它们之间交替执行。但是,Multi/exec能够确保在multi/exec两个语句之间的命令之间没有其他客户端正在执行命令。

在这种场景我们需要使用 TxPipelineTxPipelined 方法将 pipeline 命令使用 MULTI EXEC包裹起来。

// TxPipeline demo
pipe := rdb.TxPipeline()
incr := pipe.Incr(ctx, "tx_pipeline_counter")
pipe.Expire(ctx, "tx_pipeline_counter", time.Hour)
_, err := pipe.Exec(ctx)
fmt.Println(incr.Val(), err)// TxPipelined demo
var incr2 *redis.IntCmd
_, err = rdb.TxPipelined(ctx, func(pipe redis.Pipeliner) error {incr2 = pipe.Incr(ctx, "tx_pipeline_counter")pipe.Expire(ctx, "tx_pipeline_counter", time.Hour)return nil
})
fmt.Println(incr2.Val(), err)

相当于

MULTI
INCR pipeline_counter
EXPIRE pipeline_counts 3600
EXEC

Watch

搭配 WATCH命令来执行事务操作

从使用WATCH命令监视某个 key 开始,直到执行EXEC命令的这段时间里,如果有其他用户抢先对被监视的 key 进行了替换、更新、删除等操作,那么当用户尝试执行EXEC的时候,事务将失败并返回一个错误,用户可以根据这个错误选择重试事务或者放弃事务

源码接口

Watch(fn func(*Tx) error, keys ...string) error

Watch 方法搭配 TxPipelined 的使用示例:

// watchDemo 在key值不变的情况下将其值+1
func watchDemo(ctx context.Context, key string) error {return rdb.Watch(ctx, func(tx *redis.Tx) error {n, err := tx.Get(ctx, key).Int()if err != nil && err != redis.Nil {return err}// 假设操作耗时5秒// 5秒内我们通过其他的客户端修改key,当前事务就会失败time.Sleep(5 * time.Second)_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {pipe.Set(ctx, key, n+1, time.Hour)return nil})return err}, key)
}

将上面的函数执行并打印其返回值,如果我们在程序运行后的5秒内修改了被 watch 的 key 的值,那么该事务操作失败,返回redis: transaction failed错误。

GET 、SET和WATCH 的示例

go-redis 官方文档中使用 GETSETWATCH命令实现一个 INCR 命令的完整示例

// 此处rdb为初始化的redis连接客户端
const routineCount = 100// 设置5秒超时
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()// increment 是一个自定义对key进行递增(+1)的函数
// 使用 GET + SET + WATCH 实现,类似 INCR
increment := func(key string) error {txf := func(tx *redis.Tx) error {// 获得当前值或零值n, err := tx.Get(ctx, key).Int()if err != nil && err != redis.Nil {return err}// 实际操作(乐观锁定中的本地操作)n++// 仅在监视的Key保持不变的情况下运行_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {// pipe 处理错误情况pipe.Set(ctx, key, n, 0)return nil})return err}// 最多重试100次for retries := routineCount; retries > 0; retries-- {err := rdb.Watch(ctx, txf, key)if err != redis.TxFailedErr {return err}// 乐观锁丢失}return errors.New("increment reached maximum number of retries")
}// 开启100个goroutine并发调用increment
// 相当于对key执行100次递增
var wg sync.WaitGroup
wg.Add(routineCount)
for i := 0; i < routineCount; i++ {go func() {defer wg.Done()if err := increment("counter3"); err != nil {fmt.Println("increment error:", err)}}()
}
wg.Wait()
n, err := rdb.Get(ctx, "counter3").Int()
fmt.Println("最终结果:", n, err)

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

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

相关文章

【开源】基于Vue+SpringBoot的创意工坊双创管理系统

项目编号&#xff1a; S 049 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S049&#xff0c;文末获取源码。} 项目编号&#xff1a;S049&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、…

nodejs 沙盒逃逸

1.[GFCTF 2021]ez_calc 一道很有意思的一道nodejs的题 沙箱逃逸和绕过&#xff1a; F12 看源码 if(req.body.username.toLowerCase() ! admin && req.body.username.toUpperCase() ADMIN && req.body.passwd admin123){ // 登录成功&am…

如何关闭vue项目中的[eslint]校验

要关闭Vue项目中的ESLint校验&#xff0c;可以按照以下步骤进行操作&#xff1a; 打开项目根目录下的.eslintrc.js文件&#xff08;如果没有该文件&#xff0c;则创建一个新的&#xff09;。在文件中添加以下代码&#xff1a;module.exports {// 其他配置项...rules: {// 禁用…

Qt MVC示例 simpletreemodel 树模型

Qt MVC示例 simpletreemodel 树模型 从文本中读取树模型数据&#xff0c;缩进代表子项 TreeItem 表示一行字符串数据 treeitem.h #ifndef TREEITEM_H #define TREEITEM_H#include <QList> #include <QVariant>//! [0] class TreeItem { public:explicit Tree…

聚焦清晰度评价指标所用到的各种算法

首先&#xff0c;我想吐槽一下&#xff0c;看了好几篇聚焦评价函数的文章&#xff0c;说到底都是一篇文章转载或者重复上传&#xff0c;介绍了将近 15 种清晰度的算法&#xff0c;原文找了半天都没找到在哪&#xff0c;最多也仅能找到一些比较早的转载。 无参考图像的清晰度评…

习题3-5 三角形判断

习题3-5 三角形判断 给定平面上任意三个点的坐标(x1​,y1​)、(x2​,y2​)、(x3​,y3​)&#xff0c;检验它们能否构成三角形。 输入格式: 输入在一行中顺序给出六个[−100,100]范围内的数字&#xff0c;即三个点的坐标x1​、y1​、x2​、y2​、x3​、y3​。 输出格式: 若这3个…

压缩字符串II

null备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/string-compression/description/ 给你一个字符数组 chars &#xff0c;请使用下述算法压缩&#xff…

Moonbeam生态项目分析 — — 去中心化交易所Beamswap

流动性激励计划Moonbeam Ignite是帮助用户轻松愉快体验Moonbeam生态的趣味活动。在Moonbeam跨链连接的推动下&#xff0c;DeFi的各种可能性在这里爆发。DeFi或许不热门&#xff0c;但总有机会捡漏&#xff0c;了解Monbeam生态项目&#xff0c;我们邀请Moonbeam大使分享他们的研…

数学 --笔试、面试高频

数学 排列组合 10个相同的糖果&#xff0c;分给三个人&#xff0c;每个人至少要得一个。有()种不同分法 10个糖果&#xff0c;中间正好9个空挡&#xff0c;从这9个空挡中任意取出2个作为分割点&#xff0c;正好能把糖果分为3份&#xff0c;并且保证每一份中至少有一个糖果。…

动手学深度学习(五)---模型选择、过拟合、欠拟合

文章目录 一、理论知识1.训练误差和泛化误差 【相关总结】 一、理论知识 1.训练误差和泛化误差 训练误差&#xff1a;模型在训练数据上的误差泛化误差&#xff1a;模型在新数据上的误差 ex:根据摸底考试成绩来预测未来考试分数在过去的考试中表现很好&#xff08;训练误差&am…

【教程】 一文部署配置并入门 Redis

综述 什么是Redis Redis官网——Redis.io Redis, 作为一个高性能的键值对数据库&#xff0c;主要应用于以下场景&#xff1a; 缓存系统&#xff1a;由于其高速读写能力&#xff0c;Redis 非常适合用作缓存系统&#xff0c;减少数据库负载。 会话存储&#xff08;Session St…

【九日集训】第五天:排序

今天主要学习了C语言中的排序API,Qsort()本质上还是使用快速排序实现的; 具体使用方法:qsort(待排序数组, 数组长度, 每个元素字节长 sizeof(int), 比较函数) 比较函数 比较函数决定当前排序是升序还是降序,传入两个参数,返回1则交换,-1和0则不交换 一般使用方法 int cmp(…

在Spring Boot中使用不同的日志

前言&#xff0c;本篇就是介绍在Java中使用相关的日志&#xff0c;适合初学者看&#xff0c;如果对这篇不感兴趣的可以移步了&#xff0c;本篇主要围绕我们Java中的几种日志类型&#xff0c;也说不上有多深入&#xff0c;算的上浅入浅出吧&#xff0c;如果你有一段时间的开发经…

单片机_RTOS_架构

一. RTOS的概念 // 经典单片机程序 void main() {while (1){喂一口饭();回一个信息();} } ------------------------------------------------------ // RTOS程序 喂饭() {while (1){喂一口饭();} }回信息() {while (1){回一个信息();} }void main() {create_task(喂饭);cr…

OpenHarmony 4.0 Release 编译及报错

1、环境准备 安装下面这三东西&#xff0c;是为了下载 Harmony 源码 sudo apt install curl sudo apt install python3-pip sudo apt install git-lfs 安装下面这五个东西&#xff0c;是为了解决编译到最后报错(头铁不信的&#xff0c;你可以试试&#xff0c;等最后再安装) …

opencv常用函数表

函数名功能说明cv2.imread()读取图像文件cv2.imshow()显示图像窗口cv2.imwrite()保存图像文件cv2.cvtColor()颜色空间转换cv2.resize()图像缩放cv2.flip()图像翻转cv2.rectangle()绘制矩形cv2.circle()绘制圆形cv2.line()绘制直线cv2.putText()绘制文本cv2.bitwise_and()与操作…

【Hadoop】集群资源管理器 YARN

一、yarn 简介 Apache YARN (Yet Another Resource Negotiator) 是 hadoop 2.x 引入的分布式资源管理系统。主要用于解决 hadoop 1.x 架构中集群资源管理和数据计算耦合在一起&#xff0c;导致维护成本越来越高的问题。 yarn主要负责管理集群中的CPU和内存 用户可以将各种服…

linux 中断管理机制

中断的概念 中断是指在CPU正常运行期间&#xff0c;由于内外部事件或由程序预先安排的事件引起的 CPU 暂时停止正在运行的程序&#xff0c;转而为该内部或外部事件或预先安排的事件服务的程序中去&#xff0c;服务完毕后再返回去继续运行被暂时中断的程序。Linux中通常分为外部…

yolov1网络结构说明

文章目录 一. 网络结构二. 网络说明1. 网络的输入2. 网络的输出(1) 5 5表示:每个网格使用两个先验框进行预测。(2) “5”表示&#xff1a;每个先验框包含的预测信息的数量。(3) 20表示&#xff1a;20个分类预测值(4) 每个网格能预测几个目标&#xff1f; 一. 网络结构 论文下…

在日常工作中怎么处理vue项目中的错误的?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue项目中的错误如何处理 目录 一、错误类型 二、如何处理 后端接口错误 代码逻辑问题 全局设…