Redis之持久化、集群

news2024/12/23 5:58:57

1. Redis持久化

Redis为什么需要持久化?因为Redis的数据我们都知道是存放在内存中的,那么每次关闭或者机器断电,我们的数据旧丢失了。

因此,Redis如果想要被别人使用,这个问题就需要解决,怎么解决呢?就是说我们的数据要同步到磁盘,只有同步到磁盘中了,数据才不会丢失,然后我们启动的时候,内存从磁盘里再加载数据,这样就既能满足基于内存的操作,保证性能,同时也尽可能的防止了数据的丢失。

那么Redis做持久化的方式有哪些呢? RDB和AOF

1.1 RDB

RDB是Redis默认的持久化方案,当满足一定条件的时候,会把当前内存中的数据写入磁盘,生成一个快照文件dump.rdb(默认)

可配置RDB文件的文件名与路径:

# The filename where to dump the DB
dbfilename dump . rdb //dunmp.rdb 文件名
dir . / // 文件路径

那么RDB什么时候会触发呢?

  • 自动触发
    • 配置触发
save 900 1 900 s 检查一次,至少有 1 key 被修改就触发
save 300 10 300 s 检查一次,至少有 10 key 被修改就触发
save 60 10000 60 s 检查一次,至少有 10000 key 被修改
  • shutdown正常关闭;
任何组件,在正常关闭的时候,都会去完成该完成的事情,比如 Mysql中的Redolog 持久化 正常关闭的时候也会去持久化。
  •  flushall指令触发
数据清空指令会触发 RDB 操作,并且是触发一个空的 RDB 文件,所以, 如果在没有开启其他的持久化的时候,flushall 是可以删库跑路的,在 生产环境慎用。
  • 手工触发
    • save 主线程去进行备份,备份期间不会去处理其它的指令,其它指令必须等待
    • bgsave 子线程去进行备份,其它指令正常执行

操作实例演示:

a.我们首先添加一份数据并且备份到RDB

redis > set k1 1
redis > set k2 2
redis > set k3 3

 b.查看数据是否存在

redis > keys *

c.进行shutdown操作触发RDB快照

 redis> shutdown

 d.对现有RDB数据进行备份cp

redis > cp dump . rdb dump . rdb . bak

 e 启动redis

redis > src / redis - server & redis . conf

 发现数据都还在

f. 现在模拟数据丢失

redis > flushall

 g. 停服务器再启动

redis > shutdown
redis > src / redis - server & redis . conf

h. 此时发现数据已经丢失,现在就要从我们备份的数据恢复,先关闭

 redis> shutdown

 i.删除原RDB备份数据

redis > rm dump . rdb

j 将备份数据改名为bump.rdb

 mv dump.rdb.bak dump.rdb

k.  重启服务

src / redis - server & redis . conf

 我们发现数据已经恢复

思考:我们的数据是怎么备份到RDB中的呢?

1. 新起子线程,子线程会将当前 Redis 的数据写入一个临时文件
2. 当临时文件写完成后,会替换旧的 RDB 文件。
Redis 启动的时候,如果只开启了 RDB 持久化,会从 RDB 文件中加载数据。

 RDB的优势:

1. 是个非常紧凑型的文件,非常适合备份与灾难恢复。
2. 最大限度的提升了性能,会 fork 一个子进程,父进程永远不会产于磁盘IO或者类似操作。
3. 更快的重启。

简单总结一句话,RDB恢复与备份都非常的快

RDB的不足

 1.数据安全性不是很高,因为是根据配置的时间来备份,假如每5分钟备份 一次,也会有5分钟数据的丢失

2. 经常 fork 子进程,所以比较耗 CPU ,对 CPU 不是很友好。 

1.2 AOF

由于RDB的数据可靠性非常低,所以Redis又提供了另外一种持久化方案: Append Only File 简称 AOF

AOF默认是关闭的,你可以在配置文件中进行开启 (追加文件,即每次更改的命令都会附加到我的AOF文件中)

appendonly no // 默认关闭,可以进行开启
# The name of the append only file ( default : "appendonly.aof" )
appendfilename "appendonly.aof" //AOF 文件名

 1.2.1同步机制

AOF, 会记录每个写的操作,那么问题来了?我难道每次操作命令又得跟磁盘交互呢?不跟mysql 一样每次需要跟磁盘交互呢?
当然不行,所以, redis 支持几种策略,由你们自己来决定要不要每次都跟磁盘交互
# appendfsync always 表示每次写入都执行 fsync( 刷新 ) 函数 性能会非常非常慢 但是非常安全
appendfsync everysec 每秒执行一次 fsync 函数 可能丢失 1s 的数据
# appendfsync no 由操作系统保证数据同步到磁盘,速度最快 你的数据只需要交给操作系统就行
默认1s一次,最多有1s的数据丢失

1.2.2 重写机制

由于AOF是追加的形式,所以文件会越来越大,越大的话,数据加载越慢。所以我们需要对AOF文件进行重写。

那么什么是重写呢?

比如 我们的 incr 指令,假如我们 incr 100 次,现在数据是 100 ,但是我们的aof 文件中会有 100 incr 指令,但是我们发现这个 100 条指令用处不大,假如我们能把最新的内存里的数据保存下来的话。
所以,重写就是做了这么一件事情,把当前内存的数据重写下来,然后把
之前的追加的文件删除。

重写流程(Redis7之前)

1. Redis fork 一个子进程,在一个临时文件中写入新的 AOF (当前内存的数据生成的新的AOF
2. 那么在写入新的 AOF 的时候,主进程还会有指令进入,那么主进程会在内存缓存区中累计新的指令 (但是同时也会写在旧的AOF 文件中,就算重写失败,也不会导致AOF 损坏或者数据丢失)
3. 如果子进程重写完成,父进程会收到完成信号,并且把内存缓存中的指令追加到新的AOF 文件中
4. 替换旧的 AOF 文件 ,并且将新的指令附加到重写好的 AOF 文件中。

 什么时候进行重写(根据配置)

# 重写触发机制
auto - aof - rewrite - percentage 100
auto - aof - rewrite - min - size 64 mb 就算达到了第一个百分比的大小,也必须大于 64 M

 说明:在aof文件小于64mb的时候不进行重写,当到达64mb的时候,就重写一次。重写后的aof文件可能是40mb.上面配置了auto-aof-rewrite-percentage为100,即aof文件到了80mb的时候进行重写

1.2.3 AOF的优势与不足

优势

1. 安全性高,就算默认的持久化同步机制,也最多只会导致 1s 丢失。
2.AOF 由于某些原因,比如磁盘满了等导致追加失败,也能通过 redis
check-aof 工具来修复   ./redis-check-aof --fix append
3. 格式都是追加的日志,所以可读性更高

不足

1. 数据集一般比 RDB
2. 持久化跟数据加载比 RDB 更慢
3. 7.0 之前,重写的时候,因为重写的时候,新的指令会缓存在内存区,所以会导致大量的内存使用
4. 并且重写期间,会跟磁盘进行 2 IO ,一个是写入老的 AOF 文件,一个 是写入新的AOF 文件

2.Redis集群

2.1 Redis主从

为什么要有主从?

1. 故障恢复 主挂了或者数据丢失了,我从还会有数据冗余
2. 负载均衡,流量分发 我们可以主写,从库读,减少单实例的读写压力
3. 高可用 我们等下讲的集群 等等,都是基于主从去实现的

 安装教程后续会单独出文章

我们现在已经安装了一个主从,先看下基本信息

主:

127.0 . 0.1 : 6379 > info replication
# Replication
role : master // 角色
connected_slaves : 1 // 从节点数量
slave0 : ip = 192.168 . 8.127 , port = 6379 , state = online , offset = 7889
9 , lag = 1 // 从节点的信息 状态 偏移量
master_replid : 04f4969 ab63ce124e870fa1e4920942a5b3448e7
//# master 启动时生成的 40 16 进制的随机字符串,用来标识 master 节点
master_replid2 : 0000000000000000000000000000000000000000
master_repl_offset : 78899 //mater 已写入的偏移量
second_repl_offset : - 1
repl_backlog_active : 1
repl_backlog_size : 1048576 // 缓冲区大小
repl_backlog_first_byte_offset : 1
repl_backlog_histlen : 78899 // 缓冲区的数据已有大小(是个环形,跟RedoLog一样会覆盖)

从:

 127.0.0.1:6379> info replication

# Replication
role : slave // 角色
master_host : 192.168 . 8.129 // 主节点 IP
master_port : 6379 // 主节点端口
master_link_status : up // 连接状态 up 是正常同步连接状态 down
示复制端口
master_last_io_seconds_ago : 1 // 主库多少秒没有发送数据到从库 0-
10
master_sync_in_progress : 0 // 是否正在跟主服务同步
slave_repl_offset : 163 // 从节点偏移量
slave_priority : 100 // 选举时成为主节点的优先级 越大优先级越高 0不会成为主节点
slave_read_only : 1 // 是否为只读从库 如果不是只读,则能自己进行数据写入,默认是只读
connected_slaves : 0 // 连接的从库实例
master_replid : 04f4969 ab63ce124e870fa1e4920942a5b3448e7
//master 启动时生成的 40 16 进制的随机字符串,用来标识 master 节点
master_replid2 : 0000000000000000000000000000000000000000
//slave 切换 master 之后,会生成了自己的 master 标识,之前的 master 节点的标识存到了master_replid2 的位置
master_repl_offset : 163 // 已写入偏移量
second_repl_offset : - 1
repl_backlog_active : 1
repl_backlog_size : 1048576 // 复制积压的缓存区大小
repl_backlog_first_byte_offset : 1
repl_backlog_histlen : 163

 2.1.1 主从数据同步

我们发现,我们的信息中,有个slave_read_only,如果是1代表只读。也就是默认,当然也可以配置成写,但是写的数据不会同步到主库,需要自己去保证数据的一致性,可能从库写的数据会被主库的数据操作覆盖。出现从库set一个值后,获取到的是主库覆盖的数据。

举例:

127.0 . 0.1 : 6379 > set k1 2 // 从库设置 k1 2

 127.0.0.1:6379> set k1 3 //主库设置k13 并且会同步到从库

 127.0.0.1:6379> get k1

"3"     // 从库得到的是主库设置的值

 思考:  我们主库的数据是怎么同步到从库的呢?同步过程是怎么样的?或者主从数据是怎么保证一致性的。

a.建立连接

当首次成为主节点的从节点时,执行 replicaof ip port 命令的时候就会保存主服务器的IP 与端口
并且与主服务器建立连接,接收主节点返回的命令
判断主节点是否有密码 如果有 进行权限校验
保证主从之前保存了各自的信息,并正常连接。

b.slave发起同步master数据指令

在slave的serverCron方法调用replicationCron方法,里面会发起跟master的数据同步

run_with_period ( 1000 ) replicationCron ();

 b.1 全量同步

1. master 服务器收到 slave 的命令后( psync ),判断 slave 传给我的master_replid 是否跟我的 replid 一致,如果不一致或者传的是个空的,那么就需要全量同步。
2. slave 首次关联 master ,从主同步数据, slave 肯定是没有主的 replid, 所以需要进行全量同步。
3. 进行全量同步
        3.1. master开始执行 bgsave ,生成一个 RDB 文件,并且把 RDB 文件传输给我们的slave ,同时把 master replid 以及 offerset master 的数据进度,处理完命令后,都会写入自身的offerset
        3.2. slave接收到 rdb 文件后,清空 slave 自己内存中的数据,然后用 rdb来加载数据,这样保证了slave 拿到的数据是 master 生成 rdb 时候的最新数据。
        3.3. 由于 master 生成 RDB 文件是用的 bgsave 生成,所以,在生成文件的时候,是可以接收新的指令的。那么这些指令,我们需要找一个地方保存,等到slave 加载完 RDB 文件以后要同步给 slave
                3.2.1. 在master 生成 rdb 文件期间,会接收新的指令,这些新的指令会保存在一个内存区间,这个内存区间就是replication_buffer
                3.2.2. 这个空间不能太小,如果太小,为了数据安全,会关闭跟从库的网络连接。再次连接得重新全量同步,但是问题还在,会导致无限的在同步

 replication_buffer大小的设置

client - output - buffer - limit replica 256 mb 64 mb 60  256 mb 硬性限制,大于 256M 断开连接
64 mb 60 软限制 超过 64M 并且超过了 60s 还没进行同步 内存数据就会断开连接

 b.2 增量同步

为什么需要增量同步?

这是因为每个节点都会保存数据的偏移量,那么就有可能出现slave跟master网络断开一小会,然后发起数据同步的场景,如图所示:

 slave1由于网络断开了,偏移量跟master相差了3.

那么当slave1重新跟master连接后,同样的会去跟master连接触发数据同步。但是这个时候还需不需要全量同步了?我们肯定是尽可能的减少全量同步。

所以,当master收到slave的指令时:

1. 判断 slave1 传给我的 master_replid 是否跟 master replid 一致,由于之前已经连接过保过了master replid ,满足条件。
2. 所以我希望只同步断开连接后没有同步到的数据,必须,我 slave1 只差 了3 的数据。那么我需要找到这个 3 的数据。所以 master 中有个另外的积压缓(replication_backlog_buffer )。
我们也不可能无限制的往里面写数据, replication_backlog_buffer 的数据是会覆盖的。
3. 所以,我们 slave1 master 相差的 3 条数据可能会被覆盖,如果覆盖了,触发全量,如果没有覆盖,即能找到相差的3 条数据。增量即可。

 replication_backlog_buffer的配置

# The bigger the replication backlog , the longer the
time the replica can be 复制积压越大,复制副本的时间越长
# disconnected and later be able to perform a partial
resynchronization . 已断开连接,稍后可以执行部分重新同步。
#
# The backlog is only allocated once there is at least
a replica connected . 只有在至少连接了一个副本后,才会分配积压工 作。
#
# repl - backlog - size 1 mb

 b.3 指令同步

master写入的指令,异步同步给slave,如果有slave,写入replication_backlog

_buffer

整体主从数据同步流程图: Redis主从同步策略| ProcessOn免费在线作图,在线流程图,在线思维导图

2.2 Sentinel哨兵

主从,虽然解决了比如负载、数据备份等问题。但是我们发现如果master挂了,slave不会直接升级为主,必须手动把slave升级为主。这样肯定人为维护的成本比较高。所以我们希望能有一个技术帮我们实现这样的需求,于是就有了哨兵集群。

什么是哨兵集群?

Redis sentinel 在不适用 Cluster 集群的时候,为 Redis 提供了高可用性。
并且提供了监测、通知、自动故障转移、配置提供等功能。
监控 :能够监控我的 Redis 各实例是否正常工作
通知 :如果 Redis 的实例出现问题,能够通知给其他实例以及 sentinel
自动故障转移 :当我的 master 宕机, slave 可以自动升级为 master
配置提供 sentinel 可以提供 Redis master 实例地址,那么客户端只需要跟sentinel 进行连接, master 挂了后会提供新的 master

其实sentinel是独立于Redis服务的单独的服务,并且它们之间是相互通信的。

2.2.1 哨兵故障转移流程

我们的哨兵到底是怎么去发现我们的master挂了的呢?挂了后让slave变成Master的整个流程是咋样的呢?

a。发现master故障

1. 当我们某个 sentinel master 通信时(默认 1s 发送 ping ),发现我在 一定时间内(down-after-milliseconds ) 没有收到 master 的有效的回复。这个时候这个sentinel 就会人为 master 是不可用,但是有多个sentinel,它现在只有 1个人觉得宕机了,这个时候不会触发故障转移,
只会标记一个状态,这个状态就是 SDOWN Subjectively Down condition ),也就是我们讲的主观下线
2. SDOWN 时,不会触发故障转移,会去询问其他的 sentinel ,其他的sentinel是否能连上 master ,如果超过 Quorum( 法定人数 ) sentinel 都认为master 不可用,都标记 SDOWN 状态,这个时候, master 可能就真的是down 了。那么就会将 master 标为 ODOWN Objectively Down condition 客观下线)

b. 进行故障转移

1. 当状态为 ODWON 的时候,我们就需要去触发故障转移,但是有这么多 的sentinel ,我们需要选一个 sentinel 去做故障转移这件事情,并且这 个sentinel 在做故障转移的时候,其他 sentinel 不能进行故障转移
2. 所以,我们需要选举一个 sentinel 来做这件事情 : 其中这个选举过程有 2个因素。
        2.1  Quorum 如果小于等于一半,那么必须超过半数的 sentinel 授权,你才能去做故障迁移,比如5 sentinel ,你配置的 Quorum=2 ,那么选举的时候必须有3 5 台的一半以上)人同意
        2.2. Quorum如果大于一半,那么必须 Quorum sentinel 授权,故障迁移才能启动。

 c.选哪个slave来变成master

1. master 的断开连接时间
如果 slave 与主服务器断开的连接时间超过主服务器配置的超时时间 (down-after-milliseconds )的十倍,被认为不适合成为 master 。直接去除资格
2. 优先级
配置 replica-priority replica-priority 越小,优先级越高,但是配置为0的时候,永远没有资格升为 master
3. 已复制的偏移量
比较 slave 的赋值的数据偏移量,数据最新的优先升级为 master
4. Run ID (每个实例启动都会有个 Run ID
通过 info server 可以查看。

2.2.2 Sentinel导致的数据一致性问题

官方建议配置至少3个sentinel

原因如下:

1. 如果只有 1 sentinel 实例,则这个实例挂了就不能保证 sentinel 的高可用性。
2. 如果,我配置了 2 sentinel ,分别在 127 跟128.n并且我配置的quorum=1 ;就可能发生
        2.1.sentinel2检测到 master 不可用,因为 127 128 网络断开,这个时候会触发主观下线,同时,sentinel2 只能连接到 1 sentinel ,也满足半数以上原则(只有1 sentinel2
        2.2.sentinel2开启故障转移,将 128 slave 升级为 master, 就出现了 2 个master,这个情况也叫作脑裂。并且客户端会连接到 2 master 。 (客户端连的是sentinel 集群,所以 sentinel1 连到 127.sentinel2 连到 128
        2.3  2 master 都会写入数据,当网络恢复后, 127 会变成从, 127 的数据会
128 去拿取,这个时候 127 的数据就会丢失

2.2.3 脑裂问题

脑裂问题其实就是我会有2个master,client会从不同的master写数据,从而在master恢复的时候会导致数据丢失。

所以只要发生分区容错性,不管多少节点都会出现,比如3个节点。

初始 129 master, 假如 129 网络断开,跟 127.128 连接断开后, 128sentinel发起故障转移。发现 sentinel 的个数超过一半,能够发起故障 转移。将128 升级为 master ,导致 128.129 同时 2 master 并可用

解决方案:

在Redis.cfgt文件中有2个配置:

min - replicas - to - write 1 至少有 1 个从节点同步到我主节点的数据,但是由于是异步同步,所以是最终一致性 不会确保有数据写入
min - replicas - max - lag 10 判断上面 1 个的延迟时间必须小于等于 10s

 按上述场景

129由于没有slave同步,不满足我配置的要求,不能进行数据写入。尽量减少数据一致性问题。

思考,为什么部署奇数台?一因为4跟3 能容许挂掉的机器数量是一样的,都是1台

2.3 Redis Cluster

我们发现sentinel提供了比如监控、自动故障转移、客户端配置等高可用的方案,但是没有分片功能。

何为分片:就是我希望把数据分别到不同的节点。这样如果某些节点异常,其它数据能正常提供服务,跟我们微服务的思想很相似。

所以我们cluster就提供了这样的解决方案

1. 多个节点之间的数据拆分,也就是我们的数据分片
2. 当某些节点遇到故障的时候,其他的节点还能继续服务。

 2.3.1 hash slot(虚拟槽)

那么如何进行分片?分片要做的事情就是把不同的数据放到不同的实例里面去。就相当于我们分表,不同的数据放到不同的表里。

普通取模问题

取模 直接取模实例数,得到 key hash 值,取模实例数,假如实例是 3 ,那么取模后得到0-2 的值,每个值代表一个实例。
但是这种取模有一个问题,假如我做了实例的扩容与缩容,那么全部数据要进行迁移。
假如我之前是 3 台,扩容到 4 台,那么所有的数据都必须重新 rehash
所以, Redis 里面提出了一个 Hash 槽,也叫作虚拟槽的概念。什么是虚拟槽,其实就是虚拟节点。
Redis cluster 中有 16384 个虚拟槽

我们的key会跟槽对应,怎么对应?

根据key通过CRC16取模16383得到一个0到16383的值,计算公式:slot=CRC16(key)&16383,得到的值,就代表这个key在哪个虚拟槽。

举例:

假如
set k1 1 :
CRC16 ( k1 ) & 16383 = 11901
set k2 1 :
CRC16 ( k2 ) & 16383 = 10
set k3 1 :
CRC16 ( k3 ) & 16383 = 6666
那么我们 k1 对应的槽是 11901 k2 对应的槽是 10 k3 对应的槽是 6666

key跟槽的关系是根据key算出来的,后续不能变动。

如果想把相关keu放入一个虚拟槽,也就是一个实例节点,我们可以采用{},那么就只会根据{}里面的内容计算hash槽!

比如: zsc{18}跟james{18}就会在一个虚拟槽

那么key怎么去放到我们的真实节点?

假设我们现在有6台实例,三主三从。主跟槽的对应关系如下:
master1 0-5460 虚拟槽
master2 5461-10922 虚拟槽
master3 10923-16383 虚拟槽

 我们知道,k1的虚拟槽是10001,所以放到master3,依次类推,k2放到master1,k3放到mster2

从节点的数据全部来源于主,所以k1放入master3的从,以此对应。

127.0.0.1:6380> cluster nodes 查看当前节点的虚拟槽信息

这样,每次节点的扩容与缩容,只需要改变节点跟虚拟槽的关系即可,不需要全部变动。

3. 总结

        redis是内存型数据库,因此每次机器关机都会清理内存,因此,要想保证redis的可用性,就需要持久化技术,redis持久化分为RDB快照和AOF追加两种形式; 但是为了高可用,流量的分发以及为了应对redis挂了之后的可用性,引入了主从,主从之间就又设计到了数据的全量同步和增量同步;随后,为了更进一步的将主从切换智能化,提出了sentinel哨兵模式,可用监控主的状态,采用一定的策略,保证主挂了以后从可以升级为主;最后是为了更进一步提升redis的高可用,采用集群的方案,将redis数据分布到不同的节点进行管理。

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

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

相关文章

关于OpenFlow协议的运行机制和实践分析(SDN)

目录 OpenFlow运行机制 1 OpenFlow信道建立 1.1 OpenFlow消息类型 1.2 信道建立过程解析 2 OpenFlow消息处理 2.1 OpenFlow流表下发与初始流表 2.2 OpenFlow报文上送控制器 2.3 控制器回应OpenFlow报文 3 OpenFlow交换机转发 3.1 单播报文转发流程 OpenFlow的实践分析…

C++的第一道门坎:类与对象(三)

目录 一.再谈构造函数 1.1构造函数体赋值 1.2初始化列表 1.3explicit关键字 二.static成员 2.1概念 ​编辑 2.2特性 三.友元 3.1友元函数 3.2友元类 4.内部类 一.再谈构造函数 1.1构造函数体赋值 class Date { public:Date(int year,int month,int day){_year ye…

使用KEPServer连接欧姆龙PLC获取对应标签数据(标签值类型改为字符串型)

1.创建通道(通道),(选择对应的驱动,跟当前型号PLC型号对应)。 2.创建设备,(填入IP地址以及欧姆龙的默认端口号:44818) 3.创建对应的标签。这里关键讲诉下字…

【VSCode实战】转换大小写快捷键

今天在VSCode Insiders上编码,突然想将某常量转换为大写。按照virtual studio的习惯,我Ctrl Shift U没有效果,Ctrl U也没效果。网上搜了搜,原来VSCode Insiders没有这个默认功能。 而VSCode Insiders这么强大怎么可能没有大小…

Keras深度学习框架实战(1):图像分类识别

1、绪论 1.1 图像分类的定义 图像分类是计算机视觉领域中的一项基本任务,其定义是将输入图像分配给预定义类别中的一个或多个。具体来说,图像分类系统接受一个图像作为输入,并输出一个或多个类别标签,这些标签描述了图像中的内容…

pytorch 指定GPU的几种方法

在使用PyTorch时,你可以通过多种方式指定和使用GPU。以下是一些常见的方法: 1. 使用torch.device torch.device是PyTorch中用于指定设备(CPU或GPU)的对象。你可以通过将张量移动到指定设备来使用GPU。 import torch# 检查是否有可用的GPU device = torch.device("…

光子芯片:突破算力瓶颈的新希望

引言 在现代计算机科学中,计算能力的提升是推动技术进步的核心动力。然而,随着摩尔定律的逐渐失效,传统电子芯片的算力提升面临瓶颈。光子芯片作为一种新兴技术,因其高频率、低损耗和高信噪比的优点,正成为突破算力瓶…

抖音太可怕了,我卸载了

这两天刷短视频,上瘾了,太可怕了。 自己最近一直在研究短视频制作,所以下载了抖音,说实话,我之前手机上并没有抖音,一直在用B站。 用了两天抖音,我发现,这玩意比刷B站还容易上瘾啊…

打工人福音⚡:公牛充电交互协议,建议收藏!

分享《一套免费开源充电桩物联网系统,是可以立马拿去商用的!》 协议原文件下载地址: 链接: https://pan.baidu.com/s/1kW15Nfe9cjPDFLGPYJ-zUg?pwdagq2 提取码: agq2 1 总则 1.1 协议概述 本协议适用于公司所有充电产品包括交直流充电桩、…

SDK开发

为什么需要Starter? 理想情况:开发者只需关心调用哪些接口,传递哪些参数就跟调用自己写的代码一样简单。 开发starter的好处:开发者引入之后,可以直接在application.yml中写配置,自动创建客户端。 starter开发流程 …

bhyve:FreeBSD下的原生虚拟机管理器

hbyve简介 自 FreeBSD 10.0-RELEASE 起,BSD 许可的 bhyve 虚拟机管理器已成为底层系统不可或缺的一部分。bhyve 强大而灵活,支持多种客户机操作系统,涵盖 FreeBSD、OpenBSD 以及多个 Linux 发行版。在默认配置下,bhyve 提供对串行…

中建环能 | “农村生活污水治理稳质增效与智能运维技术研究及成套装备应用” 科技成果评价

中华环保联合会组织召开了中建环能科技股份有限公司申请的“农村生活污水治理稳质增效与智能运维技术研究及成套装备应用”技术成果评价会。会议由中华环保联合会水环境治理专业委员会秘书长刘愿军主持。 评审会委员 本次评价会邀请了7位相关专业领域的专家组成专家评价委员会。…

Meterpreter工具使用

Meterpreter属于stage payload,在Metasploit Framework中,Meterpreter是一种后渗透工具,它 属于一种在运行过程中可通过网络进行功能扩展的动态可扩展型Payload。这种工具是基于“内存DLL注 入”理念实现的,它能够通过创建一个新进…

RocketMq broker源码解析

broker 集群工作流程 NameSrv启动成功后,等待broker、Consumer和producer启动后也与NameSrv保持长连接, NameSrv相当于是路由控制中心。启动broker, broker与所有的NameSrv建立长连接, broker,通过定时线程定时向NameSrv发送心跳,broker信息…

mysql中子查询的语法和执行过程

大家好。我们在日常开发过程中,肯定都经常用到了子查询。今天我们就来聊一下mysql中子查询的一些语法以及子查询的执行过程。 一、子查询的语法 首先在开讲之前,我们先创建t1、t2两张表,并分别在表中插入三条数据,方便我们下面内…

JDK环境配置、安装

DK环境配置(备注:分32位与64位JDK,32位电脑只能按照32位JDK,64位电脑兼容32、64位JDK) 一、检查自己电脑是否安装过JDK 1.在电脑屏幕左下角,输入命令提示符CMD,打开命令提示符应用 2.在打开界…

AI视频下载:ChatGPT数据科学与机器学习课程

ChatGPT是一个基于OpenAI开发的GPT-3.5架构的AI对话代理。作为一种语言模型,ChatGPT能够理解并对各种主题生成类似人类的响应,使其成为聊天机器人开发、客户服务和内容创作的多用途工具。 此外,ChatGPT被设计为高度可扩展和可定制的,允许开发人员对其响应进行微调并将其集成到…

[stm32]——定时器与PWM的LED控制

目录 一、stm32定时器 1、定时器简介 2、定时器分类 3、通用定时器介绍 二、PWM相关介绍 1、工作原理 2、PWM的一般步骤 三、定时器控制LED亮灭 1、工程创建 2、代码编写 3、实现效果 四、采用PWM模式,实现呼吸灯效果 1、工程创建 2、代码编写 3、实现效果 一、stm3…

跨境电商多店铺:怎么管理?风险如何规避?

跨境电商的市场辽阔,有非常多的商业机会。你可能已经在Amazon、eBay、Etsy等在线平台向潜在客户销售产品了。为了赚更多的钱,你可能还在经营多个店铺和品牌。 但是,像Amazon、eBay、Etsy等知名平台会有自己的规则,他们开发了很多…

风电功率预测 | 基于TCN-GRU时间卷积门控循环单元的风电功率预测(附matlab完整源码)

完整代码 clc; clear close allX = xlsread(风电场预测.xlsx); X = X(5665:8640,:); %选取3月份数据 num_samples =