Redis集群(Cluster)
1. 什么是集群
- 广义的集群:只要是多台机器,构成一个分布式系统,就可以称为一个“集群”。像前面的主从结构,哨兵模式都是“广义的集群”
- 狭义的集群:redis提供的集群模式,这个集群模式主要解决存储空间不足的问题
例如整个数据全局是1TB,引入三组Master/Slave来存储,那么每一组Master/Slave存储数据全集的一部分,从而构成一个更大的整体,称为redis集群(Cluster)
在上图中,这三组机器存储的数据都不一样,每个slave都是对应master的备份(当master挂了,就会选举一个slave成为新的master)。每个红框部分称为一个分片,如果全量数据进一步增加,只要再增加更多,即可解决。
2.数据分片算法
2.1 哈希求余
借鉴哈希表的基本思想,针对要插入的数据的key(redis都是键值对结构)计算hash值(比如使用MD5计算hash值)。再把这个hash值余上分片个数,就得到一个下标。此时就可以把这个数据放到该下标对应的分片中。即hash(key) % N
md5是一个非常广泛使用的hash算法
- md5计算的结果是定长的,无论输入的原字符串多长,最终算出的结果都是固定长度
- md5计算的结果是分散的,两个原字符串,哪怕大部分都相同,只有一小部分不同,算出来的结果也会差别很大。因此使用md5作为hash函数,可以有效避免hash冲突
- md5计算的结果是不可逆的,给你原字符串,很容易算出md5值;给你md5值,很难还原出原始字符串。因此常使用md5加密
优点
简单高效,数据分配均匀
缺陷
随着业务增长,数据变多,现有分片不够使用。需要进行“扩容”,需要重新进行hash,计算新的下标。
上图中一共20个数据,只有3个数据不需要搬运,如果是20亿的数据,就需要搬运17亿!!!并且每个分片中不止有主节点还有从节点,需要进行主从同步,开销特别大。
2.2 一致性哈希
使用hash求余中,当前key属于哪个分片是交替的。像上图中,102属于0号分片,103属于1号分片,104属于2号分片,105又数据0号分片,交替出现,导致搬运成本非常高。
而一致性哈希把交替出现,改进成连续出现。
- 把0->2^32-1的数据空间,映射到一个圆环上,数据按照顺时针方向增长
- 假设当前存在三个分片,就把分片放到圆环的某个位置上
- 假定有一个key,计算得到的hash值为H,那么这个key映射到哪个分片规则是,从H所在位置,顺时针往下找,找到第一个分片,就是该key所从属的分片
N个分片把整个圆环分成了N个管辖区间,key的hash值落在某个区间内,就归对应区间管理
扩容
从3个分片扩容到4个分片时
此时,只需要将0号分片上的部分数据给搬运到3号分片上即可,1,2号分片管理的区间不变。
- 优点:大大降低了扩容是数据搬运的规模,提高了扩容操作的效率
- 缺点:数据分配不均匀,会数据倾斜
2.3 哈希槽分区算法
这是redis采用的分片算法,可以有效解决搬运成本高和数据分配不均的问题,redis cluster引入哈希槽(hash slots)算法。
:::tips
hash_slot = crc16(key) % 16384
:::
hash_slot 哈希槽
其中crc16也是一种hash算法
16384 = 16 * 1024 即16k
相当于把整个哈希值,映射到16384个槽位上,即[0,16383].
然后再把这些槽位比较均匀的分配给每个分片,每个分片的节点都需要记录自己持有的那些槽位。
例如当前有三个分片,可能的分配方式:
- 0号分片:[0,5461],共5462个槽位
- 1号分片:[5462,10923],共5463个槽位
- 2号分片:[10924,16383],共5460个槽位
:::success
每个分片会使用“位图”这样的数据结构表示出当前有多少槽位。16384个bit位,用每一位的0/1来区分自己这个分片当前是否持有该槽位号。16384%8=2048,即2kb
:::
扩容
例如新增一个分片,就需要针对原有的槽位进行重新分配
- 0号分片: 【0,4095】共4096个槽位
- 1号分片:【5462,9557】共4096个槽位
- 2号分片:【10924,15019】共4096个槽位
- 3号分片:【4096,5461】+【9558,10923】+【15020,16383】共4096个槽位
在上述过程中,只有被移动的槽位,对应的数据才需要被搬运。并且分片上的槽位号,不一定是连续的区间。
哈希槽分区算法的实质:结合了哈希算法和一致性哈希的思想,
问题1:redis集群最多有16384个分片吗?
一共有16384个槽位,如果是16384个分片,意味着一个分片一个槽位,此时很难保证数据再各个分片的均衡性。key要先映射到槽位,再映射到分片中。如果每个分片的包含的槽位比较多,槽位个数相当,就可以认为包含的key的数量也是相当的。如果每个分片包含的槽位非常少,槽位个数不一定能直观反应到key的数目,因为有的槽位,有多个key,有的槽位,可能没有key.并且redis作者建议集群分片数不超过1000
问题2:为什么是16384个槽位
redis作者答案:https://github.com/antirez/redis/issues/2576
节点之间通过心跳包通信,心跳包中包含该节点持有拿下slots,这个是使用位图表示,表示16384(16k)个slots,需要位图大小是2kb。如果给定的slots数更多,比如65536,需要8kb位图表示,8kb对于内存不算什么,但是在频繁的网络心跳包中,是一个不小的开销。
另一方面,redis集群不建议超过1000个分片,所以16k对于最多1000个分片来说是足够用的,同时也会使对应的槽位配置位图体积不至于很大。
3. 搭建redis集群
基于docker,搭建一个集群,每个节点都是一个容器,拓扑结构如下:
注意:我们一共会创建11个redis节点,其中前9个用来演示集群搭建,后两个用来演示集群扩容
3.1创建目录和配置
- 创建redis-cluster目录,内部创建两个文件
docker-compose.yml
和generate.sh
- 关掉所有启动的redis容器,防止后续发生端口冲突
可以通过
docker ps -a
来查看是否全部关闭
- 执行shell脚本,
generate.sh
内容如下
:::tips
for port in KaTeX parse error: Undefined control sequence: \< at position 12: (seq 1 9); \̲<̲br />do \<br />…{port}/
touch redis p o r t / r e d i s . c o n f < b r / > c a t < < E O F > r e d i s {port}/redis.conf<br />cat << EOF > redis port/redis.conf<br/>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 KaTeX parse error: Undefined control sequence: \< at position 14: (seq 10 11); \̲<̲br />do \<br />…{port}/
touch redis p o r t / r e d i s . c o n f < b r / > c a t < < E O F > r e d i s {port}/redis.conf<br />cat << EOF > redis port/redis.conf<br/>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
:::
执行命令
:::tips
bash generate.sh
:::
生成目录如下
其中每个redis.conf都不相同,以redis1为例:
区别在于每个配置中
cluster-announce-ip
是不同的,其他部分都相同,因为后续会给每个节点分配不同的ip地址
配置说明:
cluster-enabled yes
开启集群cluster-config-file nodes.conf
集群节点生成的配置cluster-node-timeout 5000
节点失联的时间cluster-announce-ip 172.30.0.101
节点自身的ipcluster-announce-port 6379
节点自身的业务端口cluster-announce-bus-port 16379
管理端口,用来给一些管理上的任务通信的。例如主节点挂了,需要让从节点成为主节点,就需要通过刚才管理端口来完成对应的操作
3.2 编写docker-compose.yml
version: '3.3'
networks:mynet:ipam:config:- subnet: 172.30.0.0/24
services:redis1:image: 'redis:5.0.9'container_name: redis1restart: alwaysvolumes:- ./redis1/:/etc/redis/ports:- 6371:6379- 16371:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.101redis2:image: 'redis:5.0.9'container_name: redis2restart: alwaysvolumes:- ./redis2/:/etc/redis/ports:- 6372:6379- 16372:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.102redis3:image: 'redis:5.0.9'container_name: redis3restart: alwaysvolumes:- ./redis3/:/etc/redis/ports:- 6373:6379- 16373:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.103redis4:image: 'redis:5.0.9'container_name: redis4restart: alwaysvolumes:- ./redis4/:/etc/redis/ports:- 6374:6379- 16374:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.104redis5:image: 'redis:5.0.9'container_name: redis5restart: alwaysvolumes:- ./redis5/:/etc/redis/ports:- 6375:6379- 16375:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.105redis6:image: 'redis:5.0.9'container_name: redis6restart: alwaysvolumes:- ./redis6/:/etc/redis/ports:- 6376:6379- 16376:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.106redis7:image: 'redis:5.0.9'container_name: redis7restart: alwaysvolumes:- ./redis7/:/etc/redis/ports:- 6377:6379- 16377:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.107redis8:image: 'redis:5.0.9'container_name: redis8restart: alwaysvolumes:- ./redis8/:/etc/redis/ports:- 6378:6379- 16378:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.108redis9:image: 'redis:5.0.9'container_name: redis9restart: alwaysvolumes:- ./redis9/:/etc/redis/ports:- 6379:6379- 16379:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.109redis10:image: 'redis:5.0.9'container_name: redis10restart: alwaysvolumes:- ./redis10/:/etc/redis/ports:- 6380:6379- 16380:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.110redis11:image: 'redis:5.0.9'container_name: redis11restart: alwaysvolumes:- ./redis11/:/etc/redis/ports:- 6381:6379- 16381:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.111
3.3 启动容器
启动之前检查redis服务是否全部关闭
启动容器
:::tips
docker-compose up -d
:::
验证是否启动
:::tips
docker ps -a
:::
3.4 构建集群
此处,把前9个主机构成集群,3主6从。后两个主机用来演示后续扩容
:::tips
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 2172.30.0.105:6379
:::
3.5 使用集群
此时,使用客服端连上集群中的任何一个节点,都相当于连上整个集群。使用命令redis-cli -h 172.30.0.101 -p 6379 -c
- 客服端后面要加上
-c
选项,因为通过“哈希槽分区算法”计算出对应的哈希槽,如果该哈希槽不在该分片,而是在其他分片就访问不到。加上-c
就会自动把请求重定向到对应的节点
- 使用
cluster nodes
可以查看整个集群的情况
- 如果在从节点进行写操作,会重定向到master节点
4. 故障处理
4.1 主节点宕机
在上述的拓扑结构中,redis1,redis2,redis3是主节点,挑选一个停掉
:::tips
docker stop redis1
:::
重新启动redis1
:::tips
docker start redis1
:::
4.2 故障处理流程
1. 故障判定,识别出某个节点是否挂了
- 节点A给节点B发送ping包,B就给A返回pong包,包含右集群的配置信息(该节点的id,该节点从属于哪个分片,是主节点还是从节点,属于哪个主节点,持有那些
slots
的位图) - 每个节点,每秒钟都会随机给一些节点发送ping包,而不是全发一遍。这样的设定是为了避免如果节点很多,心跳包也会很多(例如9个节点,如果全发,就是9*8=72组心跳包,而且是按照N^2级别增长)
- 当节点A给节点B发送ping包,B不能如期回应的时候,此时A就会尝试重置和B的tcp连
接,看是否能连接成功,如果仍然连接失败,A就会把B设为PFALL
状态(主观下线) - A判定B为
PFALL
之后,会通过redis内置的Gossip协议,和其他节点进行沟通,向其他节点确认B的状态(每个节点都会维护一个自己的”下线列表“,由于视角不同,每个节点的下线列表也不一定相同) - 此时A发现很多其他节点也认为B为
PFALL
,并且数目超过集群个数的一半,那么A就会把B标记FALL
(客观下线),并把消息同步给其他节点,其他节点收到后,也会把B标记为FALL
2. 故障迁移
- 如果B是从节点,那么不需要进行故障迁移
- 如果B是主节点,那么就会从B的从节点中挑选一个(比如C和D)触发故障迁移
- 从节点会判定自己是否具有参选资格,如果从节点和主节点已经很久没有通信,即很久没有同步过数据,主从节点之间差异较大,时间超过阈值,就失去竞选资格
- 具有资格的节点,比如C和D,就会先休眠一段时间,休眠时间=500ms基础时间+[0,500ms]随机时间 + 排名 * 1000ms。offset值越大,排名越靠前(越小)
- 比如C的休眠时间到了,C就会给集群中其他节点,进行拉票操作,但是只有主节点才有投票资格
- 主节点就会把自己的票投给C(每个主节点只有一票),当C收到的票数超过主节点数目的一半,C就会晋升为主节点。(C自己负责执行
slaveof no one
,并且让D执行slaveof C
) - 同时,C还会将自己成为主节点的信息,同步给集群的其他节点,大家也会更新自己保存的集群结构信息。
哨兵模式,是先投票竞选出一个leader,让leader负责找一个从节点升级为主节点。而集群模式里直接投票选出新的主节点
4.3 出现集群宕机
- 某个分片,所有的主节点和从节点都挂了
- 某个分片,主节点挂了,但是没有从节点
- 超过半数的master节点都挂了
5. 集群扩容
现在搭建的集群的主机号101-109,9个主机,构成了3主6从结构的集群。现在将主机号为110和111也加入集群中,以110为master,111为slave,数据分片从3->4。
5.1 添加主节点
将新的主节点110加入到集群中
:::tips
redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
:::
- 172.30.0.110:6379:新增节点的地址
- 172.30.0.101:6379:集群上任意一个节点的地址都可以,表示要把这个新节点添加到这个集群上
重新分配slots
:::tips
redis-cli --cluster reshard 172.30.0.101:6379
:::
- 172.30.0.101:6379:集群中任意节点的地址都可以,表示这个集群
此处是询问用户要移动多少的slots给新增的主节点,我们这里分成4片,即4096
这是问你要把这些哈希槽分配给谁,输入他的id
有两种分配方式让你选择
- all,表示从其他每个持有slots的master节点都拿一些过来
- 手动指定,从某一个/几个节点来移动slots,输入完他们的id,以done结尾
当输入yes才是真正开始搬运
问题:在搬运slots/key的过程中,此时客服端能否访问到redis集群
搬运key,大部分key是不用搬运的,针对这些未搬运的key,是可以正常访问的.针对这些正在搬运的key,是有可能出现访问出错的情况.
例如客服端访问key1,集群通过分片算法,得到key1是第一个分片的数据,就会重定向到第一个分片的节点,就可能在重定向过去之后,正好key1被搬走,自然就无法访问.
5.2 从节点添加到集群中
将主机号111添加到集群中,作为主机号110的从节点
:::tips
redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster-slave --cluster-master-id [172.30.1.110节点的nodeid]
:::
相关文章:

Redis集群(Cluster)
1. 什么是集群 广义的集群:只要是多台机器,构成一个分布式系统,就可以称为一个“集群”。像前面的主从结构,哨兵模式都是“广义的集群”狭义的集群:redis提供的集群模式,这个集群模式主要解决存储空间不足…...

Scapy 解析 pcap 文件从HTTP流量中提取图片
Scapy 解析 pcap 文件从HTTP流量中提取图片 前言一、网络环境示例二、嗅探流量示例三、pcap 文件处理最后参考 作者:高玉涵 时间:2023.9.17 10:25 环境:Linux kali 5.15.0-kali3-amd64,Python 3.11.4,scapy…...

难得有个冷静的程序员发言了:纯编码开发实施的项目,失败的案例也有很多
难得有个冷静的程序员发言了:纯编码开发实施的项目,失败的案例也有很多。假如用低代码实施,能达到不失败或提高成功率,对软件开发项目交付,会是重大的价值。 我的观点:两者都可能失败,不同的是&…...
Leetcode.146 LRU 缓存
题目链接 Leetcode.146 LRU 缓存 mid 题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 c a p a c i t y capacity capacity 初始化 LRU 缓存int get(int key) 如果关键…...

科技资讯|Canalys发布全球可穿戴腕带设备报告,智能可穿戴增长将持续
市场调查机构 Canalys 近日发布报告,表示 2023 年第 2 季度全球可穿戴腕带设备出货量达 4400 万台,同比增长了 6%。 主要归功于其亲民的价格以及消费者对价位较高的替代品仍持谨慎态度,基础手环市场尽管与去年同期相比有所下降,…...
使用https接口,无法调通接口响应不安全
网页pc使用不安全https 页面提示不安全–点击高级–跳过 接口使用部安全https 无法像页面一样可以跳过 方法:安装证书 还是无法响应报错不安全: 1、确定证书绑定ip还是域名(ip和域名都可以绑定) 使用的是httpsip,报…...

uniapp开发h5,解决项目启动时,Network: unavailable问题
网上搜了很多,发现都说是要禁用掉电脑多余的网卡,这方法我试了没有好,不晓得为啥子,之后在网上看,uniapp的devServer vue2的话对标的就是webpack4的devserver(除了复杂的函数配置项),…...
9.17 校招 实习 内推 面经
绿泡*泡: neituijunsir 交流裙 ,内推/实习/校招汇总表格 1、自动驾驶一周资讯 - 一汽与Mobileye 签署战略合作,小鹏汽车将用经销商销售逐渐替换直营模式,原小鹏汽车副总裁加盟赛力斯 自动驾驶一周资讯 - 一汽与Mobileye 签署战…...

【Python小项目之Tkinter应用】随机点名/抽奖工具大优化:新增查看历史记录窗口!语音播报功能!修复预览文件按钮等之前版本的bug!
文章目录 前言一、实现思路二、关键代码查看历史记录按钮语音播报按钮三、完整代码总结前言 老生常谈,先看效果:(订阅专栏可获取完整代码) 初始状态下,我们为除了【设置】外的按钮添加弹窗,提示用户在使用工具之前要先【设置】。在设置界面,我们主要修改了【预览文件】…...

数据结构与算法:排序算法(1)
目录 冒泡排序 思想 代码实现 优化 鸡尾酒排序 优缺点 适用场景 快速排序 介绍 流程 基准元素选择 元素交换 1.双边循环法 使用流程 代码实现 2.单边循环法 使用流程 代码实现 3.非递归实现 排序在生活中无处不在,看似简单,背后却隐藏…...

NotePad++ 在行前/行后添加特殊字符内容方法
我们在处理数据时,会遇到需要在每行数据前面、后面、开头、结尾添加各种不一样的字符 如果数据不多,我们可以自己手动的去添加,但如果达到了成百上千行,此时再机械的手动添加是不现实的 这里教给大家如何快速的在数据每行的前后…...

【JavaEE】多线程案例-线程池
文章目录 1. 什么是线程池2. 为什么要使用线程池(线程池有什么优点)3. 如何使用Java标准库提供的线程池3.1 创建一个线程池对象3.2 什么是工厂模式3.3 为什么要使用工厂模式3.4 Executors 创建不同具有不同特性的线程池3.5 ThreadPool 类的构造方法3.6 线…...

服务器搭建(TCP套接字)-fork版(服务端)
基础版的服务端虽然基本实现了服务器的基本功能,但是如果客户端的并发量比较大的话,服务端的压力和性能就会大打折扣,为了提升服务端的并发性能,可以通过fork子进程的方式,为每一个连接成功的客户端fork一个子进程,这样…...
缺失的第一个正数:高效解法与技术
缺失的第一个正数:高效解法与技术 背景 在计算机编程中,有时候需要寻找一个未排序整数数组中没有出现的最小的正整数。这篇技术博客将详细讨论这个问题,并提供一个时间复杂度为 O(n) 且只使用常数级别额外空间的解决方案。 问题描述 leet…...
常用的辅助网站(持续更新)
标题 一、uni-app方向二、H5方向 一、uni-app方向 1、uni-app官网 地址:https://uniapp.dcloud.net.cn/ 2、香蕉云编 地址:https://www.yunedit.com/ 描述:一般用来配置ios证书或安卓证书、上传ios包至商店 3、uView 地址:http…...

LeetCode 75 - 01 : 最小面积矩形
type pair struct{x, y int }func minAreaRect(points [][]int)int{mp : map[pair]struct{}{}// 将二维数组中的坐标映射到map中for i : range points{mp[pair{points[i][0], points[i][1]}] struct{}{}}// 将结果设置为一个最大值,防止影响求最小值的逻辑res : ma…...

每日一题:请解释什么是闭包(Closure)?并举一个实际的例子来说明。(前端初级)
今天继续在前端初级笔试题中被AI虐: 碱面的答案,问题:初级,回答:初级https://bs.rongapi.cn/1702510598371151872/14我的回答如下: 闭包是指由大括号包裹的一个区域,这个区域代表了一个变量生效…...

广告主必看!NetMarvel五大优势驱动出海App投放增长
App出海走到今天,流量红利早就不存在,摆在广告主面前最棘手的两个问题,一是不起量,二是买量成本太高,得不偿失。 如何在确保出海应用用户规模有所增长的同时,也保证整体ROI处在较高水平?NetMar…...

数据结构与算法之复杂度
时间复杂度 1.抓大头 2.常数用o(1),低阶函数也用o(1)代替(直接去掉) 3.取最坏情况 对数相关写法的规定...

ATECLOUD电源测试软件平台如何测试电源纹波?
电源纹波是影响电源稳定性的重要因素,过大的纹波会导致电源模块的工作效率降低,可能使电源模块直接损坏。使用ATECLOUD碘盐测试软件平台对纹波进行测试,检测其工作情况,以确保其稳定性和性能。 电源纹波的产生 电源的纹波通俗的来…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...