Redis部署-集群

目录

集群

数据分片算法

哈希求余

一致性哈希算法

哈希槽分区算法

redis集群搭建

1.创建目录和配置.

2.将上述redis节点.构建成集群

3.使用客户端连接集群

集群模式下的故障转移流程

1.故障判定

2.故障迁移

集群扩容


集群

广义上的集群,只要是多个机器,构成了分布式系统,都可以称为是一个"集群".前面的主从模式和哨兵模式也可以称为是广义的集群.

狭义的集群,redis提供的集群模式,在这个集群模式之下,主要是姐姐,存储空间不足的问题.

redis集群基本概念

上述的哨兵模式,虽然提高了系统的可用性,但是真正用来存储数据的还是master和slave节点,所有的数据都需要存储在单个的master和slave节点中.

如果数据量很大,超出了master/slave所在机器的物理内存,就可能出现严重问题了.

那么如何获得更大的空间,加机器即可!!!

redis集群就是在上述思路下,引入多组master/slave存储数据全集的一部分,从而构成一个更大的整体,称为是redis集群.

假定整个数据全集是1TB,此时就可以引入三组master/slave,每一组master/slave只需要存储整个数据全集的三分之一即可.

其中每一组主从节点保存的是同样的数据,占数据全集的三分之一.

每个从节点都是对应主节点的备份,当主节点挂了,对应的slave会补位成主节点.

每组主从节点都可以称为是一个分片(sharding).

如果全量数据进一步增加,只要在增加更多的分片即可.


数据分片算法

Redis cluster的核⼼思路是⽤多组机器来存数据的每个部分.那么接下来的核⼼问题就是,给定⼀个数据(⼀个具体的key),那么这个数据应该存储在哪个分⽚上?读取的时候⼜应该去哪个分⽚读取?
围绕这个问题,业界有三种⽐较主流的实现⽅式.

哈希求余

借助了哈希表的基本思想,借助hash函数,把一个key映射到整数,在针对数组的长度,求余,就可以得到一个数组的下标.

比如有三个分片,编号为0,1,2.

此时就可以针对要插入的数据key计算hash值(比如使用MD5计算hash值),在把这个hash值余上分片的个数,就得到了一个编号,此时就可以把这个数据放到对应的下标对应分片中了.

md5是一个计算hash值的算法.它能够针对一个字符串里面的内容进行一系列的数学演算,最终得到一个整数.

它是一个非常广泛使用的hash算法.特点:

  • 1.md5计算结果是定长的,无论输入的原字符串有多长,最终算出的结果就是固定长度.
  • 2.md5计算结果是分散的,两个源字符串,哪怕只有一个地方不同,算出来的md5值也会差别很大.
  • 3.md5计算结果是不可逆的.字符串->md5值是很容易得到,而根据md5值还原出原始字符串是很困难的,理论上是不可行的.

如果计算出hash(key)%3==0,此时这个key就要存储在0号分片中,后续查询key的时候,也是同样的算法.

数据搬运

一旦服务器集群需要扩容,就需要更高的成本了.分片的主要目的是为了提高存储能力,分片越多,能存的数据也就越多,但是成本也就更高.

如果随着业务的增长,原先的三个分片已经不够用了,那么此时就要"扩容",引入更多的分片.

引入新的分片的后,hash(key)%N中的N就变了,加入这里新引入一个分片,N就从3变为了4.

当hash函数和key都不变的情况下,如果N变了,整体的分片结果仍然会改变.

如果发现某个数据,在扩容之后,不应该存储在当前的分片中了,就需要重新进行分配这个数据,这个过程就叫做数据搬运.

从上图可以看出,一共20个数据,经过扩容之后,只有3个数据不需要搬运,17个数据需要搬运!!!

由此我们知道采用哈希求余算法需要搬运的数据的比例是很高的.如果在生产环境上扩容,开销是极大的.所以我们往往不能直接在生产环境上操作上述过程,只能通过替换的方式来实现扩容.但是替换也就意味着依赖的机器更多了,成本更高,操作步骤也非常复杂!!!


一致性哈希算法

在hash求余这种操作下,当前的key属于哪个分片,是交替的.

102->0,103->1,104->2,105->0......,交替出现,就导致数据搬运的成本很大.

在一致性hash算法中,把交替出现,改进成了连续出现.降低了数据搬运的开销,能够高效扩容.

一致性hash算法过程

1.把0->2^31-1这个数据空间,映射到一个圆环上,数据按照顺时针方向增长.

2.假设当前存在三个分片,就把分片放到圆环的某个位置上.

3.假定有一个key,计算得到hash值H,就从H所在位置,顺时针往下找,找到的第一个分片,即为该key所从属的分片.

这就相当于,N个分片的位置,把整个圆环分成了N个管辖空间,key的hash值落在某个区间内,就归对应的区间管理.


在这种情况下,如果扩容一个分片,原有分片在环上的位置不动,只要在环上新安排一个分片位置即可.

此时,只要把0号分片上的部分数据,搬运到3号分片上即可,1号分片和2号分片管理的区间上的数据都是不变的.

虽然搬运的成本低了,但是这几个分片上的数据量,就可能步均匀了,就造成了数据倾斜的问题!!!


哈希槽分区算法

此种算法是redis真正采用的分片算法.

为了解决搬运成本高和数据分配不均匀的问题,reids cluster引入了哈希槽算法.

hash_slot = crc16(key) % 16384

其中crc也是一种hash算法.

相当于把整个哈希值,映射到16384个槽位上,也就是[0,16384].

然后把这些槽位均匀的分配给每个分片,每个分片的节点都需要记录自己持有哪些分片.

这种算法,本质就是把一致性hash和哈希求余两种方式结合一下.

假设现在有三个分片,一种可能的分配方式:

0号分片:[0,5461],共5462个槽位;

1号分片:[5462,10923],共5462个槽位.

2号分片:[10924,16383],共5460个槽位.

虽然不是严格意义的均匀,但是差异非常小,此时这三个分片上的数据就是比较均匀的了.

上述只是一种可能的分片方式,实际上分片是非常灵活的,每个分片持有的槽位号,可以是连续的,也可以是不连续的.

此处,每个分片都会使用位图这样的数据结构,来表示出当前持有的槽位.16384个bit位(2KB),用每一位的0或者1来区分这个分片是否持有这个槽位.

如果需要扩容,比如新增一个3号分片,就可以针对原有的槽位进行重新分配.

比如可以把之前每个分片持有的槽位,各拿出一点,分给新的分片.

• 0号分⽚:[0,4095],共4096个槽位
• 1号分⽚:[5462,9557],共4096个槽位
• 2号分⽚:[10924,15019],共4096个槽位
• 3号分⽚:[4096,5461]+[9558,10923]+[15019,16383],共4096个槽位.

注意,我们在使用redis集群分片的时候,不需要手动指定哪些槽位分配给某个分片,只需要告诉redis某个分片应该持有多少个槽位即可,redis会自动完成后续的槽位分配,以及key对应的搬运工作.

关于哈希槽分区算法的两个问题

redis集群是最多有16384个分片吗???

其实不然,如果一个分片上只有一个槽位,这对于集群的数据均匀是难以保证的.而且16384个分片这么大规模的集群,本身的可用性是一个大问题.

实际上redis的作者建议分片的数目不应该超过1000.

为什么是16384个槽位???

节点之间通过⼼跳包通信.⼼跳包中包含了该节点持有哪些slots.这个是使⽤位图这样的数据结构
表⽰的.表⽰16384(16k)个slots,需要的位图⼤⼩是2KB.如果给定的slots数更多了,⽐如65536个了,此时就需要消耗更多的空间,8KB位图表⽰了.8KB,对于内存来说不算什么,但是在频繁的⽹络⼼跳包中,还是⼀个不⼩的开销的.

另⼀⽅⾯,Redis集群⼀般不建议超过1000个分⽚.所以16k对于最⼤1000个分⽚来说是⾜够⽤
的,同时也会使对应的槽位配置位图体积不⾄于很⼤.

总结来说,就是这些个槽位基本上是够用的,同时占用的网络带宽也不是很大.


redis集群搭建

在这里由于只有一台云服务器,所以也是基于docker搭建.

实际工作中,一般是通过主机的方式,来搭建集群.

在搭建之前,一定要把之前启动的redis容器,给停止掉!!!在redis-data目录和redis-sentinel目录下分别执行docker-compose down命令.

在这里我们创建出11个redis节点,其中9个用于集群的搭建,2个用于集群的扩容.


1.创建目录和配置.

创建redis-cluster目录,内部创建两个文件.

在linux上以.sh为后缀结尾的文件,称为是shell脚本.shell脚本里可以批量化执行命令,并且还能加入条件,循环,函数等机制,来完成更加复杂的工作.

generate.sh内容

for port in $(seq 1 9); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.10${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
# 注意 cluster-announce-ip 的值有变化.
for port in $(seq 10 11); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done

for port in $(seq 1 9);表明这是一个基于范围的循环.类似于java的for each.

seq也是一个命令,seq 1 9表示生成1-9闭区间内的数据.

\是续行符,把下一行的内容和当前行,合并成一行.shell默认情况下,要求把所有的代码都写到一行里,使用续行符来换行.

对于for来说,用do和done表示代码块的开始和结束,shell中{}用来表示变量了,不表示代码块.

shell中拼接字符是直接写到一起,而不需要使用+.

因此上述第一个循环就表示,创建9个目录,在这些目录下创建一个文件,将内容写到文件中去.

这些内容只有在配置集群的ip的时候是不一致的,

cluster-announce-ip 172.30.0.10${port},会生成101-109的ip.

经过上述两个循环,就会得到11个目录,每个目录里都有一个配置文件,配置文件中ip地址各不相同.

cluster-enabled yes表示开启集群
cluster-config-file nodes.conf//不需要手动写,redis自动生成,后续启动节点之后,会配置一些redis集群信息,写入到此文件中.
cluster-node-timeout 5000//多个节点保持联络的心跳包的超时时间
cluster-announce-ip 172.30.0.10${port}//该redis节点所在主机的ip,当前是使用docker容器模拟的主机,此处写的应该是docker容器的ip.
cluster-announce-port 6379//redis节点自身绑定的端口(容器内的端口),属于是业务端口.
cluster-announce-bus-port 16379//该redis节点的管理端口.

一个服务器,可以绑定多个端口号.

业务端口是用来完成业务数据通信的,响应redis客户端的请求.

管理端口:为了完成一些管理上的任务来进行通信的端口,如果某个分片的redis主节点挂了,就需要从节点成为主节点,此过程就需要管理端口来完成对应的操作.

完成上述操作之后,使用bash命令执行shell脚本.


docker-compose.yml的编写

version: '3.7'
networks:
  mynet:
    ipam:
      config:
        - subnet: 172.30.0.0/24
services:
  redis1:
    image: 'redis:5.0.9'
    container_name: redis1
    restart: always
    volumes:
      - ./redis1/:/etc/redis/
    ports:
      - 6371:6379
      - 16371:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.101
  redis2:
    image: 'redis:5.0.9'
    container_name: redis2
    restart: always
    volumes:
      - ./redis2/:/etc/redis/
    ports:
      - 6372:6379
      - 16372:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.102
  redis3:
    image: 'redis:5.0.9'
    container_name: redis3
    restart: always
    volumes:
      - ./redis3/:/etc/redis/
    ports:
      - 6373:6379
      - 16373:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.103
  redis4:
    image: 'redis:5.0.9'
    container_name: redis4
    restart: always
    volumes:
      - ./redis4/:/etc/redis/
    ports:
      - 6374:6379
      - 16374:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.104
  redis5:
    image: 'redis:5.0.9'
    container_name: redis5
    restart: always
    volumes:
      - ./redis5/:/etc/redis/
    ports:
      - 6375:6379
      - 16375:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.105
  redis6:
    image: 'redis:5.0.9'
    container_name: redis6
    restart: always
    volumes:
      - ./redis6/:/etc/redis/
    ports:
      - 6376:6379
      - 16376:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.106
  redis7:
    image: 'redis:5.0.9'
    container_name: redis7
    restart: always
    volumes:
      - ./redis7/:/etc/redis/
    ports:
      - 6377:6379
      - 16377:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.107
  redis8:
    image: 'redis:5.0.9'
    container_name: redis8
    restart: always
    volumes:
      - ./redis8/:/etc/redis/
    ports:
      - 6378:6379
      - 16378:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.108
  redis9:
    image: 'redis:5.0.9'
    container_name: redis9
    restart: always
    volumes:
      - ./redis9/:/etc/redis/
    ports:
      - 6379:6379
      - 16379:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.109
  redis10:
    image: 'redis:5.0.9'
    container_name: redis10
    restart: always
    volumes:
      - ./redis10/:/etc/redis/
    ports:
      - 6380:6379
      - 16380:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.110
  redis11
    image: 'redis:5.0.9'
    container_name: redis11
    restart: always
    volumes:
      - ./redis11:/etc/redis/
    ports:
      - 6381:6379
      - 16381:16379
    command:
      redis-server /etc/redis/redis.conf
    networks:
      mynet:
        ipv4_address: 172.30.0.111

此处为了后续创建静态ip,要先手动创建出网络,同时给这个网络也分配ip.

创建完配置文件之后,启动容器.


2.将上述redis节点.构建成集群

redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379 172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379 172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2

--cluster create表示建立集群,后面填写每个节点的ip和端口.

--cluster-replicas 2表示每个主节点需要2个从节点备份.

redis在构建集群的时候,谁是主节点谁是从节点,哪些节点是一个分片不是固定的.

执行命令.

输入yes.

集群构造完毕.


3.使用客户端连接集群

从101-109九个节点,现在是一个整体,使用客户都安连上任意一个节点,都是在操作整个集群,本质上都是等价的.

使用cluster nodes命令查看当前集群的信息.

使用集群来存储数据.

设置成集群模式之后,当前数据就要分片存储了,k1这个key通过hash计算之后,得到slot为12706,属于103这个分片,所以就报错了.

我们可以在启动redis客户端的时候,加上-c选项,此时客户端如果发现当前的key的操作不在当前分片上,就能够自动的重定向到对应的分片主机.

请求转发给了103这个节点,进一步完成了数据存储的操作.

使用集群之后,之前学过的操作多个key的命令有时候就不能正常使用了,此时如果key分布在多个分片上,就有可能出现问题.


如果集群中,有节点挂了怎么办?

如果挂了的是从节点,没有多大影响.

如果挂了的是主节点,因为只有主节点才能处理写操作(如果在从节点上尝试写操作,此时就会自动的被重定向到指定的主节点上),此时集群做的工作就和哨兵做的类似了,集群会自动的把该主节点旗下的从节点,选拔一个出来,晋升为主节点.

我们先使用docker stop redis1命令停掉redis1.

在连上一个客户端查看集群信息.

可以看出,106成了新的主节点,并且105成了106的从节点.

然后我们在使用docker start redis1恢复redis1节点.

再次查看集群信息.

101成了从节点,从属于106.

通过上述过程,我们可以看出,集群机制具有故障转移的机制.


集群模式下的故障转移流程

1.故障判定

集群中的所有节点, 都会周期性的使⽤⼼跳包进⾏通信.
1. 节点 A 给 节点 B 发送 ping 包, B 就会给 A 返回⼀个 pong 包. ping 和 pong 除了 message type
属性之外, 其他部分都是⼀样的. 这⾥包含了集群的配置信息(该节点的id, 该节点从属于哪个分⽚,
是主节点还是从节点, 从属于谁, 持有哪些 slots 的位图...).
2. 每个节点, 每秒钟, 都会给⼀些随机的节点发起 ping 包, ⽽不是全发⼀遍. 这样设定是为了避免在节点很多的时候, ⼼跳包也⾮常多(⽐如有 9 个节点, 如果全发, 就是 9 * 8 有 72 组⼼跳了, ⽽且这是按照 N^2 这样的级别增⻓的).
3. 当节点 A 给节点 B 发起 ping 包, B 不能如期回应的时候, 此时 A 就会尝试重置和 B 的 tcp 连接, 看能否连接成功. 如果仍然连接失败, A 就会把 B 设为 PFAIL 状态(相当于主观下线).
4. A 判定 B 为 PFAIL 之后, 会通过 redis 内置的 Gossip 协议, 和其他节点进⾏沟通, 向其他节点确认 B 的状态. (每个节点都会维护⼀个⾃⼰的 "下线列表", 由于视⻆不同, 每个节点的下线列表也不⼀定相同).
5. 此时 A 发现其他很多节点, 也认为 B 为 PFAIL, 并且数⽬超过总集群个数的⼀半, 那么 A 就会把 B 标记成 FAIL (相当于客观下线), 并且把这个消息同步给其他节点(其他节点收到之后, 也会把 B 标记成FAIL).
⾄此, B 就彻底被判定为故障节点了.

2.故障迁移

上述例⼦中, B 故障, 并且 A 把 B FAIL 的消息告知集群中的其他节点.
如果 B 是从节点, 那么不需要进⾏故障迁移.
如果 B 是主节点, 那么就会由 B 的从节点 (⽐如 C 和 D) 触发故障迁移了.
所谓故障迁移, 就是指把从节点提拔成主节点, 继续给整个 redis 集群提供⽀持.
具体流程如下:
1. 从节点判定⾃⼰是否具有参选资格. 如果从节点和主节点已经太久没通信(此时认为从节点的数据和主节点差异太⼤了), 时间超过阈值, 就失去竞选资格.
2. 具有资格的节点, ⽐如 C 和 D, 就会先休眠⼀定时间. 休眠时间 = 500ms 基础时间 + [0, 500ms] 随机时间 + 排名 * 1000ms. offset 的值越⼤, 则排名越靠前(越⼩).
3. ⽐如 C 的休眠时间到了, C 就会给其他所有集群中的节点, 进⾏拉票操作. 但是只有主节点才有投票资格.
4. 主节点就会把⾃⼰的票投给 C (每个主节点只有 1 票). 当 C 收到的票数超过主节点数⽬的⼀半, C 就会晋升成主节点. (C ⾃⼰负责执⾏ slaveof no one, 并且让 D 执⾏ slaveof C).
5. 同时, C 还会把⾃⼰成为主节点的消息, 同步给其他集群的节点. ⼤家也都会更新⾃⼰保存的集群结构信息.
上述选举的过程, 称为 Raft 算法, 是⼀种在分布式系统中⼴泛使⽤的算法. 在随机休眠时间的加持下, 基本上就是谁先唤醒, 谁就能竞选成功.

注意和哨兵的区别,哨兵实现出leader,leader负责找一个从节点升级成主节点.而集群是直接投票选出新的主节点.


集群扩容

101-109九个主机,构成了3主6从结构的集群.

现在将110和111两个节点也加入到集群当中,以110为主节点,111为从节点,同时数据分片从3变为4.

1.新的主节点110加入到集群中

redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379

add-node后的第一组地址是新节点的地址,第二组地址是集群中任意节点的地址,代表整个集群.

此时通过cluster nodes命令查看到110已经成为主节点了,但是还有槽位分配给它.

2.重新分配slots

把之前三组的master上面的槽位各自分出一些来,给到新的主节点.

redis-cli --cluster reshard 172.30.0.101:6379

reshard后的地址是集群中任意节点的地址,reshard代表重新切分的意思.

执行此命令之后,会进入交互式操作,redis会提示用户输入以下内容:

1).多少个slots要进行reshard?

此处我们填写4096.

2).哪个节点接收这些slots?

此处我们填写172.30.0.110这个节点的集群节点的id,上方会有打印,直接粘贴即可.

3).这些slots从哪些节点搬运过来?

此处我们填写all,意思是每个主节点都分一些槽位过来.

也可以手动指定,从某一个或者某几个节点来移动slots,输入以done结尾.

当输入all之后,给出的搬运计划还没有真正开始,当输入yes之后,搬运才真正开始.

此时不仅仅是slots的重新划分,也会把slots上对应的数据,也搬运到新的主机上,这是比较重量的操作!!!

注意,在搬运key的过程中,对于哪些不需要搬运的key,客户端进行访问的时候是没有问题的,但是对于需要搬运的key,进行访问可能会出现短暂的访问错误(因为key的位置发生了变化),随着搬运完成,这样的错误也就自然恢复了.

搬运完成后,就可以看到它的槽位信息了.

3.给新的主节点添加从节点

光有主节点了,此时扩容的⽬标已经初步达成.但是为了保证集群可⽤性,还需要给这个新的主节点添加,从节点,保证该主节点宕机之后,有从节点能够顶上.

redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster-slave --cluster-master-id [172.30.0.110节点的nodeid]

从节点添加完毕!!!


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

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

相关文章

[IDEA] 写代码时没有类型推断的解决方法

本示例使用scala, 其他语言同理 使用 .var 时会自动生成变量 使用快捷键 CtrlAtlv 一样 val abc "abc"但是这个变量没有显式表现类型 期望 val abc: String "abc" 解决方法

【带头学C++】----- 九、类和对象 ---- 9.13 运算符重载——(9.13.1-9.13.4)

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️创做不易&#xff0c;麻烦点个关注❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️ ❤️❤️❤️❤️❤️❤️❤️❤️❤️文末有惊喜&#xff01;献舞一支&#xff01;❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️ 目录 9.13…

Linux安装MySQL数据库系统

1、MySQL的编译安装。 1.1、准备工作 &#xff08;1&#xff09;为了避免发生端口冲突、程序冲突等现象&#xff0c;建议先查询MySQL软件的安装情况&#xff0c;确认没有使用以RPM方式安装的mysql-server、mysql软件包&#xff0c;否则建议将其卸载。 [rootlocalhost ~]# rp…

微信社群机器人开发

简要描述&#xff1a; 删除朋友圈 请求URL&#xff1a; http://域名地址/deleteSns 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId…

蚂蚁集团20篇论文入选AI顶会NeurlPS,7成论文聚焦生成式AI

人工智能新浪潮如火如荼&#xff0c;中国互联网企业奋力逐浪并行。 当地时间12月10日&#xff0c;为期六天的全球AI顶级会议NeurlPS在美国路易斯安那州新奥尔良市举办。NeurlPS披露的数据显示&#xff0c;本届会议共有12343篇有效论文投稿&#xff0c;接收率仅为26.1%。蚂蚁集…

FastAPI之响应模型

前言 响应模型我认为最主要的作用就是在自动化文档的显示时&#xff0c;可以直接给查看文档的小伙伴显示返回的数据格式。对于后端开发的伙伴来说&#xff0c;其编码的实际意义不大&#xff0c;但是为了可以不用再额外的提供文档&#xff0c;我们只需要添加一个 response_mod…

单片双向马达驱动芯片D6208的芯片描述

D6208 是一块单片双向马达驱动电路&#xff0c;它使用TTL电平的逻辑信号就能控制卡式录音机和其它电子设备中的双向马达。该电路由一个逻辑部分和一个功率输出部分组成。逻辑部分控制马达正、反转向及制动&#xff0c;功率输出部分根据逻辑控制能提供100mA&#xff08;典型值&a…

[PyTorch][chapter 6][李宏毅深度学习][Logistic Regression]

前言&#xff1a; logistic回归又称logistic回归分析&#xff0c;是一种广义的线性回归分析模型&#xff0c;常用于数据挖掘&#xff0c;疾病自动诊断&#xff0c;经济预测等领域。 逻辑回归根据给定的自变量数据集来估计事件的发生概率&#xff0c;由于结果是一个概率&#xf…

【docker 】 安装docker(centOS7)

官网 docker官网 github源码 官网 在CentOS上安装Docker引擎 官网 在Debian上安装Docker引擎 官网 在 Fedora上安装Docker引擎 官网 在ubuntu上安装Docker引擎 官网 在RHEL (s390x)上安装Docker引擎 官网 在SLES上安装Docker引擎 最完善的资料都在官网。 卸载旧版本 …

异地现场工控设备,如何实现远程配置、调试?

南京某企业专注于工业物联领域&#xff0c;在相关项目中往往会在各个点位部署基于Linux系统的中控主机&#xff0c;实现各类物联设备信息的采集、汇总。但是&#xff0c;由于各点位分散多地&#xff0c;且数量达到了上百个&#xff0c;虽然中控主机具备4G物联网接入能力&#x…

Vue3-07-样式绑定-style绑定的写法总结

style 绑定的方式 1.html中直接一个属性一个属性的写&#xff1b; 2.直接绑定一个对象&#xff1b; 3.绑定一个包含多个样式对象的数组。style绑定样式的注意点 推荐使用 驼峰命名 规则来编写样式的名称&#xff0c;如 &#xff1a; fontSize:12px; 如果使用 中线分割的规则时…

医美行业-上游厂商的营销规模分析与测算

一、医美行业整体发展趋势&#xff1a;轻医美逐步占领市场&#xff0c;占比逐年增加&#xff0c;规模增速远超手术类医美 从2019年开始医美行业扩张速度放缓&#xff0c;2020年受疫情影响中国美容用户的医美行为有所减少&#xff0c;增速放缓至9.9%&#xff0c;随着疫情的好转及…

计算机组成原理-堆栈寻址

文章目录 堆栈寻址软堆栈vs硬堆栈小结 堆栈寻址 栈结构后进后出 软堆栈vs硬堆栈 硬堆栈用寄存器实现 软堆栈就是用内存实现 小结 入栈和出栈即栈顶元素位置的变化不同

【计算机网络】滑动窗口 流量控制 拥塞控制 概念概述

参考资料&#xff1a;计算机网络第八版-视频课程

LabVIEW实时建模检测癌细胞的异常

LabVIEW实时建模检测癌细胞的异常 癌症是全球健康的主要挑战之一&#xff0c;每年导致许多人死亡。世界卫生组织指出&#xff0c;不健康的生活方式和日益严重的环境污染是癌症发生的主要原因之一。癌症的发生通常与基因突变有关&#xff0c;这些突变导致细胞失去正常的增长和分…

java--Map集合的遍历方式

1.Map集合的遍历方式之一&#xff1a;需要用的Map的如下方法 2.Map集合的遍历方式二&#xff1a;键值对 3.Map集合的遍历方式三&#xff1a;Lambda 需要用的Map的如下方法

mybatis-plus使用达梦数据库处理枚举类型报错的问题

使用mybatis-plus连接达梦数据库&#xff0c;枚举类型无法读取 枚举类&#xff1a; 实体&#xff1a; 数据库字段&#xff1a; mybatis-plus枚举包配置&#xff1a; 调用查询方法&#xff1a; List<QualityRuleTemplate> qualityRuleTemplates ruleTemplateServic…

可视化监控云平台/智能监控EasyCVR如何使用脚本创建ramdisk挂载并在ramdisk中临时运行

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。安防管理视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存…

Datawhale 12月组队学习 leetcode基础 day1 枚举

这是一个新的专栏&#xff0c;主要是一些算法的基础&#xff0c;对想要刷leedcode的同学会有一定的帮助&#xff0c;如果在算法学习中遇到了问题&#xff0c;也可以直接评论或者私信博主&#xff0c;一定倾囊相助 进入正题&#xff0c;今天咱们要说的枚举算法&#xff0c;这是个…

高压功率放大器的作用是什么

高压功率放大器是一种电子设备&#xff0c;其作用是将低电平的信号增强到高功率水平&#xff0c;以驱动要求高电压和电流的负载。它在各种应用中起着至关重要的作用&#xff0c;包括无线通信、医疗仪器、雷达系统、工业控制等领域。 高压功率放大器在无线通信中具有重要意义。在…