[Redis] Redis服务集群

news2024/12/23 17:55:55

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 集群概念介绍
  • 2. 数据分片方式与规则
    • 2.1 哈希求余算法
    • 2.2 一致性哈希算法
    • 2.3 哈希槽分区算法(redis使用)
  • 3. 基于docker搭建集群
  • 4. 主节点宕机自动处理流程
  • 5. 集群扩容

1. 集群概念介绍

集群这个词,可以从广义上来理解,也可以从狭义上来理解,其中广义的集群,只要是多个机器,构成了分布式系统。我们前面学过的哨兵模式,也可以算作是一种广义上的集群。狭义上的集群,是redis提供的一种集群模式,在这个集群模式之下,这个集群模式之下,主要解决存储空间不足的问题,即拓展存储空间
我们前面的哨兵模式提高了系统的可用性,哨兵模式中,本质上还是redis主从节点存储数据,其中要是请求一个主节点/从节点,就得存储整个数据的“全集”。但是集群中主要要解决的问题就是要引入多台机器,每台机器存储一部分数据.只要机器规模足够大,就可以存储任意数据的大小了.比如整个数据全集是1TB,引入三组Master/Salve来存储(注意是三组集群,每组集群中由一个主节点和若干从结点组成,集群中各个服务器存储的数据是相同的).那么每一组机器只需要存储整个数据全集的1/3即可.
在这里插入图片描述
这其中每个服务器集群上都需要存储一定规模的数据,也就是把数据分为了多份,但是数据在分成多份的时候,应该怎么分?这就是我们接下来需要主要研究的问题.

2. 数据分片方式与规则

上面的每个红框中的集群,都可以算是一个数据分片.下面是三种主流的数据分片方式.

2.1 哈希求余算法

所谓哈希求余,就是借鉴了哈希表的基本思想,借助哈希函数,把一个key映射到整数,再针对数据的长度,求余就可以得到一个数组的下标.
哈希求余的分片算法具体是什么样子的呢?
比如有三个分片,编号0 1 2,此时就可以针对要插入的数据的key计算出一个哈希值(计算哈希值的算法,一般是针对一个字符串里面的内容进行一系列的变换,比如md5算法就是一种哈希算法,他是把一个字符串变换成为一个16进制的数字).在把这个哈希值余上一个分片个数,就会得到一个下标.此时就可以把这个数据放到该下标对应的分片中了.
在这里插入图片描述
比如,hash(key) % N => 0,由于求出的余数是0,此时这个key对应的数据就要存储在0号分片中.后续查询key的时候也是同样的算法.只要key是一样的,hash函数式一样的,得到的分片的值就是一样的.
随着业务逐渐增长,数据变多的时候,仅有的几个分片就不足以保存数据了,这就需要对集群进行扩容,引入新的分片.**这时候,哈希求余算法的缺点就体现出来了,就是在增加集群容量,需要对数据进行搬运的时候,开销非常大 **.需要对数据进行搬运的原因就是,集群的数量增加,取余的N会增加,这就使得有些数据不应该待在当前的分片了,就需要重新进行分配.
而这些数据在搬运的时候,大部分的数据都是需要搬运的,这就是扩容的开销非常大.
在这里插入图片描述
从上图中可以看到,其中的21个数据,只有3个key没有被搬运,其他的key都是搬运过的.
当然,哈希求余的分片算法也是有一定优点的,那就是简单高效,数据分配比较均匀.

2.2 一致性哈希算法

哈希求余这种操作中,当前的key属于哪个分片是交替的.
比如某些数据的hash值分别是102,103,104,这些数据在余3之后,得到的值分别是0,1,2,它们哈希求余求出的值是交替的,交替分布在不同的集群中.在一致性哈希这种算法中,我们就把数据交替存储改进成了连续存储.以下的过程就是一致性哈希算法的过程:

  1. 首先把数据空间全部映射到一个圆环上,数据按照顺时针方向增长.
    在这里插入图片描述
  2. 假设当前存在三个分片,把分片放到圆环的某个位置.
    在这里插入图片描述
  3. 假定有一个key,通过哈希函数计算得到的哈希值H,之后把计算出的H映射到圆盘上对应数据的位置.之后从H所在的位置,顺时针向下找,找到的第一个分片,就是该key所从属的分片.
    在这里插入图片描述
    这就相当于,N个分片的位置,把整个圆环分成了N个管辖的区间,key的哈希值落在某个区间内,就归对应区间管理.
    在这里插入图片描述
    在这种一致性哈希算法情况下,如果想要对数据进行扩容,我们需要如何处理呢?原有分片在环上的位置不动,只需要在换上安排一个新的分片即可.
    在这里插入图片描述
    此时只需要把0号分片上的部分数据搬运给3号分片即可,1号分片和2号分片管理的区间都是不变的.
    这种算法的搬运成本相对于哈希求余的方式确实低了不少.虽然搬运的成本低了,但是缺点就是这几个分片的数据量就可能会发生某种程度上的不均匀,也就是发生数据倾斜.

2.3 哈希槽分区算法(redis使用)

这种算法是redis真正采用的算法,为了解决上述问题,redis集群就引入了哈希槽算法

hash_slot = crc16(key) % 16384
其中crc也是一种哈希算法,16384其实是16*1024,也就是2^14

其实这种算法就是把一致性哈希和哈希求余两种方式结合一下.也就是把哈希值映射到16384个槽位上.
然后再把这些槽位均匀地分给每个分片
,每个分片的接地那都需要记录自己持有哪些分片.每个分片都会使用"位图"这样的数据结构来表示出当前有多少槽位号,每一位用0/1来区分自己这个分片当前是否持有该槽位号
假设当前有三个分片,一种可能得分配方式:
• 0号分片:[0,5461],共5462个槽位
• 1号分片:[5462,10923],共5462个槽位
• 2号分片:[10924,16383],共5460个槽位
这里只是一种可能得分片方式,实际上分片方式是很灵活的.每个分片持有的槽位号,是可以连续,也可以不连续的.这里的分配虽然不是严格意义上的"均匀",但是差异却非常小了.此时这三个分片上的数据已经在某种程度上比较均匀了.
如果后需要进行扩容,比如新增一个3号分片,就可以针对原有的槽位进行重新分配.比如可以把之前的每个分片持有的槽位各拿出一点,分给新的分片:
• 0号分片:[0,4095],共4096个槽位
• 1号分片:[5462,9557],共4096个槽位
• 2号分片:[10924,15019],共4096个槽位
• 3号分片:[4096,5461]+[9558,10923]+[15019,16383],共4096个槽位
此外,还有一些其他的问题:

  1. redis集群最多有16384个分片吗?
    key是要先映射到槽位上,在映射到分片上的.如果每个分片包含的槽位比较多,槽位个数相当,就可以认为包含的key的个数是相当的,那么就可以认为数据分布式均匀的.如果每个分片包含的槽位非常少,槽位个数不一定直观反应到key的数目,这种情况之下,数据均匀性是很难保证的.而且如果每个分片中包含的槽数非常少,这就会使得集群的服务器规模非常庞大,服务器越多,出现故障的概率就越大.
    在redis官方文档中提到,作者建议我们集群的分片数不应该超过1000.
  2. 为什么是16384个槽位?
    这是由于结点之间需要通过心跳包进行通信,心跳包通过网络来在结点之间发送,心跳包中包含了该结点持有了哪些槽位,如果每个心跳包中给定的槽位数更多了,这时候心跳包就会变大,会增加网络传输上的开销.

3. 基于docker搭建集群

在搭建docker集群的时候,一定要记得把之前启动的redis容器给停止掉.否则可能会产生端口上的冲突.我们需要搭建的集群环境如下:
在这里插入图片描述
由于我们需要创建的redis结点较多,redis结点之间大同小异.在Linux操作系统的环境之下,我们需要引入shell脚本来批量创建.
就是把shell命令操作写入了一个文件中,批量化执行,同时还可以加入,条件,循环,函数机制等.

  1. 首先批量生成redis配置文件.创建redis-cluster目录.内部创建shell脚本文件,命名为generate.sh注意文件后缀必须是sh.
    generate文件的内容如下:
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
  1. 之后在redis-cluster目录之下执行命令执行脚本.bash generate.sh.注意想要在指定的目录中生成文件,必须在指定的目录之下执行命令,于是就会在目录之下批量生成指定目录和配置文件.
redis-cluster/
├── generate.sh 
├── redis1 
│   └── redis.conf 
├── redis10 
│   └── redis.conf 
├── redis11 
│   └── redis.conf 
├── redis2 
│   └── redis.conf 
├── redis3 
│   └── redis.conf 
├── redis4 
│   └── redis.conf 
├── redis5 
│   └── redis.conf 
├── redis6 
│   └── redis.conf 
├── redis7 
│   └── redis.conf 
├── redis8 
│   └── redis.conf 
└── redis9 
 └── redis.conf 

其中每个redis.conf每个都不同.区别在与每个配置中配置的cluster-announce-ip是不同的,其他的部分都是相同的.

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.101
cluster-announce-port 6379
cluster-announce-bus-port 16379

我们对conf文件中的这些字段来解释一下:
- cluster-enabled: 开启集群
- cluster-config-file: 启动结点之后,redis自动配置的一些集群信息,这些是redis自动生成的,不需要手写.
- cluster-node-timeout: 多个结点之间需要进行交互,保持联络,如果发送心跳包之后,超过这个时间没有回应,则会主观判定为宕机.
- cluster-announce-ip: 该redis接地那所在主机的ip地址.当前是使用docker容器模拟主机,此处写的应该是docker容器的ip.
- cluster-announce-port: 业务端口,用来进行业务数据通信
- cluster-announce-bus-port: 管理端口,为了完成一些管理上的任务来进行通信.
3. 之后就需要使用docker来创建出redis容器了.在redis-cluster目录之下创建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,5,6...同理
  • subnet: 此处为了后续创建静态的ip,就需要先手动创建出网络,同时给这个网段分配ip,这里分配的网络号是172.30.0,其中这个网络号是私网格式的一种,需要注意的是,不能和当前主机上现有的其他网段冲突,0/24是主机号.
  • volumes: 配置文件映射
  • ports: 端口映射,需要注意的是,映射右边的端口必须和配置文件中的保持一致.
  • ipv4_address: 静态配置的网络ip,这里的ip也必须和之前的配置文件中的一致.
  1. 启动容器docker-compose up -d
  2. 接下来就需要把这些服容器全部构建为集群
    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表示每个主节点需要两个从结点备份.设置了这个配置之后,redis就会知道,每3个结点是一伙的(一个分片).但是分配的时候,谁是主节点,谁是从结点,都是随机的.
      执行之后,容器之间会进行加入集群操作.之后系统会弹出日志,描述集群的搭建是增怎样的.输入yes之后才会真正创建.见到[OK]之后说明集群建立完成.
  3. 使用客户端连上集群中的任何一个结点,都相当于连上了整个集群.redis-cli -h 172.30.0.101 -p 6379,在客户端中,我们使用cluster nodes来查看当前集群的信息,但是存在一个问题,我们知道redis集群中存储数据的时候是使用哈希槽分区算法来分配数据的,如果我们以这种姿势启动客户端的话,如果set的key不属于所在主节点的集群的话,就会报错.
    在这里插入图片描述
    所以我们在启动客户端的时候,我们就需要在后面加上一个-c,这时候如果所添加的key不属于当前的集群的话,就会重定向到其他对应分片上的主机中.后期获取也是可以直接获取到的.
172.30.0.101:6379> set k1 1
-> Redirected to slot [12706] located at 172.30.0.103:6379
OK
172.30.0.103:6379> get k1
"1"

4. 主节点宕机自动处理流程

如果集群中的主节点发生了宕机,此处集群做的工作就和之前哨兵做的工作类似了,就会自动的把该主节点旗下的从结点给挑出来一提拔为主节点.
但是此处的故障处理转移,具体的流程还和哨兵有一些区别.

  1. 故障判定,通过周期性发送心跳包来判定某个结点是否挂掉.
    结点A首先给结点B发送ping包,如果B不能如期回应的时候,A就会尝试重置和B的tcp连接,看能否连接成功,如果仍然连接失败,A就会把B设置为PFAIL(主观下线)状态.== A判定B为主观下线之后,会通过redis内置的gossip协议,和其他节点进行沟通==,向其他节点确认B的状态.此时A发现其他很多结点都认为B主观下线了,并且数目超过了集群总个数的一半,那么A就会把B标记为客观下线.并且把这个消息同步给其他的结点,其他节点收到之后,也会把B标记为客观下线.

  2. 故障迁移
    如果B是从结点,就不需要进行故障迁移.如果B是主节点,那么就会由B的从结点(比如C和D)触发故障迁移.把从结点提拔为主节点.
    从结点首先判定自己是否具有参选资格.如果主节点和从结点太久没有通信,那么就证明主节点和从结点的数据差异太大了,就会失去竞选资格.具有资格的结点,比如C和D,就会先休眠一定的时间.休眠时间=500ms基础时间+[0,500ms]随机时间+排名*1000ms. 其中offset越大,则排名越靠前(越小),offset越大,数据就越靠近主节点,排名就会更靠前休眠时间也更短.比如C的休眠时间到了,C就会给其他所有集群中的结点进行拉票操作.但是只有主节点才有投票的资格.主节点就会把自己的票投给C.当C收到的票数超过主节点的一半的时候,C就会晋升为主节点.同时C还会把自己成为主节点的消息通知其他集群的结点,大家也都会更新自己保存的集群结构的信息.

上述的选举过程符合Raft算法,在随机休眠时间的加持之下,基本上谁先唤醒,谁就可以竞选成功.

上述和哨兵最明显的区别就是,哨兵是选取一个Leader来进行提拔主节点,而这里是直接通过主节点投票选举出主节点

5. 集群扩容

扩容会涉及到大量数据的迁移操作,所以扩容是一件风险比较高,成本比较大的操作.

  1. 把新的主节点加入到集群中
    redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
    add-node之后的第一组地址是新节点的地址,第二组是集群中的任意节点地址,表示把新的结点添加到哪个集群中去.
  2. 重新分配哈希槽位
    把之前Master上面的slots拎出来一些,分配给新的master.
    redis-cli --cluster reshard 172.30.0.101:6379
    reshard之后的地址是集群中任意一个结点的地址.
    执行之后,会进入交互式操作,redis会询问一下内容:
    • 多少个槽位需要reshard?
    • 哪个结点来接收槽位?此处填写新加入的结点.
    • 这些槽位从哪些结点搬运过来?此处如果填写all,表示的就是每个主节点都会拿一点槽位过来,如果手动指定,就会动指定的某个或者是几个节点来搬运槽位.
    • 之后会打印初步分配方案,让用户确认,确定的时候输入yes即可.在搬运真正开始的时候,此时不仅仅是槽位的重新划分,也会把槽位上对应的数据搬运到新的主机上,此时是一个比较重量的操作,可能需要消耗一定的时间.

注意在搬运的时候,在迁移的槽位不可被访问,其他未搬运的key是可以正常访问的

  1. 给新的主节点添加从结点
    redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --clusterslave --cluster-master-id [172.30.1.110 节点的 nodeId]
    此时扩容目标初步达成,但是为了保证整个集群的可用性,还需要给主节点添加一些从结点,保证主节点宕机之后,有接班人.

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

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

相关文章

LLaMA-Factory全流程训练模型

&#x1f917;本文主要讲述在docker下使用LLaMA-Factory训练推理模型。 &#x1fae1;拉取镜像 首先需要启动docker&#xff0c;然后在终端中输入&#xff1a; docker run -tid --gpus all -p 8000:8000 --name LLM -e NVIDIA_DRIVER_CAPABILITIEScompute,utility -e NVIDIA…

计算机组成原理对于学习嵌入式开发的意义

计算机组成原理对于学习嵌入式开发的意义 前言 最近有位同学向我咨询&#xff0c;问学习嵌入式开发需不需要学习硬件&#xff1f;进而引申到了需不需要学习计算机组成原理呢&#xff1f; 正文 首先计算机组成原理是计算机科学与技术专业的一门核心基础课程&#xff0c;它深入…

Python学习从0到1 day27 Python 高阶技巧 ③ 设计模式 — 单例模式

此去经年&#xff0c;再难同游 —— 24.11.11 一、什么是设计模式 设计模式是一种编程套路&#xff0c;可以极大的方便程序的开发最常见、最经典的设计模式&#xff0c;就是我们所学习的面向对象了。 除了面向对象外,在编程中也有很多既定的套路可以方便开发,我们称之为设计模…

算法---解决“汉诺塔”问题

# 初始化步骤计数器 i 1 # 定义移动盘子的函数 def move(n, mfrom, mto): global i # 使用全局变量i来跟踪步骤 print("第%d步:将%d号盘子从%s->%s" % (i, n, mfrom, mto)) # 打印移动步骤 i 1 # 步骤计数器加1 #第一种方法 # 定义汉诺塔问题的递归…

2024游戏陪玩app源码的功能介绍/线上陪玩交友上线即可运营软件平台源码搭建流程

一个完整的陪玩交友系统从概念到实现再到维护的全过程得以清晰展现。每一步都需要团队的紧密协作与细致规划&#xff0c;以确保系统既满足用户需求&#xff0c;又具备良好的稳定性和可扩展性。 基础框架 移动端开发框架&#xff1a;如uniapp&#xff0c;它支持多平台开发&…

AGI自学分享,简单有用的理论与实践

开始必备 谷歌邮箱 没有谷歌邮箱简直“寸步难行”。 GitHub Build and ship software on a single, collaborative platform GitHub GitHub上有所有开源项目的源代码&#xff0c;当然还有许许多多资源的分享。 huggingface huggingface上的space可以试用许多模型demo&a…

基于stm32的智能变频电冰箱系统

基于stm32的智能变频电冰箱系统 持续更新&#xff0c;欢迎关注!!! 基于stm32的智能变频电冰箱系统 随着集成电路技术的发展&#xff0c;单片微型计算机的功能也不断增强&#xff0c;许多高性能的新型机种不断涌现出来。单片机以其功能强、体积小、可靠性高、造价低和开发周期短…

[OpenGL]使用OpenGL实现透明效果

一、简介 本文介绍了如何使用OpenGL实现透明效果&#xff08;transparent&#xff09;&#xff0c;并在最后给出了全部的代码。 在实现透明效果时&#xff0c;使用OpenGL中的混合&#xff08;Blend&#xff09;功能&#xff0c;根据纹理贴图的 alpha 分量将各像素&#xff08;…

ABAP关于PS模块CJ20N中项目物料的屏幕和字段增强CI_RSADD

网上搜关于CJ20N的屏幕增强,基本都是关于项目定义(CI_PROJ)、项目WBS(CI_PRPS)、项目网络活动工序(CI_AFVU)的字段与屏幕增强,几乎没有关于项目物料(CI_RSADD)的字段屏幕增强,我在这里做一个分享。 主要逻辑:实现badi增强,并自建一个函数组后创建屏幕,在badi里面调用…

Android setTheme设置透明主题无效

【问题现象】 1、首先&#xff0c;你在AndroidManifest.xml中声明一个activity&#xff0c;不给application或者activity设置android:theme, 例如这样&#xff1a; <applicationandroid:allowBackup"true"android:icon"mipmap/ic_launcher"android:lab…

windows下git和TortoiseGit(小乌龟)和putty安装配置对github进行操作

本次安装版本如下&#xff1a; 1&#xff0c;先下载安装tortoiseGit一路下载安装即可一直到在桌面上右键可以看到有git的选项出现为止&#xff0c;注意在第一步的时候选择使用putty还是ssh建立网络连接决定后面的步骤&#xff0c;本次以选择putty为例。 2&#xff0c;安装git&a…

Flutter:input输入框

输入框&#xff1a; // 是否显示关闭按钮 bool _showClear false; // 文字编辑控制器&#xff0c;监听搜索框的变化。 final TextEditingController _controller TextEditingController(); // 输入框发生变化事件 void _onChange(String value){if(value.length > 0){setS…

Ubuntu相关指令

1、查看 Ubuntu 系统的版本信息&#xff0c;在终端输入&#xff1a; lsb_release -a该命令会输出类似如下的信息&#xff1a; No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.4 LTS Release: 22.04 Codename: jammy 在 Re…

Unity教程(十八)战斗系统 攻击逻辑

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

【软件测试】设计测试用例的方法(正交法、判定表法、错误猜测法),测试文档的写法

文章目录 正交法正交表设计正交表 判定表法判定表 设计测试用例的步骤 错误猜测法测试文档 正交法 正交试验设计(Orthogonal experimentaldesign)是研究多因素多⽔平的⼀种设计⽅法&#xff0c;它是根据正交性&#xff0c;由试验因素的全部⽔平组合中挑选出部分有代表性的点进…

MySQL技巧之跨服务器数据查询:进阶篇-从A数据库复制到B数据库的表中

MySQL技巧之跨服务器数据查询&#xff1a;进阶篇-从A数据库复制到B数据库的表中 基础篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的连接名: MY_ODBC_MYSQ…

网络安全练习之 ctfshow_web

文章目录 VIP题目限免&#xff08;即&#xff1a;信息泄露题&#xff09;源码泄露前台JS绕过协议头信息泄露robots后台泄露phps源码泄露源码压缩包泄露版本控制泄露源码(git)版本控制泄露源码2(svn)vim临时文件泄露cookie泄露域名txt记录泄露敏感信息公布内部技术文档泄露编辑器…

Elasticsearch retrievers 通常与 Elasticsearch 8.16.0 一起正式发布!

作者&#xff1a;来自 Elastic Panagiotis Bailis Elasticsearch 检索器经过了重大改进&#xff0c;现在可供所有人使用。了解其架构和用例。 在这篇博文中&#xff0c;我们将再次深入探讨检索器&#xff08;retrievers&#xff09;。我们已经在之前的博文中讨论过它们&#xf…

debug笔记:gpustat显示没有进程运行,但是GPU显存被占用

1 问题描述 使用gpustat之后&#xff0c;虽然显示除了gpu5之外别的都没有进程&#xff0c;但是GPU显存却被占用了 2 解决方法 原因是存在僵尸进程&#xff0c;已经运行完&#xff0c;但是内存并没有释放 fuser -v /dev/nvidia* 这个指令查看僵尸进程 然后kill掉即可&#…

【Chapter 3】Machine Learning Classification Case_Prediction of diabetes-XGBoost

文章目录 1、XGBoost Algorithm2、Comparison of algorithm implementation between Python code and Sentosa_DSML community edition(1) Data reading and statistical analysis(2)Data preprocessing(3)Model Training and Evaluation(4)Model visualization 3、summarize 1…