Redis生产环境最佳实践

2024-01-04

????????????????????????????????
欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术 的推送
发送 资料 可领取 深入理解 Redis 系列文章结合电商场景讲解 Redis 使用场景 中间件系列笔记 编程高频电子书
文章导读地址: 点击查看文章导读!
????????????????????????????????

Redis 生产环境最佳实践

在这里插入图片描述

为什么要写这篇文章呢?

因为我发现大多数朋友,在学习完 Redis 之后,发现还是对如何在项目中进行使用不太清楚,只了解简单的将数据按照 k-v 的方式放在缓存中,对于生产环境中许多场景的解决方案都不了解,下边将从各个场景来讲解 Redis 在生产环境中如何使用,这里主要讲解思路以及流程,具体的代码就不列出来了,只要知道思路,无论是通过已有代码还是网络资源都还是很好实现的!而且在面试中,面试官也更看重你解决问题的思路。因此,本文将详细介绍 Redis 在生产环境中的最佳实践,帮助大家更好地理解并应用它们!

Redis 生产环境解决方案

读多写少数据缓存方案

首先,对于用户数据,到底需不需要缓存呢?

这里举个例子,就比如在某红书中,对于热门用户,他的信息肯定是会被很多人看到的,像用户的数据特点就是: 读多写少 ,读操作很多的数据是非常适合放到缓存中去的,那么如何缓存呢?

  • 缓存的时间设置:可以设置为 2 个小时 + 随机几小时(添加随机几小时的原因是避免大量缓存同时过期,导致请求全部打到数据库中)
  • 缓存的 key 设置:根据 member_user:[userId] 作为 key 即可,value 存储需要查询的用户信息的 json 串
  • 数据放入缓存的时机:在获取用户信息的时候,先去缓存中取,如果没有,再去数据库中查,查出来之后放入到缓存

这里是对 缓存 + 数据库 进行双写

但是在多线程并发的情况下,可能会造成 缓存数据库双写不一致 的情况,如下:

  • 当读线程去缓存中读取数据,此时缓存中数据正好过期,那么该线程就去读数据库中的数据
  • 此时写线程开始执行,修改用户信息,并且写入数据库,再写入缓存
  • 此时读线程再接着执行,将之前在数据库中读取的旧数据写入缓存,覆盖了写线程更新后的数据

那么如何解决 缓存数据库双写不一致 呢?

加锁,将读操作和写操作执行之前,加上同一把锁,让读写操作串行化即可: user_info_lock

整体的流程如下:

在这里插入图片描述

高并发场景下优化

在高并发场景中,我们如果使用上边的这种方案会出现 大量线程阻塞 的问题,具体如下:

  1. 如果某一个用户突然火了,这时会有大量用户来请求这个用户的数据
  2. 如果恰巧这个用户的数据不在缓存中,那么会有大量的读操作线程阻塞在加锁 user_update_lock 这个步骤中等待拿锁

那么此时多线程大量的并发操作就成为了 串行拿锁 了,大大影响系统的性能,怎么解决呢?

等待加锁的操作添加一个超时时间 即可,可以设置个 200ms,这样大量的线程如果在 200ms 都拿不到锁,就直接获取锁失败,不会再串行阻塞获取锁, 串行转并行 ,如下图(粉色部分为优化):

在这里插入图片描述

分页数据缓存构建方案

在现在系统中,大部分数据都是通过 分页 进行查询的,那么针对于分页的数据,肯定就需要构建分页缓存,这里就需要考虑两个点:

  • 分页缓存的构建时机?
  • 分页缓存 key 和 value 如何设计?

先假设一种业务场景,这样下边说的时候也比较清楚一些,还是以某红书为例,要访问一个用户主页的作品,要对用户主页的作品进行分页缓存的构建

先来说一下缓存构建的时机,有两个:

  • 当其他用户来查询用户 A 的主页时,先查数据库,查到之后,再进行 缓存的构建操作
  • 当用户 A 新增分享的时候,用户 A 主页的数据发生变化,此时进行 缓存的重建操作

但是会出现 缓存数据库不一致 的情况,如下:

  1. 另一个用户 B 此时正好来查询用户 A 的分享列表,用户 B 线程先去缓存中查询,发现没有,再去数据库中查询用户 A 的分享列表,此时 B 拿到了 A 新增分享之前的旧数据
  2. 此时如果用户 A 新增分享并落库,并且去缓存中对用户 A 的列表缓存进行重建,那么此时缓存列表中是用户 A 的最新数据
  3. 但是此时用户 B 的线程在数据库中已经查到了用户 A 的旧数据,用户 B 的线程继续执行,将用户 A 的旧数据给放入到列表缓存中,覆盖掉了用户 A 更新的缓存,那么此时就会导致 缓存数据库不一致

如何解决呢?当然是 加锁 ,在两个构建缓存的地方加锁,保证串行化即可,如下图

查询用户列表时,分页缓存的构建流程:

在这里插入图片描述

用户新增或修改内容时,对分页缓存重建流程:

在这里插入图片描述

那么同样,在获取锁的时候需要加阻塞等待获取锁的 超时时间 ,大量用户线程阻塞在获取锁的地方,有了获取锁的超时时间

接下来说一下分页缓存中 key 和 value 如何设计:

首先,分页数据是由 pageNo 和 pageSize 控制的,可以将 pageSize 大小给固定,这样直接根据 pageNo 就可以查询出某一页的分页数据了,key 设计为: user_homedata:page:{userId}:{pageNo}

在数据库中查询出来分页数据之后,将分页数据转为 JSON 串之后,传入 Redis 缓存中即可

缓存穿透解决方案
如果大量恶意请求查询数据库中不存在的数据,那么缓存中肯定是没有的,就会导致大量请求打到数据库中,造成缓存穿透

解决方案就是在查询到数据库中不存在的数据之后,在 Redis 中也缓存起来,缓存为一个字符串: "{}" 即可,这样重复查询不存在的数据就不会打到数据库中了

空缓存的 过期时间 可以设置的短一些,避免大量的空缓存占用缓存空间

写多读少、写多读多数据缓存方案

什么时候出现 写多读少 或者 写多读多 的场景呢?

就比如说电商场景中的 购物车 功能,面临着 高并发读 高并发写

解决方案:在购物车中,就以 Redis 作为主存储,通过 MQ 异步将数据落库持久化 ,来提升系统性能!

那么在购物车中,需要缓存哪些数据呢?

  • 用户购物车已有商品的数量:使用 hash 结构存储,可以在用户添加商品到购物车中时,判断购物车中的商品是否达到购物车的上限
  • 商品的详情信息:使用 hash 结构存储
  • 购物车中商品的顺序:使用 zset 存储,存储商品的 id,根据商品加入到购物车的时间进行排序

那么在缓存中查询购物车中的商品时,会先在 Redis 中查询购物车中商品的顺序,根据顺序查出一系列商品 id,再根据商品 id 查询到商品的详情信息

下边看一下这 3 个数据在 Redis 中的存储结构:

用户购物车已有商品的数量:

# 使用 hash 结构存储,有 3 个部分,key、field、value
key    shopping_cart_hash:{userId}
field  skuId # 商品id
value  商品详情 json 串
# 整体的存储结构为:
shopping_cart_extra_hash:{userId} {
  {skuId}: "商品详情json串",
  {skuId}: "商品详情json串"
}

购物车中商品的详情信息:

# 使用 hash 存储
key -> shopping_cart_extra_hash:{userId}
field -> skuId
value -> 商品详情
# 存储结构为:
shopping_cart_extra_hash:{userId} {
  {skuId}: "商品详情json串",
  {skuId}: "商品详情json串"
}

购物车中商品的顺序:

# 存储结构为 zset,通过 score 排序
key    shopping_cart_zset:{userId}
value  skuId
score  System.currentTimeMillis()  # 分数使用当前系统的时间戳即可,按照加入购物车的时间对商品进行排序

这几个缓存数据可视化存储结构我也给画了出来,见下图:

在这里插入图片描述

分布式锁控制

这里在添加购物车的时候,注意添加分布式锁控制并发安全,避免同一个用户点了多次,但是没有加锁,导致丢失了几次该商品的添加

这里分布式锁的 key 设计为: UPDATE_CART_LOCK_KEY:{userId}:{skuId} ,通过 userId 和 skuId 来控制同一把锁,将 锁的粒度控制在商品级别 ,尽可能加大并发度

添加购物车商品时,在 Redis 中更新完毕,就通过 MQ 发送异步消息,将数据进行 落库操作 ,整体流程如下图:

在这里插入图片描述

高并发读写性能优化方案

先说一下业务场景,在库存模块中,需要进行 入库 出库 操作,并且在高峰期的时候,会有大量用户对库存进行高并发的读和写操作

性能优化解决方案:库存 分片存储 ,并且 渐进性写入

下边来说一下,如何进行具体的分片存储:

比如说某一个商品有 100 件库存,Redis 集群有 5 个节点,先将 100 个商品拆分为 5个分片(每个分片存储 20 个商品),再将 5 个分片分散到 Redis 集群的各个节点中,每个节点 1 个分片,那么也就是每个 Redis 节点存储 20 个商品库存

分片存储后,对于这个商品的 高并发 操作,就会被分散地打到多个 Redis 节点中,在分片存储的时候,一般将分片数量和 Redis 节点数设置的一样

在分片写入库存的时候,采用 渐进性写入 ,比如说新入库一个商品有 300 个,有 3 个 Redis 节点,那么我们分成 3 个分片的话,1 个 Redis 节点放 1 个分片,1 个分片存储 100 个商品,那么如果我们直接写入缓存,先写入第一个 Redis 节点 100 个库存,再写入第二个 Redis 节点 100 个库存,如果这时写入第三个 Redis 节点 100 个库存的时候失败了,那么就导致操作库存的请求压力全部在前两个 Redis 节点中,采用 渐进性写入 的话,流程为:我们已经直到每个 Redis 节点放 100 个库存了,那么我们定义一个轮次的变量,为 10,表示我们去将库存写入缓存中需要写入 10 轮,那么每轮就写入 10 个库存即可,这样写入 10 轮之后,每个 Redis 节点中也就有 100 个库存了,这样的好处在于,即使有部分库存写入失败的话,对于请求的压力也不会全部在其他节点上,因为写入失败的库存很小,很快时间就可以消耗完毕

基于 分片 的添加库存流程如下:

在这里插入图片描述

那么既然添加库存时使用 分片存储 了,在扣减库存的时候,也必须轮询 Redis 节点进行扣减库存,如果当前 Redis 节点上的库存不够扣除,那么就去遍历下一个 Redis 节点查看库存是否足够,如果遍历完所有 Redis 节点都不够,那么就统计所有 Redis 节点上的库存总和是否足够,如果足够,则一个一个进行扣除,这时候还存在 扣除异常回滚 的情况,如果某一个 Redis 节点上扣除失败了,需要进行回滚,再将之前扣除的 Redis 节点上的库存给加回来,扣除库存的流程如下:

在这里插入图片描述

热 key 处理

热 key 问题就是某一瞬间可能某条内容特别火爆,大量的请求去访问这个数据,那么这样的 key 就是热 key,往往这样的 key 也是存储在了一个 redis 节点中,对该节点压力很大

那么对于热 key 的处理就是通过热 key 探测系统对热 key 进行计数,一旦发现了热 key,就将热 key 在 jvm 本地缓存中再存储一份,那么当再有大量请求来读取时,就直接在应用的 jvm 缓存中读取到直接返回了,不会再将压力给到同一个 redis 节点中了,如下图:

在这里插入图片描述

京东开源了 高性能热 key 探测中间件:JD-hotkey ,可以实时探测出系统的热数据,生产环境中可以基于 JD-hotkey 来解决热 key 的问题

大 key 处理

大 key 问题是指在 Redis 中某一个 key 所存储的 value 值特别大,几个 mb 或者几十 mb,那么如果频繁读取大 key,就会导致大量占用网络带宽,影响其他网络请求

对于大 key 会进行特殊的切片处理,并且要对大 key 进行监控,如果说发现超过 1mb 的大 key,则进行报警,并且自动处理,将这个大 key 拆成多个 k-v 进行存储,比如将 big-key 拆分为 —> big-key01,big-key02 ...

那么大 key 的解决方案如下:

  • 通过 crontab 定时调度 shell 脚本,每天凌晨通过 rdbtools 工具解析 Redis 的 rdb 文件,过滤 rdb 文件中的大 key 导出为 csv 文件,然后使用 SQL 导入 csv 文件存储到 MySQL 中的表 redis_large_key_log
  • 使用 canal 监听 MySQL 的 redis_large_key_log 表的 binlog 日志,将增量数据发送到 RocketMQ 中(这里该表的增量数据就是解析出来的大 key,将大 key 的数据发送到 MQ 中,由 MQ 消费者来决定如何对这些大 key 进行处理)
  • 在 MQ 的消费端可以通过一个大 key 的处理服务来对大 key 进行切分,分为多个 k-v 存储在 Redis 中

那么在读取大 key 的时候,需要判断该 key 是否是大 key,如果是的话,需要对多个 k-v 的结果进行拼接并返回

数据库与缓存最终一致性的解决方案

如果不采用更新数据时双写来保证数据库与缓存的一致性的话,可以通过 canal + RocketMQ 来实现数据库与缓存的最终一致性,对于数据直接更新 DB,通过 canal 监控 MySQL 的 binlog 日志,并且发送到 RocketMQ 中,MQ 的消费者对数据进行消费并解析 binlog,过滤掉非增删改的 binlog,那么解析 binlog 数据之后,就可以知道对 MySQL 中的哪张表进行 增删改 操作了,那么接下来我们只需要拿到这张表在 Redis 中存储的 key,再从 Redis 中删除旧的缓存即可,那么怎么取到这张表在 Redis 中存储的 key 呢?

可以我们自己来进行配置,比如说监控 sku_info 表的 binlog,那么在 MQ 的消费端解析 binlog 之后,就知道是对 sku_info 表进行了增删改的操作,那么假如 Redis 中存储了 sku 的详情信息,key 为 sku_info:{skuId} ,那么我们就可以在一个地方对这个信息进行配置:

// 配置下边这三个信息
tableName = "sku_info"; // 表示对哪个表进行最终一致性
cacheKey = "sku_info:"; // 表示缓存前缀
cacheField = "skuId"; // 缓存前缀后拼接的唯一标识

// data 是解析 binlog 日志后拿到的 key-value 值,data.get("skuId") 就是获取这一条数据的 skuId 属性值
// 如下就是最后拿到的 Redis 的 key
redisKey = cacheKey + data.get(cacheField)

那么整体的流程图如下:

在这里插入图片描述

Redis 集群故障探测

在生产环境中,如果 Redis 集群崩溃了,那么会导致大量的请求打到数据库中,会导致整个系统都崩溃,所以系统需要可以识别缓存故障,限流保护数据库,并且启动接口的降级机制

降级方案设计
我们在系统中操作 Redis 一般都是通过工具类来进行操作的,假设工具类有两个 RedisCache RedisLock ,那么通过 AOP 对这两个工具类的所有方法 做一个切面 ,如果在这两个类中执行 Redis 操作时,Redis 挂掉了,就会抛出异常(Redis 连接失败),那么我们在切面的处理方法上捕捉异常,再记录下来,判断是 Redis 集群挂了还是展示网络波动

判断是集群挂掉还是网络波动的话,我们可以配置规则,比如 30 秒内出现了 3 次 Redis 连接失败,就认为 Redis 挂掉了(可以使用 Hotkey 配置规则),那么如何自动恢复呢?可以设置 hotkey 中的缓存过期时间,设置为 60 秒,那么缓存过期之后,会再次尝试去操作 Redis,如果 Redis 恢复了就可以正常使用了,如果还没有恢复,会继续向 hotkey 中 set 数据

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis生产环境最佳实践 的相关文章

  • 如何在实时添加对象时从 Redis 中弹出对象?

    我想让 Node js 进程运行 因为它正在检查 Redis 服务器是否有任何新的弹出内容 另一个进程将偶尔进行推送 而 Node 进程将尝试弹出任何进来的内容 Node 进程将保持运行 有人能给我指出一个好的方向吗 我正在尝试找出如何监听
  • 是否可以使用带有 FUSE 文件系统的 Linux VFS 缓存?

    默认情况下 Linux VFS 缓存似乎不适用于 FUSE 文件系统 例如 read 调用似乎被系统地转发到 FUSE 文件系统 我在 FUSE 特定的远程文件系统上工作 我需要一个非常积极的缓存 我需要实现自己的页面缓存吗 或者是否可以为
  • 如何在redis中创建自己的数据库?

    There are 0 to 15 databases in redis 我想使用 redis cli 创建自己的数据库 有什么命令可以实现吗 Redis 数据库并不等同于 MySQL 等 DBMS 中的数据库名称 这是一种为键创建隔离和命
  • 如何从 python 将无穷大传递给 redis?

    我正在使用 redis py 并希望将 inf 和 inf 与 ZRANGEBYSCORE 一起使用 我尝试使用 inf 的字符串和浮点来执行此操作 但它们返回一个空集 我怎样才能做到这一点 EDIT 我尝试执行以下命令 redis Str
  • Node.js 上通过套接字连接 Redis

    由于共享托管 目标主机上的我的 redis 服务器不在端口上运行 而是在非常特定的套接字上运行 可以通过套接字文件连接到该套接字 只有我的用户可以访问 但是 我还没有找到如何通过套接字指定连接node redis and connect r
  • Redis 块推送直到列表有空位

    我正在寻找类似的东西BLPUSH该命令将阻塞 直到列表的长度低于指定值max size 目的是防止生产者运行速度快于消费者时列表无限增长 功能与 python 非常相似Queue put https docs python org 3 li
  • redis集群不断打印日志WSA_IO_PENDING

    当我启动redis集群的所有redis服务器时 所有这些服务器不断打印类似WSA IO PENDING clusterWriteDone的日志 9956 03 Feb 18 17 25 044 WSA IO PENDING writing
  • Redis键空间事件不触发

    我有两个 Redis 客户端 在一个文件中我有一个简单的脚本设置并删除了 Redis 键 var redis require redis var client redis createClient 6379 127 0 0 1 client
  • 如何统计 Redis 流中未读或已确认的消息?

    使用 Redis 5 0 3 假设我们创建一个名为streamy和一个消费群体consumers XGROUP CREATE streamy consumers MKSTREAM 然后向其中添加一些消息 XADD streamy messa
  • 如何设置 Celery 以通过 ssl 与 Azure Redis 实例对话

    使用 的伟大答案 如何在microsoft azure上的django项目中配置celery redis https stackoverflow com questions 39616701 how to configure celery
  • 从redis中检索大数据集

    一台服务器上的应用程序查询另一台服务器上运行的 Redis 查询的结果数据集约为 250kzrangebyscore objects locations inf inf这在应用程序服务器上似乎需要 40 秒 当使用命令执行时redis cl
  • 如何将 ActionController::Live 与 Resque + Redis 一起使用(用于聊天应用程序)

    我正在尝试为我的 Rails 应用程序构建聊天功能 我在用ActionController Live Puma Resque Redis为了这 所以基本上在这种情况下 redissubscribe方法正在后台运行 使用resque 到目前为
  • 在 sidekiq 上配置 redis 身份验证

    我想我错过了一些东西 因为我在文档中找不到如何编写 redis 实例的用户名和密码以与 sidekiq 一起使用 有没有办法做到这一点 或者是通过 ENV 变量 Sidekiq 将无法识别的 Redis 选项直接传递给 Redis 驱动程序
  • SignalR 无法连接到 SSL 上的 Azure Redis

    我目前在 Azure 上托管我的 redis 缓存服务器 并让 signalR 依赖它作为骨干 使用以下内容 GlobalHost DependencyResolver UseRedis 服务器 端口 密码 eventKey 这可以在端口
  • 使用Redis从有限范围内生成唯一ID

    我有一些数据库项目 除了主键之外 还需要项目所属组的唯一索引 我们来调用属性nbr 以及将项目分组在一起并定义唯一范围的属性nbr 我们会打电话group This nbr必须在 1 N 范围内 并且may从外部源导入项目时进行设置 由于所
  • 有没有办法用Lettuce自动发现Redis集群中新的集群节点IP

    我有一个Redis集群 3主3从 运行在一个库伯内斯簇 该集群通过Kubernetes 服务 Kube 服务 我将我的应用程序服务器连接到 Redis 集群 使用Kube 服务作为 URI 通过 Redis 的 Lettuce java 客
  • Spring Data JPA Redis:无法编写基于自定义方法的查询

    我已经使用 Redis 配置了 Spring Data JPA 并使用RedisRepositorieswith 提供了类似的方法find findAll 所有这些方法似乎都工作得很好 但我无法编写我的自定义方法 RedisEntity f
  • 使用 Celery 通过 Gevent 进行实时、同步的外部 API 查询

    我正在开发一个 Web 应用程序 该应用程序将接收用户的请求 并且必须调用许多外部 API 来编写对该请求的答案 这可以直接从主 Web 线程使用 gevent 之类的东西来扇出请求来完成 或者 我在想 我可以将传入的请求放入队列中 并使用
  • 如何使redis中的“HSET”子键“过期”?

    我需要使 Redis 哈希中所有超过 1 个月的密钥过期 这不可能 https github com antirez redis issues 167 issuecomment 2559040 为了保持 Redis 简单 https git
  • StackExchange.Redis Get 函数抛出 TimeoutException

    我在用着StackExchange Redis与 C 和StackExchangeRedisCacheClient Get函数抛出以下异常 myCacheClient Database StringGet txtKey Text myCac

随机推荐

  • 【C++项目】【报错】[错误] new: No such file or directory, compilation terminated【及解决方法】

    一 问题描述 C源代码文件在编译过程中报错 错误 new No such file or directory compilation terminated 代码如下 include
  • 第8章 多媒体嵌入

    学习目标 了解视频 音频嵌入技术 能够总结HTML5视频 音频嵌入技术的优点 了解常用的视频文件格式和音频文件格式 能够归纳HTML5支持的视频和音频格式 掌握HTML5中视频的嵌入方法 能够在HTML5页面中添加视频文件 掌握HTML5中
  • 服务器的丢包率高怎么办

    网络出现丢包状况了怎么办 具体情况可以从以下几点来判断 1 有可能是线路故障导致的 所以可以用光纤打光仪先判断是否是光纤的问题 2 对于设备方面来说 很多都是网络接口的光纤接触不良等 3 也可能是操作系统的问题 比如网卡问题和网络运营线路问
  • element ui弹窗在别的弹窗下方,优先级不高的问题

    在 弹窗 的标签中加入append to body即可解决该问题
  • Python基础(十六、数据容器汇总)

    文章目录 一 数据容器汇总 二 数据容器通用操作 1 遍历 2 通用统计 len 容器 max 容器 min 容器
  • 解决重定向导致的cookie丢失

    转发前加上 String s response getHeader Set Cookie s HttpOnly Secure SameSite None response setHeader Set Cookie s
  • Java编写CS架构学生管理系统

    一 环境准备 工具 eclipse navicat 环境 jdk8 数据库 mysql5 7 二 正式开始 第一步 分析需求 就是我们需要知道该干什么 登录功能 对学生信息增删改查操作 第二步 创建项目StudentManager 由于我们
  • catkin_make 编译报错 Unable to find either executable ‘empy‘ or Python module ‘em‘...

    文章目录 写在前面 一 问题描述 二 解决方法 参考链接 写在前面 自己的测试环境 Ubuntu20 04 一 问题描述 自己安装完 anaconda 后 再次执行 catkin make 遇到如下问题 CMake Error at opt
  • How to collect data

    How to collect data 爬虫 Java Python 反爬虫 自动化测试工具 Selenium QMetry Automation Studio Te
  • 【ESP32接入国产大模型之文心一言】

    1 怎样接入文心一言 随着人工智能技术的不断发展 自然语言处理领域也得到了广泛的关注和应用 在这个领域中 文心一言作为一款强大的自然语言处理工具 具有许多重要的应用价值 本文将重点介绍如何通过ESP32接入国产大模型之文心一言api 以及其
  • 公司PCB设计需要外包,需要准备哪些资料给PCB设计公司呢?

    现阶段许多公司仍然是让硬件工程师来进行PCB设计和方案开发 除开这些 硬件工程师还要做更多的专业工作 这样势必会使产品上市的时间大大延长 而且现在随着高速数字电子技术的发展 对高速PCB设计的要求也越高 信号完整性仿真分析 nbsp 时序分
  • 14.10-其他阻塞和非阻塞混合使用的原则

    其他阻塞和非阻塞混合使用的原则 1 同时使用阻塞和非阻塞赋值 2 对同一变量既阻塞赋值又非阻塞赋值 综合出错 原则5 不要在同一个always块中同时使用阻塞和非阻塞赋值 1 同时使用阻塞和非阻塞赋值 Verilog语法并没有禁止将阻塞和非
  • DriveMLM

    本人转载于大佬 大型语言模型为智能驾驶开辟了新的格局 赋予了他们类似人类的思维和认知能力 本文深入研究了大型语言模型 LLM 在自动驾驶 AD 中的潜力 进而提出了DriveMLM 这是一种基于LLM的AD框架 可以在仿真环境中实现闭环自动
  • 协议茶馆:TLV 格式及编码

    本篇是多年前的存篇 出处不详 旧酒换新瓶 温故知新 有了新的理解 一 什么是 TLV 格式 几乎所有的通信都有协议 而几乎所有的需要在卡片和终端之间传送的数据 结构 都是 TLV 格式的 TLV 是 tag length 和 value 的
  • Spring框架-入门(IOC,DI)

    文章目录 Spring框架 简介 创建Spring项目 理解IOC和DI IOC控制反转 示例
  • Spring框架-Spring Bean管理

    文章目录 Spring Bean管理 Spring Bean 配置方式 使用XML配置方式 User java
  • 11.使用递归求一个整数的每一位并且求和

    使用递归求一个整数的每一位 public class Main public static void print int n if n lt 10 System out println n 10 return print n 10 Syst
  • 用C语言采集游戏平台数据并做行业分析

    游戏一直深受90 00后的喜爱 有些人因为对游戏的热爱还专门成立了工作室做游戏赚钱 但是游戏行业赚钱走不好就会被割一波韭菜 那么现在什么游戏挣钱 什么游戏好玩认可度高 带着这样的问题我将利用我毕生所学 写了下面一段爬虫程序 这是一个用C 编
  • 夺冠!特等奖!实在Agent智能体闪耀“2023首届全国人工智能应用场景创新挑战赛总决赛”

    为贯彻落实国务院 新一代人工智能发展规划 及科技部 教育部等六部委联合印发的 关于加快场景创新 以人工智能高水平应用促进经济高质量发展的指导意见 中国人工智能学会 科技部新一代人工智能发展研究中心 东莞市人民政府 联合发起主办 2023首届
  • Redis生产环境最佳实践

    欢迎关注公众号 通过文章导读关注 11来了 及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理解 Redis 系列文章结合电商场景讲解 Redis 使用场景 中间件系列笔记 和 编程高频电子书 文章导读地址 点击查看文