K8S MetalLB LoadBalancer

1. 简介

kubernetes集群没有L4负载均衡,对外暴漏服务时,只能使用nodePort的方式,比较麻烦,必须要记住不同的端口号。

LoadBalancer:使用云提供商的负载均衡器向外部暴露服务,外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。

img

MetalLB 是裸机 Kubernetes 集群的负载均衡器实现,使用标准路由协议。

它提供了两个功能:

  • 地址分配(address allocation):当创建 LoadBalancer Service 时,MetalLB 会为其分配 IP 地址。这个 IP 地址是从预先配置的 IP 地址库获取的。同样,当 Service 删除后,已分配的 IP 地址会重新回到地址库。
  • 对外公告(external announcement):分配了 IP 地址之后,需要让集群外的网络知道这个地址的存在。使用了标准路由协议实现:
    • Layer2 模式:ARP(ipv4)、NDP(ipv6)
    • BGP 模式

不管是Layer2模式还是BGP模式,两者都不使用Linux的网络栈,即无法使用诸如ip命令准确的查看VIP所在的节点和相应的路由,相对应的是在每个节点上面都能看到一个kube-ipvs0网卡接口上面的IP。同时,两种模式都只是负责把VIP的请求引到对应的节点上面,之后的请求怎么到达pod,按什么规则轮询等都是由kube-proxy实现的。

对应的的两种工作负载:

  • ControllerDeployment,用于监听 Service 的变更,分配/回收 IP 地址。
  • SpeakerDaemonSet,对外广播 Service 的 IP 地址。把服务类型为LoadBalancer的服务的EXTERNAL-IP公布到网络中去,确保客户端能够正常访问到这个IP。

2. 部署

2.1 测试服务

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-app
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.21.4ports:- name: httpcontainerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginx-svc
spec:ports:- name: httpport: 8080protocol: TCPtargetPort: 80selector:app: nginxtype: LoadBalancer

2.2 MetalLB

# 1. ipvs 开启严格 arp模式
$ kubectl edit configmap -n kube-system kube-proxy
...
ipvs:strictARP: true# 2. 安装组件
$ mkdir -p $HOME/metallb && cd $_
$ wget https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml$ kubectl apply -f metallb-native.yaml$ kubectl get pod -n metallb-system
NAME                          READY   STATUS    RESTARTS      AGE
controller-6f5c46d94b-b7psv   1/1     Running   1 (29s ago)   80s
speaker-6v8hn                 1/1     Running   0             80s
speaker-nzkb6                 1/1     Running   0             79s
speaker-wjqxx                 1/1     Running   0             79s

组件说明:

  • metallb-system/controller:负责IP地址的分配,以及service和endpoint的监听
  • metallb-system/speaker:负责保证service地址可达,在Layer 2模式下,speaker会负责ARP请求应答

3. Layer2 模式

  • 每个service会有集群中的一个node来负责。当服务客户端发起ARP解析的时候,对应的node会响应该ARP请求,之后,该service的流量都会指向该node(看上去该node上有多个地址)。

  • 并不是真正的负载均衡,因为流量都会先经过一个node后,再通过kube-proxy转给多个endpoints。如果该node故障,MetalLB会迁移 IP到另一个node,并重新发送ARP告知客户端迁移。

  • 更为通用,不需要用户有额外的设备;但由于Layer 2模式使用ARP/NDP,地址池分配需要跟客户端在同一子网,地址分配略为繁琐。

img

3.1 工作原理

  • Speaker 工作负载类型是 DeamonSet ,在每台节点上都调度一个 Pod。首先,几个 Pod 会先进行选举,选举出 LeaderLeader 获取所有 LoadBalancer 类型的 Service,将已分配的 IP 地址绑定到当前主机到网卡上。即所有 LoadBalancer 类型的 Service 的 IP 同一时间都是绑定在同一台节点的网卡上。

  • 当外部主机有请求要发往集群内的某个 Service,需要先确定目标主机网卡的 mac 地址。这是通过发送 ARP 请求,Leader 节点的会以其 mac 地址作为响应。外部主机会在本地 ARP 表中缓存下来,下次会直接从 ARP 表中获取。

  • 请求到达节点后,节点再通过 kube-proxy 将请求负载均衡目标 Pod。所以说,假如Service 是多 Pod 这里有可能会再跳去另一台主机。

img

3.2 试验

配置 layer2 IP池 (layer2.yaml):

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: layer2-poolnamespace: metallb-system
spec:addresses:- 192.168.3.170-192.168.3.179
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: layer2-lbnamespace: metallb-system
spec:ipAddressPools:- layer2-pool

查看结果:

# 获取
$ kubectl get svc nginx-svc
NAME        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
nginx-svc   LoadBalancer   10.96.155.95   192.168.3.170   8080:31717/TCP   9m34s$ kubectl get ep nginx-svc
NAME        ENDPOINTS                                           AGE
nginx-svc   10.244.172.62:80,10.244.172.63:80,10.244.46.53:80   9m38s$ ipvsadm -Ln | grep 192.168.3.170 -A 3
TCP  192.168.3.170:8080 rr-> 10.244.46.53:80              Masq    1      0          0-> 10.244.172.62:80             Masq    1      0          0-> 10.244.172.63:80             Masq    1      0          0# 每个节点自动增加配置
$ ip addr show kube-ipvs0 | grep 192.168.3.170 -A 1inet 192.168.3.170/32 scope global kube-ipvs0valid_lft forever preferred_lft forever

查询实际的工作代理节点:

$ curl -I 192.168.3.170:8080
HTTP/1.1 200 OK
Server: nginx/1.21.4
Date: Thu, 10 Aug 2023 06:44:21 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 02 Nov 2021 14:49:22 GMT
Connection: keep-alive
ETag: "61814ff2-267"
Accept-Ranges: bytes$ arp 192.168.3.170
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.3.170            ether   52:54:00:63:8f:d3   C                     br0

根据mac地址,查询实际的节点:

$ ip addr | grep 52:54:00:63:8f:d3 -A 1 -B 1
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 52:54:00:63:8f:d3 brd ff:ff:ff:ff:ff:ffinet 192.168.3.105/24 brd 192.168.3.255 scope global ens3

3.3 清理

kubectl delete -f layer2.yamlkubectl get pod -n metallb-system | grep Running | awk '{print $1}' | xargs kubectl delete pod -n metallb-system

4. BGP 模式

  • 所有node都会跟上级路由器建立BGP连接,并会告知路由器应该如何转发service流量
  • 是真正的 Load Balancer

在这里插入图片描述

4.1 工作原理

BGP模式不限于一个二层网络里,各个节点都会与交换机建立BGP Peer,宣告Service External IP的下一跳为自身,这样通过ECMP实现了一层负载。客户端请求通过交换机负载到后端某个节点后,再由Kube-proxy进行转发

img

4.2 路由配置

通过 openwrt 旁路由实现 BGP。使用命令 vtysh 进行 AS 配置

  • 本地:AS 65000

  • 远端:AS 65001

$ vtysh
OpenWrt# conf t
OpenWrt(config)# router bgp 65000
OpenWrt(config-router)# neighbor 192.168.3.103 remote-as 65001
OpenWrt(config-router)# neighbor 192.168.3.103 description master-01
OpenWrt(config-router)# neighbor 192.168.3.104 remote-as 65001
OpenWrt(config-router)# neighbor 192.168.3.104 description worker-01
OpenWrt(config-router)# neighbor 192.168.3.105 remote-as 65001
OpenWrt(config-router)# neighbor 192.168.3.105 description worker-02
OpenWrt(config-router)# exit
OpenWrt(config)# exitOpenWrt# show ip bgp summary
BGP router identifier 192.168.3.180, local AS number 65000
RIB entries 0, using 0 bytes of memory
Peers 3, using 27 KiB of memoryNeighbor        V         AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
192.168.3.103   4 65001       0       6        0    0    0 never    Active
192.168.3.104   4 65001       0       4        0    0    0 never    Active
192.168.3.105   4 65001       0       3        0    0    0 never    ActiveTotal number of neighbors 3OpenWrt# exit

查看 bgpd 端口监听 179 是否已打开:

$  netstat -lantp | grep -E 'zebra|bgpd'
tcp        0      0 0.0.0.0:179             0.0.0.0:*               LISTEN      5355/bgpd
tcp        0      0 0.0.0.0:2601            0.0.0.0:*               LISTEN      5350/zebra
tcp        0      0 0.0.0.0:2605            0.0.0.0:*               LISTEN      5355/bgpd
tcp        0      0 :::179                  :::*                    LISTEN      5355/bgpd
tcp        0      0 :::2601                 :::*                    LISTEN      5350/zebra
tcp        0      0 :::2605                 :::*                    LISTEN      5355/bgpd

4.3 试验

配置BPG IP池 (bgp.yaml):

apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:name: samplenamespace: metallb-system
spec:myASN: 65001peerASN: 65000peerAddress: 192.168.3.180
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: first-poolnamespace: metallb-system
spec:addresses:- 192.168.0.10-192.168.0.99
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:name: examplenamespace: metallb-system
spec:ipAddressPools:- first-pool

查看结果:

$ kubectl get svc nginx-svc
NAME        TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE
nginx-svc   LoadBalancer   10.96.167.171   192.168.0.10   8080:31323/TCP   25h$ kubectl get ep nginx-svc
NAME        ENDPOINTS                                           AGE
nginx-svc   10.244.172.59:80,10.244.172.60:80,10.244.46.52:80   25h# 每个节点均添加
$ ip addr show kube-ipvs0 | grep 192.168.0.10 -A 1inet 192.168.0.10/32 scope global kube-ipvs0valid_lft forever preferred_lft forever$ curl -I 192.168.0.10:8080
HTTP/1.1 200 OK
Server: nginx/1.21.4
Date: Thu, 10 Aug 2023 03:39:37 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 02 Nov 2021 14:49:22 GMT
Connection: keep-alive
ETag: "61814ff2-267"
Accept-Ranges: bytes$ ipvsadm -Ln | grep 192.168.0 -A 3
TCP  192.168.0.10:8080 rr-> 10.244.46.52:80              Masq    1      0          0-> 10.244.172.59:80             Masq    1      0          0-> 10.244.172.60:80             Masq    1      0          0

客户端(windows, 192.168.3.3)添加路由:

route add 192.168.0.0 MASK 255.255.0.0 192.168.3.180

访问:https://192.168.0.10:8080 ok

4.4 清理

kubectl delete -f bgp.yamlkubectl get pod -n metallb-system | grep Running | awk '{print $1}' | xargs kubectl delete pod -n metallb-system

5. IP地址共享

默认情况下,MetalLB只会将一个IP地址分配到一个LoadBalancer Service上,用户可以通过spec.loadBalancerIP来指定自己想用的IP,如果用户指定了已被分配了的IP会,则会报错。但MetalLB也提供了方式去支持多个Service共享相同的IP,主要为了解决:K8S不支持对LoadBalancer Service中的Port指定多协议;有限的IP地址资源。

具体的方式是:创建两个Service,并加上metallb.universe.tf/allow-shared-ip为Key的annotation,表明Service能容忍使用共享的LoadBalancerIP;然后通过spec.loadBalancerIP给两个Service指定共享的IP。

IP地址共享也有限制:

1)两个Service的metallb.universe.tf/allow-shared-ip值是一样的。

2)两个Service的“端口”(带协议)不同,比如tcp/53udp/53是属于不同的“端口”。

3)两个Service对应的后端Pod要一致,如果不一致,那么他们的externalTrafficPolicy需要都是Cluster,不然会无法进行正确的BGP。

6. 总结

6.1 nodeport

在创建LoadBalancer服务时,会默认创建一个nodeport服务,可通过配置allocateLoadBalancerNodePorts来关闭。

不同的loadbalancer实现原理不同,有的需要依赖nodeport来进行流量转发,有些则直接转发请求到pod中。

对于MetalLB而言,是通过kube-proxy将请求的流量直接转发到pod,因此可以关闭nodeport。

apiVersion: v1
kind: Service
metadata:name: nginx-svc
spec:allocateLoadBalancerNodePorts: falseexternalTrafficPolicy: ClusterinternalTrafficPolicy: Clusterports:- name: httpport: 8080protocol: TCPtargetPort: 80selector:app: nginxtype: LoadBalancerloadBalancerIP: 192.168.0.20  

验证:

$ kubectl delete svc nginx-svc
$ kubectl apply -f nginx-svc-disable-nodeport.yaml$ kubectl get svc nginx-svc
NAME        TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)    AGE
nginx-svc   LoadBalancer   10.96.54.226   192.168.0.20   8080/TCP   3s

6.2 Layer2

优点:

  • 通用性强,不需要BGP路由器支持,几乎可以适用于任何网络环境,云厂商例外

缺点:

  • 所有的流量都会在同一个节点上,该节点的容易成为流量的瓶颈;
  • 当VIP所在节点宕机之后,需要较长时间进行故障转移(一般在10s),主要是因为MetalLB使用了memberlist来进行选主,当VIP所在节点宕机之后重新选主的时间要比传统的keepalived使用的vrrp协议要更长;
  • 难以定位VIP所在节点,没有提供一个简单直观的方式查看到底哪一个节点是VIP所属节点,只能通过抓包或者查看pod日志来确定,当集群规模变大的时会非常麻烦

6.3 BGP

优点:

  • 无单点故障,在开启ECMP的前提下,k8s集群内所有的节点都有请求流量,都会参与负载均衡并转发请求

缺点:

  • 条件苛刻,需要有BGP路由器支持,配置起来也更复杂;
  • ECMP的故障转移(failover)并不是特别地优雅,这个问题的严重程度取决于使用的ECMP算法;当集群的节点出现变动导致BGP连接出现变动,所有的连接都会进行重新哈希(使用三元组或五元组哈希),这对一些服务来说可能会有影响;

7. 附录

7.1 BGP

BGP,Border Gateway Protocol,边界网关协议

BGP是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或“前缀”表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。

BGP的邻居关系(或称通信对端/对等实体,peer)是通过人工配置实现的,对等实体之间通过TCP端口179建立会话交换数据。BGP路由器会周期地发送19字节的保持存活(keep-alive)消息来维护连接(默认周期为60秒)。在各种路由协议中,只有BGP使用TCP作为传输层协议。

同一个AS自治系统中的两个或多个对等实体之间运行的BGP被称为iBGP(Internal/Interior BGP)。归属不同的AS的对等实体之间运行的BGP称为eBGP(External/Exterior BGP)。在AS边界上与其他AS交换信息的路由器被称作边界路由器(border/edge router),边界路由器之间互为eBGP对端。在Cisco IOS中,iBGP通告的路由距离为200,优先级比eBGP和任何内部网关协议(IGP)通告的路由都低。其他的路由器实现中,优先级顺序也是eBGP高于IGP,而IGP又高于iBGP。

iBGP和eBGP的区别主要在于转发路由信息的行为。例如,从eBGP peer获得的路由信息会分发给所有iBGP peer和eBGP peer,但从iBGP peer获得的路由信息仅会分发给所有eBGP peer。所有的iBGP peer之间需要全互联。

在这里插入图片描述

三个核心名词:

  • 自治系统(AS)
  • 内部网关协议(IGP)
  • 外部网关协议(EGP)

7.1.1 自治系统 AS

自制系统(Autonomous system,缩写 AS),是指在互联网中,一个或多个实体管辖下的所有IP 网络和路由器的组合,它们对互联网执行共同的路由策略。自治系统编号都是16位长的整数,这最多能被分配给65536个自治系统。自治系统编号被分成两个范围。第一个范围是公开的ASN,从1到64511,它们可在互联网上使用;第二个范围是被称为私有编号的从64512到65535的那些,它们仅能在一个组织自己的网络内使用。

简单理解,电信、移动、联通都有自己的 AS 编号,且不只一个。除了互联网公开的 ASN 以外,私有的编号可以在内部使用。比如我可以我的家庭网络中使用私有编号创建几个 AS。

7.1.2 内部路由协议 IGP

内部路由协议(Interior Gateway Protocol,IGP)是指在一个自治系统(AS)内部所使用的一种路由协议。

7.1.3 外部网关协议 EGP

外部网关协议(Exterior Gateway Protocol,EGP)是一个已经过时互联网路由协议。已由 BPG 取代。

7.1.4 BGP

BPG 是为了替换 EGP 而创建的,而除了应用于 AS 外部,也可以应用在 AS 内部。因此又分为 EBGP 和 IBGP。

7.2 OpenWrt

7.2.1 安装

wget https://mirrors.aliyun.com/openwrt/releases/19.07.4/targets/x86/64/openwrt-19.07.4-x86-64-combined-ext4.img.gzgunzip openwrt-19.07.4-x86-64-combined-ext4.img.gz
cp openwrt-19.07.4-x86-64-combined-ext4.img  openwrt.img# 双网口(wan+lan)
virt-install --name=openwrt --vcpus=1 --ram=512 --os-type=generic --disk path=/root/eli/openwrt.img,bus=ide --autostart --network bridge=br0,model=e1000 --network bridge=br0,model=e1000 --import --noautoconsole --graphics vnc,listen=0.0.0.0,password=123456# 单网口(lan)
virt-install --name=openwrt --vcpus=1 --ram=512 --os-type=generic --disk path=/root/eli/openwrt.img,bus=ide --autostart --network bridge=br0,model=e1000 --import --noautoconsole --graphics vnc

修改网络配置:

# 改成与宿主机在同一网络下
$ vi /etc/config/network
...
config interface 'lan'option type 'bridge'option ifname 'eth0'option proto 'static'option ipaddr '192.168.3.180'option netmask '255.255.255.0'option ip6assign '60'option gateway '192.168.3.1'option dns '114.114.114.114'$ service network restart

登录配置页面:http://192.168.3.180

7.2.2 Quagga

为了让 OpenWrt 支持 BGP,需要安装路由软件套件 Quagga。它提供了 OSPFv2、OSPFv3、RIP v1 v2、RIPng 和 BGP-4 的实现。

Quagga 架构由核心守护进程和 zebra 组成,后者作为底层 Unix 内核的抽象层,并通过 Unix 或者 TCP 向 Quagga 客户端提供 Zserv API。正是这些 Zserv 客户端实现了路由协议,并将路由的更新发送给 zebra 守护进程。当前 Zserv 的实现:

img

Quagga 的守护进程可以通过网络可访问的 CLI(简称 vty)进行配置。 CLI 遵循与其他路由软件类似的风格。还额外提供了一个工具 vtysh,充当了所有守护进程的聚合前端,允许在一个地方管理所有 Quagga 守护进程的所有功能。

$ opkg update && opkg install quagga quagga-zebra quagga-bgpd quagga-vtysh$ netstat -lantp | grep -E 'zebra|bgpd'
tcp        0      0 0.0.0.0:2601            0.0.0.0:*               LISTEN      5350/zebra
tcp        0      0 0.0.0.0:2605            0.0.0.0:*               LISTEN      5355/bgpd
tcp        0      0 :::2601                 :::*                    LISTEN      5350/zebra
tcp        0      0 :::2605                 :::*                    LISTEN      5355/bgpd

参考资料:

https://metallb.universe.tf/configuration/

https://tinychen.com/20220519-k8s-06-loadbalancer-metallb/

https://atbug.com/load-balancer-service-with-metallb-bgp-mode/

https://ieevee.com/tech/2019/06/30/metallb.html

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

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

相关文章

日常BUG——使用Long类型作id,后端返回给前段后精度丢失问题

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 数据库long类型Id: 前端返回的Id实体类: Data ApiModel("xxx") public class …

【广州华锐视点】VR燃气轮机故障判断模拟演练系统

VR燃气轮机故障判断模拟演练系统由广州华锐视点开发&#xff0c;是一款基于虚拟现实技术的教育工具&#xff0c;旨在为学生提供一个安全、高效、互动的学习环境&#xff0c;帮助他们更好地掌握燃气轮机的故障诊断技能。 这款VR实训软件能够模拟真实的燃气轮机故障诊断场景&…

案例13 Spring MVC参数传递案例

基于Spring MVC实现HttpServletRequest、基本数据类型、Java Bean、数组、List、Map、JSON方式的参数传递。 1. 创建项目 选择Maven快速构建web项目&#xff0c;项目名称为case13-springmvc02。 2. 配置Maven依赖 <?xml version"1.0" encoding"UTF-8&quo…

前沿分享-鱼形机器人

可能并不太前沿了&#xff0c;是21年底的新闻了&#xff0c;但是看见了就顺便发一下吧。 大概就是&#xff0c;通过在pH响应型水凝胶中编码不同的膨胀速率而构建了一种环境适应型变形微机器人,让微型机器人直接向癌细胞输送药物从而减轻药物带来副作用。 技术原理是&#xff0c…

数据结构:力扣刷题

题一&#xff1a;删除有序数组中的重复项 给你一个 升序排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的…

C++:模拟实现vector以及vector的迭代器失效和拷贝问题

文章目录 实现的功能模拟实现迭代器失效隐含浅拷贝问题 实现的功能 模拟实现 由于前面实现了string&#xff0c;因此这里实现过程不为重点&#xff0c;重点为关于迭代器失效和拷贝问题 template <class T> class vector { public:typedef T* iterator;typedef const T*…

非计算机科班如何丝滑转码?

近年来&#xff0c;很多人想要从其他行业跳槽转入计算机领域。非计算机科班如何丝滑转码&#xff1f; 如何规划才能实现转码&#xff1f; 对于非计算机科班的人来说&#xff0c;想要顺利转码成为计算机相关岗位的从业者&#xff0c;需要经过以下几个步骤&#xff1a; 规划转码…

(docker)mysql镜像拉取-创建容器-容器的使用【个人笔记】

【容器的第一次创建】 容器的第一次创建&#xff0c;需要先下载镜像&#xff0c;从 镜像拉取 0、可以搜索镜像的版本 docker search mysql1、先拉取MySQL的镜像&#xff0c;默认拉取最新版&#xff0c;使用下面的命令拉取mysql镜像 docker pull mysql也可以指定mysql的版本…

MySQL 事务原理:事务概述、隔离级别、MVCC

文章目录 一、事务1.1 事务概述1.2 事务控制语句1.3 ACID特性 二、隔离级别2.1 隔离级别的分类2.1.1 读未提交&#xff08;RU&#xff09;2.1.2 读已提交&#xff08;RC&#xff09;2.1.3 可重复读&#xff08;RR&#xff09;2.1.4 串行化 2.2 命令2.3 并发读异常2.3.1 脏读2.3…

Linux 发行版 Debian 12.1 发布

导读在今年 6 月初&#xff0c;Debian 12“bookworm”发布&#xff0c;而日前 Debian 迎来了 12.1 版本&#xff0c;主要修复系统用户创建等多个安全问题。 Debian 是最古老的 GNU / Linux 发行版之一&#xff0c;也是许多其他基于 Linux 的操作系统的基础&#xff0c;包括 Ub…

Redis单机,主从,哨兵,集群四大模式

Redis 单机模式 Redis 单机模式是指 Redis 数据库在单个服务器上以独立的、单一的进程运行的模式。在这种模式下&#xff0c;Redis 不涉及数据分片或集群配置&#xff0c;所有的数据和操作都在一个实例中进行。以下是关于 Redis 单机模式的详细介绍&#xff1a; 单一实例&#…

数据分析两件套ClickHouse+Metabase(二)

Metabase篇 Metabase安装部署 任何问题请查看 -> 官方文档 jar包从GitHub下载 -> 地址 同样有个问题, 默认数据源里没有ClickHouse, 不过ClickHouse官方提供了插件包 -> 插件包 在安装metabase目录下新建一个plugins文件夹, 把下载的clickhouse.metabase-driver.ja…

spark 图计算 助力解决 dataframe中的链式依赖

链式依赖说明 name newName a b c d b c 我们需要的结果 即我们可以支持获取到链式转换的 起点 重点 以及链式的中间转换过程顺序数组. 特别说明: 出版只支持 单向 无分叉的图,其他复杂场景暂时未测试. 场景举例: 比如某件商品价格变化,我们需要知…

手机里视频太大怎么压缩?压缩教程分享

现在视频文件的体积越来越大了&#xff0c;动不动就是几个GB起步&#xff0c;如果后期再剪辑处理一下&#xff0c;更是会占据更多的设备空间了&#xff0c;还会导致我们传输受到限制&#xff0c;这时候就需要我们对视频进行压缩处理&#xff0c;下面给大家分享几个简单的方法&a…

0基础学习VR全景平台篇 第83篇:智慧眼-怎么理解分类?

一、功能说明 分类可以理解为&#xff0c;为了方便城市运营工作的管理所实行的行政区划&#xff0c;如XXX乡镇、XXX街道等等。 二、后台编辑界面 1、点击【新增】&#xff0c;填写分类的名称&#xff0c;若有上一级分类&#xff0c;那么还需选择父级分类&#xff0c;建议从最…

Vue组件库

Vue组件库 ViteVue3TypescriptTSX 1、项目搭建 1.1、创建项目&#xff08;yarn&#xff09; D:\WebstromProject>yarn create vite yarn create v1.22.19 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh pa…

Anaconda Prompt使用pip安装PyQt5-tools后无法打开Spyder或闪退

艹&#xff01;MLGBZD! 真TMD折腾人&#xff01; 出现原因&#xff1a; 首次安装完Anaconda3-2023.07-1-Windows-x86_64.exe后首次打开Spyder&#xff0c;此时是没有问题的&#xff0c;然后打开Anaconda Prompt&#xff0c;查看有哪些包&#xff0c;pip list 这时候开始首次安…

RCNA——单臂路由

一&#xff0c;实验背景 之前的VLAN实现的很多都是相同部门互相访问&#xff0c;不同部门无法访问。不过这次整来了一个路由器&#xff0c;领导说大部分的部门虽说有保密信息需要互相隔离&#xff0c;但是这些部门和其它部门也应该互相连通以方便工作交流。因此要配置新的环境&…

springboot汽车租赁后台java出租客户管理jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 springboot汽车租赁后台 系统有1权限&#xff1a;管理…

MySQL缓存策略

文章目录 一、MySQL缓存方案的作用二、提高MySQL访问性能的方式2.1 读写分离2.1.1 是什么&#xff1f;2.1.2 解决了什么&#xff1f;2.1.3 原理是什么&#xff1f; 2.2 连接池2.1.1 是什么&#xff1f;2.1.2 解决了什么&#xff1f;2.1.3 原理是什么&#xff1f; 2.3 异步连接2…