1. 程式人生 > >k8s(十二)、分散式儲存Ceph RBD使用

k8s(十二)、分散式儲存Ceph RBD使用

前言

Ceph儲存有三種儲存介面,分別是:
物件儲存 Ceph Object Gateway
塊裝置 RBD
檔案系統 CEPHFS

Kubernetes支援後兩種儲存介面,支援的接入模式如下圖:
在這裡插入圖片描述

在本篇將測試使用ceph rbd作持久化儲存後端

RBD建立測試

rbd的使用分為3個步驟:
1.服務端/客戶端建立塊裝置image
2.客戶端將image對映進linux系統核心,核心識別出該塊裝置後生成dev下的檔案標識
3.格式化塊裝置並掛載使用

# 建立
[[email protected] ~]# rbd create --size 10240000 rbd/test1    #建立指定大小的node
[
[email protected]
~]# rbd info test1 rbd image 'test1': size 10000 GB in 2560000 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.31e3b6b8b4567 format: 2 features: layering, exclusive-lock,object-map, fast-diff, deep-flatten flags: #對映進核心操作之前,首先檢視核心版本,jw版本的ceph預設format為2,預設開啟5種特性,2.x及之前的核心版本需手動調整format為1 ,4.x之前要關閉object-map, fast-diff, deep-flatten功能才能成功對映到核心,這裡使用的是centos7.4,核心版本3.10 [
[email protected]
~]# rbd feature disable test1 object-map fast-diff deep-flatten # 對映進核心 [[email protected] ~]# rbd map test1 [[email protected] ~]# ls /dev/rbd0 /dev/rbd0 #掛載使用 [[email protected] ~]# mkdir /mnt/cephrbd [[email protected] ~]# mkfs.ext4 -m0 /dev/rbd0 [[email protected]
~]# mount /dev/rbd0 /mnt/cephrbd/

Kubernetes Dynamic Pv 使用

首先回顧一下上篇cephfs在k8s中的使用方式:
繫結使用流程: pv指定儲存型別和介面,pvc繫結pv,pod掛載指定pvc.這種一一對應的方式,即為靜態pv
例如cephfs的使用流程:
在這裡插入圖片描述

那麼什麼是動態pv呢?
在現有PV不滿足PVC的請求時,可以使用儲存分類(StorageClass),pvc對接sc後,k8s會動態地建立pv,並且向相應的儲存後端發出資源申請.
描述具體過程為:首先建立sc分類,PVC請求已建立的sc的資源,來自動建立pv,這樣就達到動態配置的效果。即通過一個叫 Storage Class的物件由儲存系統根據PVC的要求自動建立pv並使用儲存資源

Kubernetes的pv支援rbd,從第一部分測試使用rbd的過程可以看出,儲存實際使用的單位是image,首先必須在ceph端建立image,才能建立pv/pvc,再在pod裡面掛載使用.這是一個標準的靜態pv的繫結使用流程.但是這樣的流程就帶來了一個弊端,即一個完整的儲存資源掛載使用的操作被分割成了兩段,一段在ceph端劃分rbd image,一段由k8s端繫結pv,這樣使得管理的複雜性提高,不利於自動化運維.

因此,動態pv是一個很好的選擇,ceph rbd介面的動態pv的實現流程是這樣的:
根據pvc及sc的宣告,自動生成pv,且向sc指定的ceph後端發出申請自動建立相應大小的rbd image,最終繫結使用

工作流程圖:
在這裡插入圖片描述

下面開始演示
1.建立secret
key獲取方式參考上篇文章

~/mytest/ceph/rbd# cat ceph-secret-rbd.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret-rbd
type: "kubernetes.io/rbd"
data:
  key: QVFCL3E1ZGIvWFdxS1JBQTUyV0ZCUkxldnRjQzNidTFHZXlVYnc9PQ==

2.建立sc

~/mytest/ceph/rbd# cat ceph-secret-rbd.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: cephrbd-test2
provisioner: kubernetes.io/rbd
reclaimPolicy: Retain
parameters:
  monitors: 192.168.20.112:6789,192.168.20.113:6789,192.168.20.114:6789
  adminId: admin
  adminSecretName: ceph-secret-rbd
  pool: rbd
  userId: admin
  userSecretName: ceph-secret-rbd
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"

建立pvc

~/mytest/ceph/rbd# cat cephrbd-pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: cephrbd-pvc2
spec:
  storageClassName: cephrbd-test2
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

建立deploy,容器掛載使用建立的pvc

:~/mytest/ceph/rbd# cat deptest13dbdm.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: deptest13dbdm
  name: deptest13dbdm
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deptest13dbdm
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: deptest13dbdm
    spec:
      containers:
        image: registry.xxx.com:5000/mysql:56v6
        imagePullPolicy: Always
        name: deptest13dbdm
        ports:
        - containerPort: 3306
          protocol: TCP
        resources:
          limits:
            memory: 16Gi
          requests:
            memory: 512Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: datadir
          subPath: deptest13dbdm
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: datadir
        persistentVolumeClaim:
          claimName: cephrbd-pvc2

這裡會遇到一個大坑:

~# kubectl describe pvc cephrbd-pvc2 
...
Error creating rbd image: executable file not found in $PATH

這是因為kube-controller-manager需要呼叫rbd客戶端api來建立rbd image,叢集的每個節點都已經安裝ceph-common,但是叢集是使用kubeadm部署的,kube-controller-manager元件是以容器方式工作的,內部不包含rbd的執行檔案,後面在這個issue裡,找到了解決的辦法:
Github issue
使用外部的rbd-provisioner,提供給kube-controller-manager以rbd的執行入口,注意,issue內的demo指定的image版本有bug,不能指定rbd掛載後使用的檔案系統格式,需要使用最新的版本demo,專案地址:rbd-provisioner
完整demo yaml檔案:

[email protected]:~/mytest/ceph/rbd/rbd-provisioner# cat rbd-provisioner.yaml 
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbd-provisioner
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: ["create", "update", "patch"]
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["kube-dns","coredns"]
    verbs: ["list", "get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbd-provisioner
subjects:
  - kind: ServiceAccount
    name: rbd-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: rbd-provisioner
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: rbd-provisioner
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: rbd-provisioner
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: rbd-provisioner
subjects:
- kind: ServiceAccount
  name: rbd-provisioner
  namespace: default

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: rbd-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: rbd-provisioner
    spec:
      containers:
      - name: rbd-provisioner
        image: quay.io/external_storage/rbd-provisioner:latest
        env:
        - name: PROVISIONER_NAME
          value: ceph.com/rbd
      serviceAccount: rbd-provisioner

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: rbd-provisioner

部署完成後,重新建立上方的sc/pv,這個時候,pod就正常執行起來了,檢視pvc,可以看到此pvc觸發自動生成了一個pv且綁定了此pv,pv繫結的StorageClass則是剛建立的sc:

# pod
~/mytest/ceph/rbd/rbd-provisioner# kubectl get pods | grep deptest13
deptest13dbdm-c9d5bfb7c-rzzv6                     2/2       Running            0          6h

# pvc
~/mytest/ceph/rbd/rbd-provisioner# kubectl get pvc cephrbd-pvc2
NAME           STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
cephrbd-pvc2   Bound     pvc-d976c2bf-c2fb-11e8-878f-141877468256   20Gi       RWO            cephrbd-test2   23h

# 自動建立的pv
~/mytest/ceph/rbd/rbd-provisioner# kubectl get pv pvc-d976c2bf-c2fb-11e8-878f-141877468256
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                  STORAGECLASS    REASON    AGE
pvc-d976c2bf-c2fb-11e8-878f-141877468256   20Gi       RWO            Retain           Bound     default/cephrbd-pvc2   cephrbd-test2             23h

# sc
~/mytest/ceph/rbd/rbd-provisioner# kubectl get sc cephrbd-test2
NAME            PROVISIONER    AGE
cephrbd-test2   ceph.com/rbd   23h

再回到ceph節點上看看是否自動建立了rbd image

~# rbd ls
kubernetes-dynamic-pvc-d988cfb1-c2fb-11e8-b2df-0a58ac1a084e
test1

~# rbd info kubernetes-dynamic-pvc-d988cfb1-c2fb-11e8-b2df-0a58ac1a084e
rbd image 'kubernetes-dynamic-pvc-d988cfb1-c2fb-11e8-b2df-0a58ac1a084e':
	size 20480 MB in 5120 objects
	order 22 (4096 kB objects)
	block_name_prefix: rbd_data.47d0b6b8b4567
	format: 2
	features: layering
	flags: 

可以發現,動態建立pv/rbd成功

掛載測試

回顧最上方的kubernetes支援的接入模式截圖,rbd是不支援ReadWriteMany的,而k8s的理念是像牲口一樣管理你的容器,容器節點有可能隨時橫向擴充套件,橫向縮減,在節點間漂移,因此,不支援多點掛載的RBD模式,顯然不適合做多應用節點之間的共享檔案儲存,這裡進行一次進一步的驗證

多點掛載測試

建立一個新的deploy,並掛載同一個pvc:

[email protected]:~/mytest/ceph/rbd# cat deptest14dbdm.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "4"
  creationTimestamp: 2018-09-26T07:32:41Z
  generation: 4
  labels:
    app: deptest14dbdm
    domain: dev.deptest14dbm.kokoerp.com
    nginx_server: ""
  name: deptest14dbdm
  namespace: default
  resourceVersion: "26647927"
  selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/deptest14dbdm
  uid: 5a1a62fe-c15e-11e8-878f-141877468256
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deptest14dbdm
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: deptest14dbdm
        domain: dev.deptest14dbm.kokoerp.com
        nginx_server: ""
    spec:
      containers:
      - env:
        - name: DB_NAME
          value: deptest14dbdm
        image: registry.youkeshu.com:5000/mysql:56v6
        imagePullPolicy: Always
        name: deptest14dbdm
        ports:
        - containerPort: 3306
          protocol: TCP
        resources:
          limits:
            memory: 16Gi
          requests:
            memory: 512Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: datadir
          subPath: deptest14dbdm
      - env:
        - name: DATA_SOURCE_NAME
          value: exporter:[email protected](127.0.0.1:3306)/
        image: registry.youkeshu.com:5000/mysqld-exporter:v0.10
        imagePullPolicy: Always
        name: mysql-exporter
        ports:
        - containerPort: 9104
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      nodeSelector:
        192.168.20.109: ""
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: datadir
        persistentVolumeClaim:
          claimName: cephrbd-pvc2

使用nodeselector將此deptest13和deptest14限制在同一個node中:

[email protected]:~/mytest/ceph/rbd# kubectl get pods -o wide | grep deptest1[3-4]
deptest13dbdm-c9d5bfb7c-rzzv6                     2/2       Running            0          6h        172.26.8.82    h020109
deptest14dbdm-78b8bb7995-q84dk                    2/2       Running            0          2m        172.26.8.84    h020109

不難發現在同一個節點中,是可以支援多個pod共享rbd image執行的,在容器的工作節點上檢視mount條目也可以證實這一點:

192.168.20.109:~# mount | grep rbd
/dev/rbd0 on /var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/rbd-image-kubernetes-dynamic-pvc-d988cfb1-c2fb-11e8-b2df-0a58ac1a084e type ext4 (rw,relatime,stripe=1024,data=ordered)
/dev/rbd0 on /var/lib/kubelet/pods/68b8e3c5-c38d-11e8-878f-141877468256/volumes/kubernetes.io~rbd/pvc-d976c2bf-c2fb-11e8-878f-141877468256 type ext4 (rw,relatime,stripe=1024,data=ordered)
/dev/rbd0 on /var/lib/kubelet/pods/1e9b04b1-c3c3-11e8-878f-141877468256/volumes/kubernetes.io~rbd/pvc-d976c2bf-c2fb-11e8-878f-141877468256 type ext4 (rw,relatime,stripe=1024,data=ordered)

修改新deploy的nodeselector指向其他的node:

~/mytest/ceph/rbd# kubectl get pods -o wide| grep deptest14db
deptest14dbdm-78b8bb7995-q84dk                    0/2       Terminating         0          7m        172.26.8.84    h020109
deptest14dbdm-79fd495579-rkl92                    0/2       ContainerCreating   0          49s       <none>         h009028

# kubectl describe pod deptest14dbdm-79fd495579-rkl92
...
  Warning  FailedAttachVolume     1m    attachdetach-controller  Multi-Attach error for volume "pvc-d976c2bf-c2fb-11e8-878f-141877468256" Volume is already exclusively attached to one node and can't be attached to another

pod將阻塞在ContainerCreating狀態,描述報錯很清晰地指出控制器不支援多點掛載此pv.
進行下一步測試前先刪除此臨時新增的deploy

滾動更新測試

在deptest13dbdm的deploy檔案中指定的更新方式為滾動更新:

  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate

這裡我們嘗試一下,將正在執行的pod,從一個節點排程到另一個節點,rbd 是否能遷移到新的節點上掛載:

# 修改nodeselector
[email protected]:~/mytest/ceph/rbd# kubectl edit deploy deptest13dbdm
deployment "deptest13dbdm" edited

# 觀察pod排程遷移過程
[email protected]:~/mytest/ceph/rbd# kubectl get pods -o wide| grep deptest13
deptest13dbdm-6999f5757c-fk9dp                    0/2       ContainerCreating   0          4s        <none>         h009028
deptest13dbdm-c9d5bfb7c-rzzv6                     2/2       Terminating         0          6h        172.26.8.82    h020109

[email protected]:~/mytest/ceph/rbd# kubectl describe pod deptest13dbdm-6999f5757c-fk9dp 
...
Events:
  Type     Reason                 Age                From                 Message
  ----     ------                 ----               ----                 -------
  Normal   Scheduled              2m                 default-scheduler    Successfully assigned deptest13dbdm-6999f5757c-fk9dp to h009028
  Normal   SuccessfulMountVolume  2m                 kubelet, h009028  MountVolume.SetUp succeeded for volume "default-token-7q8pq"
  Warning  FailedMount            45s                kubelet, h009028  Unable to mount volumes for pod "deptest13dbdm-6999f5757c-fk9dp_default(28e9cdd6-c3c5-11e8-878f-141877468256)": timeout expired waiting for volumes to attach/mount for pod "default"/"deptest13dbdm-6999f5757c-fk9dp". list of unattached/unmounted volumes=[datadir]
  Normal   SuccessfulMountVolume  35s (x2 over 36s)  kubelet, h009028  MountVolume.SetUp succeeded for volume "pvc-d976c2bf-c2fb-11e8-878f-141877468256"
  Normal   Pulling                27s                kubelet, h009028  pulling image "registry.youkeshu.com:5000/mysql:56v6"
  Normal   Pulled                 27s                kubelet, h009028  Successfully pulled image "registry.youkeshu.com:5000/mysql:56v6"
  Normal   Pulling                27s                kubelet, h009028  pulling image "registry.youkeshu.com:5000/mysqld-exporter:v0.10"
  Normal   Pulled                 26s                kubelet, h009028  Successfully pulled image "registry.youkeshu.com:5000/mysqld-exporter:v0.10"
  Normal   Created                26s                kubelet, h009028  Created container
  Normal   Started                26s                kubelet, h009028  Started container

[email protected]:~/mytest/ceph/rbd# kubectl get pods -o wide| grep deptest13
deptest13dbdm-6999f5757c-fk9dp                    2/2       Running            0          3m        172.26.0.87    h009028

#在原node上檢視核心中對映的rbd image塊裝置描述檔案已消失,掛載已取消
[email protected]:~/tpcc-mysql# ls /dev/rbd*
ls: cannot access '/dev/rbd*': No such file or directory
[email protected]:~/tpcc-mysql# mount | grep rbd
[email protected]:~/tpcc-mysql# 

可以看出,是可以自動完成在節點間遷移的滾動更新的,整個排程的過程有些漫長,接近3分鐘,這是因為其中至少涉及如下幾個步驟:
1.原pod終結,釋放資源
2.原node取消掛載rbd,釋放核心對映
3.新node核心對映rbd image,掛載rbd到檔案目錄
4.建立pod,掛載指定目錄

結論:
ceph rbd不支援多節點掛載,支援滾動更新.

後續

在完成了使用cephfs和ceph rbd這兩種k8s分散式儲存的對接方式測試之後,下一篇文章將針對這兩種方式進行資料庫效能測試及適用場景討論

相關推薦

k8s()分散式儲存Ceph RBD使用

前言 Ceph儲存有三種儲存介面,分別是: 物件儲存 Ceph Object Gateway 塊裝置 RBD 檔案系統 CEPHFS Kubernetes支援後兩種儲存介面,支援的接入模式如下圖: 在本篇將測試使用ceph rbd作持久化儲存後端 RBD建立

k8s(一)分散式儲存Cephfs使用

前言 在前篇部署測試完cephfs的基礎上: Ceph叢集生產環境安裝部署 cephfs調優 & 效能測試 & 常用命令 本篇介紹k8s使用 pv/pvc的方式使用cephfs分散式檔案系統 使用 首先解釋一下pv/pvc的相關概

儲存過程:高效率執行

                        

十三周作業【Linux微職位】

馬哥教育一、結合圖形描述LVS的工作原理;lvs-nat模型主要是修改目標IP地址為挑選出新的RS的IP地址。即請求進入負載均衡器時做DNAT,響應出負載均衡器時做SNAT。1.當用戶請求到達Director Server,此時請求的數據報文會先到達內核的PREROUTING鏈,此時報文的源IP是CIP,目標

十三天總結筆記

異常、io、file一:File 1.1 File:文件和目錄(文件夾)路徑名的抽象表示形式。 1.2 File的構造方法: File(String pathname):把一個路徑名稱封裝成File對象 File(String p

samba服務器配置和管理

samba、文件共享12.1、Samba簡介 Linux和Windows是兩種無論在風格還是在技術上都完全不同的操作系統,它們是兩個對立的陣形。各自都擁有自己的用戶群和市場。但是,要實現這兩種系統之間的資源共享,則需要使用Samba。Samba采用的是C/S工作模式,通過它可以將一臺Linux系統主機配置為

英文字母和數字不會換行如何處理

英文 一次 bre word-wrap style 英文字母 ron wrap -a 一次偶然的項目中,遇到一個奇怪的問題,為什麽我都寫了換行的css怎麽還是沒有換行?請教宋老師之後才知道“英文字母和數字是不會換行的”,那如何處理呢? 處理辦法,在所在類上增加下面css:

MySQL用戶管理

mysql用戶管理 MySQL是一個多用戶數據庫,具有功能強大的訪問控制系統,可以為不同用戶指定允許的權限。MySQL用戶可以分為普通用戶和root用戶。root用戶是超級管理員,擁有所有權限,普通用戶只擁有被授予的各種權限。12.1、權限表MySQL服務器通過權限來控制用戶對數據庫的訪問,權限表存放在MyS

代理模式

ring style ret 代理類 out 一個 dem public cnblogs 代理模式其實很簡單,就是把具體實現從一個功能類裏面分離,又通過引用的方式把具體實現和功能類關聯,代碼如下: package test; /** * 代理模式 * @author

匿名函數和閉包

lee 內存問題 基於 傳參 不能 更多 垃圾 資源 增強 十二、匿名函數和閉包 匿名函數就是沒有名字的函數,閉包是可訪問一個函數作用域裏變量的函數。聲明:本節內容需要有面向對象和少量設計模式基礎,否則無法聽懂. 1.匿名函數 //普通函數 function b

事件綁定及深入

dom節點 bili rec tex lin 問題: type onload fin 二十二、事件綁定及深入 事件綁定分為兩種:一種是傳統事件綁定(內聯模型,腳本模型),一種是現代事件綁定(DOM2級模型)。現代事件綁定在傳統綁定上提供了更強大更方便的功能。 1.傳

事件,委托,泛型委托,集合(泛型和非泛型),Lambda表達式(聲明委托,使用委托,簡單的委托示例,action<T>和func<t>委托,多播委托,匿名方法,Lambda表達式,參數,事件)

multicast new 調用方法 多播 ted 被調用 輸入參數 pac cas 事件(Event) 事件是一種對象或類能夠提供通知的成員,客戶端可以通過提供事件處理程序為相應的事件可添加可執行代碼,事件可以理解為一種特殊的委托。 委托(Delegate) 委托是存有對

Hadoop學習筆記————Hive的基本原理

中介 優化 prop 指示 使用 計劃分解 分享 ges 歷史數據 一般用戶用CLI(命令行界面)接口,元數據庫含有表結構 單用戶、多用戶、遠程服務 生成db文件,只能單客戶端使用數據庫 多用戶是最常用的使用模式 配置與多用戶一致 數據格式用戶自定義

configparser

def ebo efault item for ive import port gpa configparser   用於讀寫文件,但是必須是下面的格式   將這種文件當字典處理:       {key:{key1=value}} [DEFAULT] ServerAliv

根搜索算法

mar 如果 運行時常量 log 連接 java 不可 靜態 body 根搜索算法是以根對象集合作為起始點,按照從上至下的方式搜索被根對象集合所連接的目標對象是否可達,如果不可達就意味著已經死亡其OOP中的mark word就會標記為垃圾對象。 根對象集合中存儲的內容如下:

索引

根據 圖片 drop 一個 inf 調整 分享圖片 技術 nbsp 1.定義 索引對應的英文單詞是:index 索引的作用:相當於一本字典目錄,提高程序的檢索/查詢效率;表中每一個字段都可添加索引。 註:主鍵會自動添加索引,能夠通過主鍵查詢的盡量通過主鍵查詢,效率較高

usermod命令用戶密碼管理mkpasswd命令

有時 小寫 其他 文件 電話 mod 沒有 happy -- 十二、usermod命令、用戶密碼管理、mkpasswd命令一、usermod命令usermod:更改用戶屬性。格式:usermod -u 111 username;usermod -g 123 username

三大核心特征-多態

div clas abs 派生 pan ima strac function fun 多態指的是面向對象編程時,屏蔽了子類對象之間的差異,可以使調用對象方法的客戶端代碼中代碼保持通用性,而不必針對每個不同的對象寫不同的實現。 多態的實現依靠的是繼承、抽象方法或接口的特性。

雙向鏈表的java實現

rst nod inf ole tmp 插入 頭結點 oid ava 原理圖: 運行結果: Node代碼: public class Node { int data; Node next; Node previous;

iptables filter表小案例iptables nat表應用

iptables小案例 iptables應用 三十二、iptables filter表小案例、iptables nat表應用一、iptables filter表小案例需求:只針對filter表,預設策略INPUT鏈DROP,其他兩個鏈ACCEPT,然後針對192.168.188.0/24開通22端口,