Kubernetes高可用动态存储NFS集群

2023-11-03


部署NFS双机热备高可用环境,用作K8S容器集群的StorageClass,更好地实现K8S数据持久化

思路:

NFS + Keepalived 实现高可用,防止单点故障。

Rsync+Inotify 实现主备间共享数据进行同步。

环境准备

两台NFS服务器
192.168.20.130
192.168.20.131
一个VIP:192.168.20.251
一个k8s集群
通过在k8s部署nfs-client-provisioner连接NFS服务器的VIP使用NAS存储

技术要求

  • 两个NFS节点机器的配置要一致
  • keepalived监控nfs进程,master的nfs主进程宕掉无法启动时由slave的nfs接管继续工作。
  • k8s数据备份到slave,同时master和slave数据用rsync+inotify实时同步,保证数据完整性。
  • 生产环境下,最好给NFS共享目录单独挂载一块硬盘或单独的磁盘分区。

安装NFS服务

1)安装nfs
# yum -y install nfs-utils
2)创建nfs共享目录
# mkdir /home/k8s_storage
3)编辑export文件
# vim /etc/exports
/home/k8s_storage 192.168.20.0/24(rw,sync,no_root_squash) 
4)配置生效
# exportfs -r
5)查看生效
# exportfs
6)启动rpcbind、nfs服务
# systemctl restart rpcbind && systemctl enable rpcbind
# systemctl restart nfs && systemctl enable nfs 
7)查看 RPC 服务的注册状况
# rpcinfo -p localhost
8)showmount测试
Master节点测试
# showmount -e 192.168.20.130
Export list for 192.168.20.130:
/home/k8s_storage 192.168.20.0/24 
Slave节点测试
# showmount -e 192.168.20.131
Export list for 192.168.20.131:
/home/k8s_storage 192.168.20.0/24

安装keepalived

1)安装keepalived
# yum -y install keepalived 
2)Master节点的keepalived.conf配置
这里特别需要注意:
一定要设置keepalived为非抢占模式,如果设置成抢占模式会在不断的切换主备时容易造成NFS数据丢失。
# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf_bak
# >/etc/keepalived/keepalived.conf
# vi /etc/keepalived/keepalived.conf
global_defs {
    router_id master   #id可以随便设
}
vrrp_script chk_nfs {
    script "/etc/keepalived/nfs_check.sh"    #监控脚本
    interval 2
    weight -20   #keepalived部署了两台,所以设为20,如果三台就设为30
}
vrrp_instance VI_1 {
    state BACKUP    #两台主机都设为backup非抢占模式
    interface ens192  #网卡名写自己的,不要照抄
    virtual_router_id 51
    priority 100    #服务启动优先级,值越大,优先级越高,BACKUP 不能大于MASTER
    advert_int 1
    nopreempt       #设置为非抢占模式必须要该参数
    authentication {
        auth_type PASS
        auth_pass Kibo
    }  
    track_script {
        chk_nfs
    }
    virtual_ipaddress {
        192.168.20.251     #虚拟ip
    }
} 
3)Slave节点的keepalived.conf配置
只需将priority参数项修改为80,其他配置的和master节点一样,脚本也一样。
# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf_bak
# >/etc/keepalived/keepalived.conf
# vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    router_id master  
}
vrrp_script chk_nfs {
    script "/etc/keepalived/nfs_check.sh"   
    interval 2
    weight -20  
}
vrrp_instance VI_1 {
    state BACKUP   
    interface eth0 
    virtual_router_id 51
    priority 80  
    advert_int 1
    nopreempt      
    authentication {
        auth_type PASS
        auth_pass 1111
    }  
    track_script {
        chk_nfs
    }
    virtual_ipaddress {
        192.168.20.251     
    }
}
4)编辑nfs_check.sh监控脚本
# vi /etc/keepalived/nfs_check.sh
#!/bin/bash
A=`ps -C nfsd --no-header | wc -l`
if [ $A -eq 0 ];then
        systemctl restart nfs-server.service
        sleep 2
        if [ `ps -C nfsd --no-header| wc -l` -eq 0 ];then
            pkill keepalived
        fi
fi 
设置脚本执行权限
# chmod 755 /etc/keepalived/nfs_check.sh
5)启动keepalived服务
# systemctl restart keepalived.service && systemctl enable keepalived.service
查看服务进程是否启动
# ps -ef|grep keepalived
6)检查vip是否存在
在两台节点机器上执行"ip addr"命令查看vip,其中会在一台机器上产生vip地址。
# ip addr|grep 192.168.20.251
    inet 192.168.20.251/32 scope global ens192     
测试vip地址要能被ping通 
# ping 192.168.20.52
PING 192.168.20.52 (192.168.20.52) 56(84) bytes of data.
64 bytes from 192.168.20.52: icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from 192.168.20.52: icmp_seq=2 ttl=64 time=0.027 ms
64 bytes from 192.168.20.52: icmp_seq=3 ttl=64 time=0.041 ms
7)keepalived故障测试
停掉vip所在的Master节点机器上的keepalived服务后,发现vip会自动飘移到另一台Backup机器上才算测试成功。
当该Master节点的keepalived服务重新启动后,vip不会重新飘移回来。因为keepalived采用了非抢占模式。
如果keepalived设置为抢占模式,vip会在Master节点的keepalived重启恢复后自动飘回去,
但是这样一直来回切换可能会造成NFS数据不完整,因为这里必须设置成非抢占模式。
由于配置了nfs的nfs_check.sh监控脚本,所以当其中一台节点机器上的NFS服务宕停后会自动重启NFS。
如果NFS服务重启失败,则会自动关闭该节点机器上的keepalived服务,如果该节点有vip则会自动飘移到另外一台节点上。

安装Rsync+Inofity

1)安装rsync和inotify
# yum -y install rsync inotify-tools
2)Master节点机器配置rsyncd.conf
# cp /etc/rsyncd.conf /etc/rsyncd.conf_bak
# >/etc/rsyncd.conf
# vi /etc/rsyncd.conf
uid = root
gid = root
use chroot = 0
port = 873
hosts allow = 192.168.20.0/24  #允许ip访问设置,可以指定ip或ip段
max connections = 0
timeout = 300
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
log format = %t %a %m %f %b
transfer logging = yes
syslog facility = local3
[master_web]
path = /home/k8s_storage
comment = master_web
ignore errors
read only = no   #是否允许客户端上传文件
list = no
auth users = rsync  #指定由空格或逗号分隔的用户名列表,只有这些用户才允许连接该模块
secrets file = /etc/rsyncd.passwd  #保存密码和用户名文件,需要自己生成
编辑密码和用户文件(格式为"用户名:密码"# vim /etc/rsyncd.passwd
rsync:Kibo@2020
编辑同步密码(注意这个文件和上面的密码和用户文件路径不一样)
该文件内容只需要填写从服务器的密码,例如这里从服务器配的用户名密码都是rsync:123456,则主服务器则写123456一个就可以了
# vim /opt/rsyncd.passwd
Kibo@2020
设置文件执行权限
# chmod 600 /etc/rsyncd.passwd &&  chmod 600 /opt/rsyncd.passwd
启动服务
# systemctl enable rsyncd && systemctl restart rsyncd
检查rsync服务进程是否启动
# ps -ef|grep rsync
3)Slave节点机器配置rsyncd.conf
就把master主机/etc/rsyncd.conf配置文件里的[master_web]改成[slave_web]
其他都一样,密码文件也设为一样
# cp /etc/rsyncd.conf /etc/rsyncd.conf_bak
# >/etc/rsyncd.conf
# vim /etc/rsyncd.conf
uid = root
gid = root
use chroot = 0
port = 873
hosts allow = 192.168.20.0/24
max connections = 0
timeout = 300
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
log format = %t %a %m %f %b
transfer logging = yes
syslog facility = local3
[slave_web]
path = /home/k8s_storage
comment = master_web
ignore errors
read only = no
list = no
auth users = rsync
secrets file = /etc/rsyncd.passwd
编辑密码和用户文件(格式为"用户名:密码"# vim /etc/rsyncd.passwd
rsync:123456
编辑同步密码
# vim /opt/rsyncd.passwd
123456 
设置文件执行权限
# chmod 600 /etc/rsyncd.passwd
# chmod 600 /opt/rsyncd.passwd 
启动服务
# systemctl enable rsyncd && systemctl restart rsyncd 
检查rsync服务进程是否启动
# ps -ef|grep rsync

手动验证下Master节点NFS数据同步到Slave节点

在Master节点的NFS共享目录下创建测试数据
# ls /home/k8s_storage/
# mkdir /home/k8s_storage/test
# touch /home/k8s_storage/{a,b}
# ls /home/k8s_storage/
a  b  test
手动同步Master节点的NFS共享目录数据到Slave节点的NFS共享目录下
# rsync -avzp --delete /home/k8s_storage/ rsync@192.168.20.131::slave_web --password-file=/opt/rsyncd.passwd
到Slave节点查看
# ls /home/k8s_storage/
a  b  test

上面rsync同步命令说明:

  • /home/k8s_storage/ 是同步的NFS共享目录
  • rsync@192.168.20.131::slave_web
  • rsync 是Slave节点服务器的/etc/rsyncd.passwd文件中配置的用户名
  • 192.168.20.131为Slave节点服务ip
  • slave_web 为Slave服务器的rsyncd.conf中配置的同步模块名
  • –password-file=/opt/rsyncd.passwd 是Master节点同步到Slave节点使用的密码文件,文件中配置的是Slave节点服务器的/etc/rsyncd.passwd文件中配置的密码

设置Rsync+Inotify自动同步

这里需要注意:不能设置Master和Slave节点同时执行rsync自动同步,即不能同时设置双向同步。因为Master节点将数据同步到Slave节点,如果Slave节点再将数据同步回到Master节点,这个就矛盾了。所以需要确保只有一方在执行自动同步到另一方的操作。方式就是判断当前节点服务器是否存在VIP,如存在VIP则自动同步数据到另一台节点上。如不存在VIP则不执行自动同步操作。

Master节点服务器操作

编写自动同步脚本/opt/rsync_inotify.sh

#!/bin/bash
host=192.168.20.131
src=/home/k8s_storage/
des=slave_web
password=/opt/rsyncd.passwd
user=rsync
inotifywait=/usr/bin/inotifywait
$inotifywait -mrq --timefmt '%Y%m%d %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src \
| while read files ;do
 rsync -avzP --delete --timeout=100 --password-file=${password} $src $user@$host::$des
 echo "${files} was rsynced" >>/tmp/rsync.log 2>&1
done

编写VIP监控脚本/opt/vip_monitor.sh

#!/bin/bash
VIP_NUM=`ip addr|grep 192.168.20.251|wc -l`
RSYNC_INOTIRY_NUM=`ps -ef|grep /usr/bin/inotifywait|grep -v grep|wc -l`
if [ ${VIP_NUM} -ne 0 ];then
   echo "VIP在当前NFS节点服务器上" >/dev/null 2>&1
   if [ ${RSYNC_INOTIRY_NUM} -ne 0 ];then
      echo "rsync_inotify.sh脚本已经在后台执行中" >/dev/null 2>&1
   else
      echo "需要在后台执行rsync_inotify.sh脚本" >/dev/null 2>&1
      nohup sh /opt/rsync_inotify.sh &
  fi
else
   echo "VIP不在当前NFS节点服务器上" >/dev/null 2>&1
   if [ ${RSYNC_INOTIRY_NUM} -ne 0 ];then
      echo "需要关闭后台执行的rsync_inotify.sh脚本" >/dev/null 2>&1
      ps -ef|grep rsync_inotify.sh|grep -v grep|awk '{print $2}'|xargs kill -9
      ps -ef|grep inotifywait|grep -v grep|awk '{print $2}'|xargs kill -9
   else
      echo "rsync_inotify.sh脚本当前未执行" >/dev/null 2>&1
   fi
fi

编写持续执行脚本/opt/rsync_monit.sh

#!/bin/bash
while [ "1" = "1" ]
do
  /bin/bash -x /opt/vip_monitor.sh >/dev/null 2>&1
done

后台运行脚本

# chmod 755 /opt/rsync_inotify.sh
# chmod 755 /opt/vip_monitor.sh
# chmod 755 /opt/rsync_monit.sh
# nohup sh /opt/rsync_inotify.sh &
# nohup sh /opt/rsync_monit.sh &

设置rsync_monit.sh脚本的开机启动

# chmod +x /etc/rc.d/rc.local
# echo "nohup sh /opt/rsync_monit.sh & " >> /etc/rc.d/rc.local

Slave节点服务器操作

脚本名为/opt/rsync_inotify.sh,内容如下:

#!/bin/bash
host=192.168.20.130
src=/home/k8s_storage/
des=master_web
password=/opt/rsyncd.passwd
user=rsync
inotifywait=/usr/bin/inotifywait
$inotifywait -mrq --timefmt '%Y%m%d %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src \
| while read files ;do
 rsync -avzP --delete --timeout=100 --password-file=${password} $src $user@$host::$des
 echo "${files} was rsynced" >>/tmp/rsync.log 2>&1
done

编写VIP监控脚本/opt/vip_monitor.sh

#!/bin/bash
VIP_NUM=`ip addr|grep 192.168.20.251|wc -l`
RSYNC_INOTIRY_NUM=`ps -ef|grep /usr/bin/inotifywait|grep -v grep|wc -l`
if [ ${VIP_NUM} -ne 0 ];then
   echo "VIP在当前NFS节点服务器上" >/dev/null 2>&1
   if [ ${RSYNC_INOTIRY_NUM} -ne 0 ];then
      echo "rsync_inotify.sh脚本已经在后台执行中" >/dev/null 2>&1
   else
      echo "需要在后台执行rsync_inotify.sh脚本" >/dev/null 2>&1
      nohup sh /opt/rsync_inotify.sh &
  fi
else
   echo "VIP不在当前NFS节点服务器上" >/dev/null 2>&1
   if [ ${RSYNC_INOTIRY_NUM} -ne 0 ];then
      echo "需要关闭后台执行的rsync_inotify.sh脚本" >/dev/null 2>&1
      ps -ef|grep rsync_inotify.sh|grep -v grep|awk '{print $2}'|xargs kill -9
      ps -ef|grep inotifywait|grep -v grep|awk '{print $2}'|xargs kill -9
   else
      echo "rsync_inotify.sh脚本当前未执行" >/dev/null 2>&1
   fi
fi

编写持续执行脚本/opt/rsync_monit.sh

#!/bin/bash
while [ "1" = "1" ]
do
  /bin/bash -x /opt/vip_monitor.sh >/dev/null 2>&1
done

后台运行脚本 (只执行rsync_monit.sh)

# chmod 755 /opt/rsync_inotify.sh
# chmod 755 /opt/vip_monitor.sh
# chmod 755 /opt/rsync_monit.sh
# nohup sh /opt/rsync_monit.sh &

设置rsync_monit.sh脚本的开机启动

# chmod +x /etc/rc.d/rc.local
# echo "nohup sh /opt/rsync_monit.sh & " >> /etc/rc.d/rc.local

验证自动同步

1)比如当前VIP在Master节点,在Master节点创建测试数据,观察是否自动同步到Slave节点
# ip addr|grep 192.168.20.251
    inet 192.168.20.251/32 scope global ens192
# rm -rf /home/k8s_storage/*
# echo "test" > /home/k8s_storage/haha
# ls /home/k8s_storage/
haha
到Slave节点上查看,已自动同步过来
# ls /home/k8s_storage/
haha
# cat /home/k8s_storage/haha
test
2)接着关闭Master节点的keeplived,将VIP飘移到Slave节点
# systemctl stop keepalived
# ip addr|grep 192.168.20.251 
到Slave节点上查看,发现VIP已经飘移过来了
# ip addr|grep 192.168.20.251
    inet 192.168.20.251/32 scope global eth0 
在Slave节点创建测试数据,观察是否自动同步到Master节点
# rm -rf /home/k8s_storage/*
# mkdir /home/k8s_storage/cha
# echo "heihei" > /home/k8s_storage/you 
到Master节点查看,发现数据已经同步过来了
# ls /home/k8s_storage/
cha heihei
3)模拟Master节点和Slave节点关机,观察开机后:
/opt/rsync_monit.sh脚本会实现开机自启动。
按照上面Master和Slave节点的自动同步验证OK。

K8s部署NFS-Provisioner

要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner,这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。前提k8s集群每台服务器安装nfs客户端【yum install -y nfs-utils】。

创建一个ServiceAccount

新建的一个名为 nfs-client-provisioner 的ServiceAccount,然后绑定了一个名为 nfs-client-provisioner-runner 的ClusterRole,而该ClusterRole声明了一些权限,其中就包括对persistentvolumes的增、删、改、查等权限,所以我们可以利用该ServiceAccount来自动创建 PV

cat nfs-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: k8s-nfs
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: k8s-nfs
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: k8s-nfs
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: k8s-nfs
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: k8s-nfs
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
部署 NFS Provisioner

cat nfs-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: k8s-nfs
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          #image: quay.io/external_storage/nfs-client-provisioner:latest
          image: docker.io/jmgao1983/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME   #nfs-provisioner的名称
              value: fuseim.pri/ifs
            - name: NFS_SERVER         #nfs服务端地址
              value: 192.168.20.251
            - name: NFS_PATH           #nfs服务端路径
              value: /home/k8s_storage
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.20.251     #nfs服务端地址
            path: /home/k8s_storage    #nfs服务端路径
设置默认存储

cat nfs-storage.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
  annotations:
    storageclass.kubernetes.io/is-default-class: "true" #---设置为默认的storageclass
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"
创建 NFS StorageClass

cat nfs-storage.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
  annotations:
    storageclass.kubernetes.io/is-default-class: "true" #---设置为默认的storageclass
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"

上面把StorageClass资源对象创建成功了,可以通过创建PVC使用了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kubernetes高可用动态存储NFS集群 的相关文章

随机推荐

  • API接口安全加密,防止接口被黑客攻击

    API接口安全加密的主要目的是为了防止黑客攻击 保护敏感数据不被泄露 以下是一些常用的API接口安全加密方式 HTTPS协议 使用HTTPS协议可以对数据进行传输加密 防止数据在传输过程中被窃听或篡改 API密钥认证 API密钥认证是指在每
  • 关键字constexpr(C++)

    关键字constexpr是在C 11中引入的 并且在C 14中得到了改进 像const一样 它可以应用于变量 当任何代码试图去修改该值时 都会引发编译器错误 与const不同 constexpr也可以应用于函数和类构造函数 constexp
  • 第13届CCF-CSP题解

    文章目录 Less 1 出现最多的数 Less 2 ISBN号码 Less 3 最大矩形 Less 4 有趣的数 Less 5 dfs Less 1 出现最多的数 直接根据题意模拟 include
  • 【yolov6系列一】深度解析网络架构

    在yolov5霸屏计算机视觉领域很久时 六月处美团开源了yolov6 并号称在精度和速度上均超越其他同量级的计算机视觉模型 刚刚瞅了一眼 star已经超过2 8k 脑子里莫名冒出一个词 国货之光 网上基于yolov6的解读有很多 文末会附上
  • Kmeans简单实现

    一 KMeans算法实现代码 class KMeans def init self data k clustres self data data self k clustres k clustres def train self max i
  • 基于 python 的数据库简单开发实验

    基于 python 的简单数据库应用程序开发总结 前言 在大三上数据库课时需要做基于数据库的 C S 和 B S 的简单应用 对之前一直接触命令行黑框框的笔者来说 需要临时学习不少新的技术 实际最后的开发非常简单 只是在前期选定技术和查找文
  • (1)密码学之RSA算法

    开始前先讲一下对称加密算法和公钥加密算法 我不喜欢叫非对称加密算法 这使我想起那个被问MD5算法属于对称还是非对称的恐惧 对称加密算法 1 甲方选择某一种加密规则 对信息进行加密 2 乙方使用同一种规则 对信息进行解密 公钥加密算法 1 乙
  • oracle 整理表 碎片,Oracle数据库表空间碎片的查询和整理方法

    一 查看表空间碎片的方法 1 查看fsfi值 select a tablespace name trunc sqrt max blocks sum blocks 100 sqrt sqrt count blocks 2 fsfi from
  • php+redis实现消息队列

    个人理解在项目中使用消息队列一般是有如下几个原因 把瞬间服务器的请求处理换成异步处理 缓解服务器的压力 实现数据顺序排列获取 redis实现消息队列步骤如下 1 redis函数rpush lpop 2 建议定时任务入队列 3 创建定时任务出
  • 目标检测mAP计算详解

    首先说明计算mAP有多个版本 每个数据集和比赛用的版本和方式也不同 下以VOC与COCO举例说明 精确度 precision 召回率 recall 分别为 常规的mAP计算为 这是一个N类检测任务 1 计算单张图片中class1的精度P V
  • Mac启动磁盘已满怎么办?Mac启动磁盘已满怎么清理?

    如果你的Mac电脑经常弹出窗口 您的启动盘几乎已经满了 这说明你的Mac硬盘空间严重不足了 清理各种不必要的垃圾可以释放一些空间 那么Mac启动磁盘已满怎么清理 下面为大家带来几点非常实用的Mac启动磁盘清理技巧 学会这些对你使用Mac电脑
  • 若依(ruoyi)代码生成树表结构的那些坑

    相信许多做后端开发的同学 一定用过若依这款框架 这款框架易上手 适合用来做后台管理系统 但是其中也存在一些坑 稍不注意就会中招 大佬可以忽略 今天 我们说的是若依的代码生成 树结构表 话不多说 直接看图说话 1 项目正常运行 成功登录之后
  • JS 对象和函数

    目录 一 对象 创建对象的四种方式 构造函数原型对象prototype和对象原型 proto 二 函数 创建函数的3种方式 一 对象 创建对象的四种方式 第一种方式 字面量 var o1 name o1 var o2 new Object
  • STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)

    STM32F103C8用内部Flash做一个优盘 USB MSC FATFS 轻松实现APP升级 数据存储 基本工程生成 直接使用STM32CubeMX生成基本的工程 省得我们去调底层 时钟配置为外部8MHz晶振 这个需要根据自己开发板的晶
  • Python爬虫教程:爬取800多所大学学校排名、星级等

    前言 国内大学最新排名 北大反超 浙大仅第四 中科大跌至第八 时隔五年 双一流 大学即将迎来首次大考 这也是继改变高校评断标准之后 第一次即将以官方对外发布 自然是引来了许多人的关注 最近 有许多不同机构发布的国内高校排名 但彼此之间的差异
  • 自我理解:TCP和UDP、HTTP、进程和线程

    一 TCP和UDP 1 什么是TCP和UDP TCP是面向连接的协议 发送数据前要建立连接 TCP提供的是可靠传输 UDP是无连接的协议 发送数据前不需要建立连接 是不可靠传输 2 TCP和UDP的区别 TCP是面向连接的协议 发送数据前要
  • 晟元协议指纹头,单片机开发踩坑指南

    一 硬件说明 1 接口 注意 其中Touch VCC 3 3V是需要常供电的 用于Touch Out触摸唤醒供电 VDD3 3V可以检测到Touch Out高电平信号再上电 如果不需要低功耗设计 可以忽略Touch Out和Touch VC
  • Arduino(六)——蜂鸣器唱歌

    进行这节课需要了解一个函数 1 tone pin frequency Duration 在我们的pin脚上 也就是我们的蜂鸣器上所连的脚 产生的一定频率frequency unsigned int hz 的方波信号 占空比一半 如果不再需要
  • 解决AppData/Local/Microsoft/WindowsApps/python: Permission denied

    先说一下原因 windows更新导致 path路径下多了下面这个路径的配置所以出问题 这2个文件导致 解决方案 让正确的pathon exe位于windows制定的python上方 如下图所示
  • Kubernetes高可用动态存储NFS集群

    文章目录 安装NFS服务 安装keepalived 安装Rsync Inofity 设置Rsync Inotify自动同步 Master节点服务器操作 Slave节点服务器操作 K8s部署NFS Provisioner 创建一个Servic