Clickhouse 用户自定义外部函数

Linux49

Clickhouse 用户自定义外部函数

写在前面

Clickhouse 从 21.11 版本开始,除了提供类似SqlServer、MySQL CREATE FUNCTION 的自定义函数之外,还有一个用户自定义函数(UDF),与其说是"用户自定义函数",为了避免混淆,称之为"用户自定义外部函数"更为准确。官方对此功能的解释:

ClickHouse can call any external executable program or script to process data. 译文:ClickHouse可以调用任何外部可执行程序或脚本来处理数据。

可以调用外部程序或脚本来处理数据,这对于数据建模、数据分析等等来说,无疑是杀手锏的存在。

开始

示例情景:调用python脚本实现向量点积运算。

环境:Docker、Clickhouse 21.11.4.14 、Ubuntu 20.04、Python3

1. 在config.xml里内增加

*_function.xml

2. 增加custom_function.xml自定义函数的声明文件

新建custom_function.xml文件,与config.xml、users.xml文件是同级目录下的,如图

3. 声明方法

打开custom_function.xml文件,编写文件内容如下:

executable
        custom_dotProduct
        Float32
        result

            Array(Float32)
            v1

            Array(Float32)
            v2

        JSONEachRow
        0
        python3 /var/lib/clickhouse/user_scripts/custom_dotProduct.py

execute_direct=0,默认是1,1表示将在clickhouse的/data/user_scripts文件夹内搜索脚本,0表是按照用户配置的命令搜索脚本路径,建议设置为0,避免找不到执行的脚本文件。其他参数可以参考文档:Introduction | ClickHouse Documentation

4. 编写python脚本

#!/usr/bin/python3
import sys
import json

if __name__ == '__main__':
    for line in sys.stdin:
        dict = json.loads(line)
        ls = []
        for v in dict.values():
            ls.insert(1, list(v))
        vector1 = tuple(ls[0])
        vector2 = tuple(ls[1])
        v = sum(p * q for p, q in zip(vector1, vector2))
        data = {'result': str(v)}
        print(json.dumps(data), end='\n')
        sys.stdout.flush()

保存脚本并命名为 custom_dotProduct.py ,再放到 /var/lib/clickhouse/user_scripts 文件夹内。

特别需要注意是脚本运行环境和存放路径问题,Clickhouse如果是放到docker里面,则需要在docker内配置python可运行的环境,其他C++、java也是如此,最起码能保证手动执行脚本的时候能运行。 在 custom_function.xml 声明方法的时候,编写的xml文件中的 <span class="cnblogs_code">command</span>命令是容器里面的路径,而不是宿主机的路径。

5. 至此已经完成,进行方法测试

--重新加载方法
SYSTEM RELOAD FUNCTIONS;

--查看方法是否加载成功
SELECT * FROM system.functions WHERE name = 'custom_dotProduct';

Clickhouse 用户自定义外部函数

执行方法:

select custom_dotProduct([1,2,3],[4,5,6]);

Clickhouse 用户自定义外部函数

最后

还需特别注意的是Clickhouse版本问题,在示例的python脚本中和官网文档中的示例python脚本取值方法不太一样,

官方示例:

first_arg = int(value['argument_1'])
second_arg = int(value['argument_2'])

它是通过自定义配置的name获取值:

executable
    test_function_sum_json
    UInt64
    result_name

        UInt64
        argument_1

        UInt64
        argument_2

    JSONEachRow
    test_function_sum_json.py

而我是通过遍历出来的:

for v in dict.values():
            ls.insert(1, list(v))

原因是Clickhouse这种取值方式必须要求在 22.3 版本以上才支持,若低于 22.3的版本用官方的取值方式是永远报错的(巨坑之一)。具体可以看我之前提的Issue: UDFs: JSON Bug ? · Issue #35562 · ClickHouse/ClickHouse (github.com)

另外,从2022年1月后,Clickhouse的Docker镜像将停止 yandex/clickhouse-server 的迭代,使用新的镜像地址 clickhouse/clickhouse-server 。

Clickhouse 用户自定义外部函数

如继续使用 yandex/clickhouse-server的镜像,最新的版本号停留在 22.1.3.7 (巨坑之二)。

好了,下班!不不不,等下下班!

Original: https://www.cnblogs.com/EminemJK/p/16079583.html
Author: 山治先生
Title: Clickhouse 用户自定义外部函数



相关阅读1

Title: redis的事务不是原子性

Reference: https://blog.csdn.net/u011692780/article/details/81213010

一、事务的四大特性

关系型数据库的事务具有四个特性:

  1. 原子性

  2. 一致性

  3. 隔离性

  4. 持久性

二、而在我们redis数据库中,事务回事什么样子的呢?

首先我们给出一个定义:redis的事务中,一次执行多条命令,本质是一组命令的集合,一个事务中所有的命令将被序列化,即按顺序执行而不会被其他命令插入

在redis中,事务的作用就是在一个队列中一次性、顺序性、排他性的执行一系列的命令。

事务的生命周期:

  1. 事务的创建:使用MULTI开启一个事务

  2. 加入队列:在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真的执行

  3. EXEC命令进行提交事务

常用的关于事务的命令有:

  1. MULTI:使用该命令,标记一个事务块的开始,通常在执行之后会回复OK,(但不一定真的OK),这个时候用户可以输入多个操作来代替逐条操作,redis会将这些操作放入队列中。

  2. EXEC:执行这个事务内的所有命令

  3. DISCARD:放弃事务,即该事务内的所有命令都将取消

  4. WATCH:监控一个或者多个key,如果这些key在提交事务(EXEC)之前被其他用户修改过,那么事务将执行失败,需要重新获取最新数据重头操作(类似于乐观锁)。

  5. UNWATCH:取消WATCH命令对多有key的监控,所有监控锁将会被取消。

注意:关于乐观锁等概念:

乐观锁:就像他的名字,不会认为数据不会出错,他不会为数据上锁,但是为了保证数据的一致性,他会在每条记录的后面添加一个标记(类似于版本号),假设A 获取K1这条标记,得到了k1的版本号是1,并对其进行修改,这个时候B也获取了k1这个数据,当然,B获取的版本号也是1,同样也对k1进行修改,这个时候,如果B先提交了,那么k1的版本号将会改变成2,这个时候,如果A提交数据,他会发现自己的版本号与最新的版本号不一致,这个时候A的提交将不会成功,A的做法是重新获取最新的k1的数据,重复修改数据、提交数据。

悲观锁:这个模式将认定数据一定会出错,所以她的做法是将整张表锁起来,这样会有很强的一致性,但是同时会有极低的并发性(常用语数据库备份工作,类似于表锁)。

那么,现在我们来执行一次具体看看redis的事务机制:

首先我会开启事务,并向数据库中存储4条数据,可以看到没执行一条命令的时候都会显示入队,并不会返回执行结果,说明redis中在事务提交之前,其内部的所有命令将不会被执行:

那么,如果中间有命令出错了会怎样呢?现在我随便打几个字符试一试:

可以看出,在第三条命令中我随便打了几个字符,提交事务的时候并没有成功,这也很符合我们对事务的理解,嗯~具有原子性。但是,有一个细节,那就是错误命令在我输入的时候就已经报错了,也就是说这个条错误命令在进入队列的时候redis就已经知道这是一条错误命令,这样,整个事务的命令将全部失败,那么,有没有一种可能某个错误指令在进入队列的时候redis还没有发现他的错误呢?我们试一试下面这个例子:

问题出现了,我们可以看到,name+1这条指令其实是错误的,但是提交事务的时候会发现,这条错误命令确实没有执行,但是其他正确的命令却执行,这是为什么的?

原因是在redis中,对于一个存在问题的命令,如果在入队的时候就已经出错,整个事务内的命令将都不会被执行(其后续的命令依然可以入队),如果这个错误命令在入队的时候并没有报错,而是在执行的时候出错了,那么redis默认跳过这个命令执行后续命令。也就是说,redis只实现了部分事务。

下面我们来看看刚刚提到的锁的问题,我们说过,redis的锁CAS(check and set)类似于乐观锁,redis的实现原理是使用watch进行监视一个(或多个)数据,如果在事务提交之前数据发生了变化(估计使用了类似于乐观锁的标记),那么整个事务将提交失败,我们可以举一个例子,我们开启两个终端,模拟两个人的操作,设置一条数据为count,初始时100,现在A对其进行监控,并且为count增加20

在没有提交之前,B也获取了这个count,为其减少50,

那么这个时候A如果提交事务,会出现失败提示:

可以看到,在A对数据的修改过程中,B对数据进行了修改,那么这条数据的"标记"就发生了变化,已经不是当初A取出数据的时候的标记了,这样,A的事务也就提交失败了。

最后通过上述的实验,我们总结redis事务的三条性质:

  1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
  2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
  3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

三、Redis中的事务为什么没有原子性与watch锁

在传统的关系型数据中,只要有任意一条指令失败,则整个事务都会被撤销回滚,而在Redis中,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做,也因此得出 Redis 事务的执行并不是原子性的。

multi,代表一段事务的开始

exec,代表一个事务的提交

queued,代表某个指令在队列中

但是,也有例外,比如如下这种情况

discard,代表某个事务撤销

watch 锁 ,在事务中不能改变被锁的值 (exec提交后返回nil)

四、总结

在redis中,对于一个存在问题的命令,如果在入队的时候就已经出错,整个事务内的命令将都不会被执行(其后续的命令依然可以入队),如果这个错误命令在入队的时候并没有报错,而是在执行的时候出错了,那么redis默认跳过这个命令执行后续命令。也就是说,redis只实现了部分事务。

总结redis事务的三条性质:

  1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
  2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
  3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

Original: https://www.cnblogs.com/skying555/p/10398724.html
Author: alex.shu
Title: redis的事务不是原子性

相关阅读2

Title: Linux 逻辑卷管理器(LVM)

LVM:

LVM: Logical Volume Manager,可以实现动态的扩容和缩容。逻辑卷是一种逻辑上的管理方式,把一块或多块硬盘或分区逻辑的组合在一起,命令成一个卷组(VG),卷组的空间来自所有硬盘空间的总和。(组成逻辑卷的硬盘或分区大小可以不一样)

VG:

多个磁盘或者分区组合在一起的(逻辑上的大硬盘)

LV:

是从VG中取出一块空间而来的(相当于VG这个逻辑上大硬盘的一个分区)

PE:

PE:物理盘区,作用是负责分配空间的最小单位(逻辑卷中),扩容和缩容都是以PE为单位来操作的。PE大小默认为4M
Clickhouse 用户自定义外部函数

LVM的实现过程:

  • 1.将设备设为物理卷 -- 贴个标签,表示这个硬盘要作为物理卷使用了
  • 2.指定卷组(一个或多个物理卷加入卷组形成一个大硬盘)
  • 3.创建逻辑卷(相当于分区)
  • 4.创建文件系统并挂载
    Clickhouse 用户自定义外部函数

逻辑卷的名字:

逻辑卷有三个名称你可以用,一个真名,两个软连接。

第一个逻辑卷对应设备名:/dev/dm-# (逻辑卷的真名)

dm: device mapper,将一个或多个底层块设备组织成一个逻辑设备的模块

逻辑卷的软链接:

  • /dev/mapper/VG_NAME-LV_NAME
  • /dev/VG_NAME/LV_NAME

逻辑卷的实现范例:

#&#x521B;&#x5EFA;swap&#x7A7A;&#x95F4;&#xFF0C;&#x5206;&#x533A;&#x7684;id&#x8981;&#x6539;&#x4E3A;82&#xFF0C;&#x521B;&#x5EFA;&#x903B;&#x8F91;&#x5377;&#xFF0C;&#x7269;&#x7406;&#x8BBE;&#x5907;&#x5206;&#x533A;&#x7684;id&#x8981;&#x6539;&#x6210;8e fdisk&#x7684;t&#x9009;&#x9879;&#x3002;
#&#x5982;&#x679C;&#x662F;&#x4F7F;&#x7528;&#x786C;&#x76D8;&#x7684;&#x8BDD;&#xFF0C;&#x5C31;&#x4E0D;&#x5B58;&#x5728;&#x6539;ID&#x7684;&#x95EE;&#x9898;&#x4E86;&#x3002;

#&#x8FD9;&#x4E9B;&#x547D;&#x4EE4;&#x4F9D;&#x8D56;lvm2&#x8FD9;&#x4E2A;&#x5DE5;&#x5177;&#x5305;

#&#x521B;&#x5EFA;&#x7269;&#x7406;&#x5377;
pvcreate /dev/sda3

#&#x4E3A;&#x5377;&#x7EC4;&#x5206;&#x914D;&#x7269;&#x7406;&#x5377;
vgcreate vg0&#xFF08;&#x5377;&#x7EC4;&#x540D;&#xFF09; /dev/sda3&#xFF08;&#x628A;&#x521B;&#x5EFA;&#x7684;pv&#x52A0;&#x8FDB;&#x6765;&#xFF09; #-s&#x53EF;&#x4EE5;&#x6307;&#x5B9A;PE&#x7684;&#x5927;&#x5C0F;

#&#x4ECE;&#x5377;&#x7EC4;&#x521B;&#x5EFA;&#x903B;&#x8F91;&#x5377;
lvcreate &#xA0;-L 256M &#xA0;-n data vg0 # -n&#xFF1A;&#x6307;&#x5B9A;&#x8BBE;&#x5907;&#x540D;&#x79F0;  -l&#xFF1A;PE&#x7684;&#x4E2A;&#x6570; -L&#xFF1A;&#x6307;&#x5B9A;LV&#x7684;&#x5927;&#x5C0F;
mkfs.xfs &#xA0; /dev/vg0/data #&#x521B;&#x5EFA;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;

#&#x6302;&#x8F7D;
mount /dev/vg0/data /mnt/data

逻辑卷的扩展和缩减

扩展逻辑卷:

#&#x4E24;&#x6B65;&#x5B9E;&#x73B0; -- &#x7A7A;&#x95F4;&#x6269;&#x5C55;&#x548C;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x6269;&#x5C55; &#xFF08;&#x7F3A;&#x70B9;&#x5728;&#x4E8E;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x6269;&#x5BB9;&#x7684;&#x65F6;&#x5019;&#x4E0D;&#x540C;&#x7CFB;&#x5217;&#x7684;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x547D;&#x4EE4;&#x4E0D;&#x4E00;&#x6837;&#xFF09;

#&#x7B2C;&#x4E00;&#x6B65;&#x5B9E;&#x73B0;&#x903B;&#x8F91;&#x5377;&#x7684;&#x7A7A;&#x95F4;&#x6269;&#x5C55;
lvextend -L [+]#[mMgGtT]&#xFF08;&#x5927;&#x5C0F;&#xFF09; /dev/VG_NAME/LV_NAME #-l:&#x6269;&#x5BB9;&#x591A;&#x5C11;&#x4E2A;pe -L&#xFF1A;&#x6269;&#x5BB9;&#x7684;&#x5927;&#x5C0F; &#x4E0D;&#x5199;+&#x53F7;&#x8868;&#x793A;&#x6269;&#x5BB9;&#x5230;xx&#xFF0C;&#x5199;&#x4E86;+&#x53F7;&#x8868;&#x793A;&#x589E;&#x52A0;xxx

#&#x7B2C;&#x4E8C;&#x6B65;&#x5B9E;&#x73B0;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x7684;&#x6269;&#x5C55;
#&#x4F7F;&#x7528;df&#x547D;&#x4EE4;&#x770B;&#x5230;&#x7684;&#x662F;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x6269;&#x5BB9;&#x4E86;&#x7684;&#x90E8;&#x5206;&#x4F46;&#x662F;&#x4E0A;&#x9762;&#x6CA1;&#x6709;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#xFF0C;&#x6240;&#x4EE5;&#x5C31;&#x770B;&#x4E0D;&#x89C1;
#&#x9488;&#x5BF9;ext
resize2fs /dev/VG_NAME/LV_NAME #resize2fs&#xFF1A;&#x5BF9;ext&#x7CFB;&#x5217;&#x7684;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x8FDB;&#x884C;&#x6269;&#x5BB9;&#xFF0C;&#x628A;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x540C;&#x6B65;&#x5230;&#x7A7A;&#x95F4;&#x91CC;&#x9762;&#x53BB;
#&#x9488;&#x5BF9;xfs
xfs_growfs MOUNTPOINT

#&#x4E00;&#x6B65;&#x5B9E;&#x73B0;&#x5BB9;&#x95F4;&#x548C;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x7684;&#x6269;&#x5C55;&#xFF08;&#x4E0D;&#x7528;&#x5173;&#x6CE8;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x7684;&#x7C7B;&#x578B;&#xFF0C;&#x76F4;&#x63A5;&#x6269;&#x5BB9;&#xFF09;
lvextend -r -l +100%FREE /dev/VG_NAME/LV_NAME #-l&#xFF1A;pe&#x7684;&#x4E2A;&#x6570;  -r&#xFF1A;&#x8868;&#x793A;&#x4E0D;&#x7BA1;&#x662F;&#x4EC0;&#x4E48;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x90FD;&#x7ACB;&#x5373;&#x540C;&#x6B65;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;  +100%FREE&#xFF1A;&#x8868;&#x793A;&#x5269;&#x4E0B;&#x7684;&#x6240;&#x6709;&#x5269;&#x4F59;&#x7A7A;&#x95F4;

扩展卷组的空间:

##&#x6DFB;&#x52A0;&#x7269;&#x7406;&#x5377;&#x5230;&#x5377;&#x7EC4;&#x4E2D;&#xFF08;&#x5206;&#x533A;&#x9700;&#x8981;&#x6539;id&#x53F7;&#xFF09;
pvcreate &#x7269;&#x7406;&#x5377;

##&#x5C06;&#x6DFB;&#x52A0;&#x7684;&#x8BBE;&#x5907;&#x6DFB;&#x52A0;&#x5230;&#x5377;&#x7EC4;&#x4E2D;
vgextend &#x5377;&#x7EC4;&#x540D; &#x7269;&#x7406;&#x5377;

缩减逻辑卷(有丢失数据的风险)

#&#x5EFA;&#x8BAE;&#x5148;&#x5907;&#x4EFD;&#x518D;&#x7F29;&#x51CF;&#xFF0C;xfs&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x4E0D;&#x652F;&#x6301;&#x7F29;&#x51CF;

#&#x4E94;&#x4E2A;&#x6B65;&#x9AA4;&#xFF1A;1.&#x5378;&#x8F7D; -- 2.&#x68C0;&#x67E5;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x5B8C;&#x6574;&#x6027;&#xFF08;&#x4E0D;&#x7BA1;&#x662F;&#x5426;&#x5B8C;&#x6574;&#x5FC5;&#x987B;&#xFF09; -- 3.&#x7F29;&#x51CF;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF; --  4.&#x7F29;&#x51CF;&#x903B;&#x8F91;&#x5377;&#x5927;&#x5C0F; -- 5.&#x91CD;&#x65B0;&#x6302;&#x8F7D;

#1.&#x5378;&#x8F7D;&#xFF1A;
umount /dev/VG_NAME/LV_NAME #&#x9996;&#x5148;&#x5378;&#x8F7D;

#2.&#x68C0;&#x67E5;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x5B8C;&#x6574;&#x6027;
e2fsck -f /dev/VG_NAME/LV_NAME

#3.&#x7F29;&#x51CF;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;
resize2fs /dev/VG_NAME/LV_NAME #[mMgGtT]&#xFF08;&#x7F29;&#x51CF;&#x540E;&#x7684;&#x5927;&#x5C0F;&#xFF0C;&#x4F8B;&#x5982;2G&#x8868;&#x793A;&#x7F29;&#x51CF;&#x5230;2G&#xFF09;

#4.&#x7F29;&#x51CF;&#x903B;&#x8F91;&#x5377;&#x5927;&#x5C0F;
lvreduce -L  [-]#[mMgGtT]&#xFF08;&#x8FD9;&#x4E2A;&#x5927;&#x5C0F;&#x8981;&#x548C;&#x4E0A;&#x9762;&#x7684;&#x5927;&#x5C0F;&#x76F8;&#x5339;&#x914D;&#xFF09; /dev/VG_NAME/LV_NAME&#xFF08;&#x5BF9;&#x8C01;&#x8FDB;&#x884C;&#x7F29;&#x51CF;&#xFF09;

#5.&#x91CD;&#x65B0;&#x6302;&#x8F7D;
mount /dev/VG_NAME/LV_NAME mountpoint

清除缓存的方法:

&#x4F7F;&#x7528; free -h &#x53EF;&#x4EE5;&#x770B;&#x5230;&#x7F13;&#x5B58;
&#x67E5;&#x770B;&#x7F13;&#x5B58;&#x5BF9;&#x5E94;&#x7684;&#x76EE;&#x5F55;&#xFF1A; find /proc -name 'drop*' --- /proc/sys/vm/drop_caches
&#x6E05;&#x7406;&#x7F13;&#x5B58;&#xFF1A;echo 3 > /proc/sys/vm/drop_caches --- 3&#x5C31;&#x662F;&#x6E05;&#x7406;&#x7F13;&#x5B58;
#&#x7F13;&#x5B58;&#x7684;&#x76EE;&#x7684;&#x5C31;&#x662F;&#x4E3A;&#x4E86;&#x63D0;&#x9AD8;&#x6027;&#x80FD;&#xFF08;&#x4E00;&#x822C;&#x505A;&#x6D4B;&#x8BD5;&#x7684;&#x65F6;&#x5019;&#x624D;&#x6E05;&#x7406;&#x7F13;&#x5B58;&#xFF09;

拆除指定的PV存储设备

要想移除指定的pv存储设备,首先要将它上面的数据移到别的pv上面去。(要确保上面的数据在别的pv上面能存得下)

#&#x5B9E;&#x73B0;&#x65B9;&#x6CD5;&#xFF1A;

#&#x79FB;&#x52A8;&#x6307;&#x5B9A;pv&#x8BBE;&#x5907;&#x4E0A;&#x7684;&#x6240;&#x6709;&#x88AB;&#x5360;&#x7528;&#x7684;pe&#x79FB;&#x52A8;&#x5230;&#x540C;&#x4E00;&#x5377;&#x7EC4;&#x7684;&#x5176;&#x4ED6;&#x6210;&#x5458;&#x4E0A;&#x9762;
pvmove &#x6307;&#x5B9A;&#x7684;pv&#x8BBE;&#x5907;

#&#x628A;pv&#x8BBE;&#x5907;&#x4ECE;vg&#x91CC;&#x9762;&#x79FB;&#x8D70;
vgreduce &#x6307;&#x5B9A;&#x7684;&#x8BBE;&#x5907;

#&#x4E0D;&#x8BA9;&#x8FD9;&#x4E2A;&#x8BBE;&#x5907;&#x4F5C;&#x4E3A;pv&#x4E86;
pvremove &#x6307;&#x5B9A;&#x7684;&#x8BBE;&#x5907;

删除逻辑卷

应该倒过来删除,从逻辑卷、卷组再到物理卷

  • 1.取消挂载
  • 2.删除逻辑卷: lvremove 逻辑卷
  • 3.删除卷组: vgremove 卷组
  • 4.删除物理卷:pbremove 物理卷

逻辑卷快照

快照:把当前的状态快速做一个备份,快照类似备份的效果,但是特别快
逻辑卷快照:瞬间把逻辑卷做个备份

工作逻辑:

  • 首先有一个卷组,卷组里面存在一个逻辑卷,假设逻辑卷里面有一些文件。
  • 做快照就是在同属于同一卷组的空间中创建一个逻辑卷(快照逻辑卷--snapshot,具有特殊属性)。
  • 创建快照的时候并没有把原逻辑卷中的数据备份到快照中,只是在硬盘上分配了一个空间。
  • 起到备份效果是因为在更改原文件的时候,会自动把被修改文件的旧版本推送到快照里面去了(只存放最初的原始版本)没有修改的文件就不会被放到做快照的这个空间里面去。

总结:

快照备份逻辑:创建快照的时候会分配一块空间,只有原文件发生了修改,才会把这个原文件的最初版本放到快照里面去(快照里面只放发生了改变的数据)。

快照的实现:(快照也是一种逻辑卷,所以使用的命令和创建逻辑卷的命令一样)

#&#x4E3A;&#x73B0;&#x6709;&#x903B;&#x8F91;&#x5377;&#x521B;&#x5EFA;&#x5FEB;&#x7167;,&#x6CE8;&#x610F;ext4&#x5FC5;&#x987B;&#x4F7F;&#x7528;-p r &#x5B9E;&#x73B0;&#x53EA;&#x8BFB;

#&#x521B;&#x5EFA;&#x5FEB;&#x7167;&#xFF1A;
lvcreate -l 64 -s -n data-snapshot /dev/vg0/data
#-l: &#x6307;&#x5B9A;&#x8FD9;&#x4E2A;&#x5FEB;&#x7167;&#x7684;&#x5927;&#x5C0F;&#xFF08;&#x591A;&#x5C11;&#x4E2A;pe&#xFF09;
# -s:&#x8868;&#x793A;&#x521B;&#x5EFA;&#x7684;&#x662F;&#x5FEB;&#x7167;&#xFF0C;&#x4E0D;&#x52A0;s&#x8868;&#x793A;&#x521B;&#x5EFA;&#x7684;&#x662F;&#x666E;&#x901A;&#x903B;&#x8F91;&#x5377;
# -n&#xFF1A; &#x5FEB;&#x7167;&#x7684;&#x540D;&#x5B57;
# /dev/vg0/data -- &#x8868;&#x793A;&#x6307;&#x5B9A;&#x7684;&#x662F;&#x8C01;&#x7684;&#x5FEB;&#x7167;&#xFF08;&#x539F;&#x59CB;&#x903B;&#x8F91;&#x5377;&#x7684;&#x540D;&#x79F0;&#xFF09;
&#x521B;&#x5EFA;&#x5B8C;&#x6210;&#x540E;&#x53EF;&#x4EE5;&#x4F7F;&#x7528; lvs&#x6216;lvdisplay&#x6765;&#x8FDB;&#x884C;&#x67E5;&#x770B;&#xFF08;&#x56E0;&#x4E3A;&#x5FEB;&#x7167;&#x4E5F;&#x662F;&#x4E00;&#x4E2A;&#x903B;&#x8F91;&#x5377;&#xFF09;

#&#x521B;&#x5EFA;&#x5FEB;&#x7167;&#x4EE5;&#x540E;&#x8FDB;&#x884C;&#x6302;&#x8F7D;
#&#x6302;&#x8F7D;&#x5FEB;&#x7167;,xfs&#x6CE8;&#x610F;&#x8981;&#x4F7F;&#x7528;-o ro&#x5B9E;&#x73B0;&#x53EA;&#x8BFB;,&#x8BBF;&#x6B62;&#x5FEB;&#x7167;&#x88AB;&#x4FEE;&#x6539;
mkdir &#xA0;-p /mnt/snap
mount -o ro,nouuid /dev/vg0/data-snapshot &#xA0; /mnt/snap   #nouuid--&#x4E0D;&#x68C0;&#x67E5;uuid xfs&#x8FD9;&#x7C7B;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x4E0D;&#x5141;&#x8BB8;&#x76F8;&#x540C;&#x7684;uuid&#x8BBE;&#x5907;&#x6302;&#x8F7D;&#xFF0C; ext&#x7CFB;&#x5217;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x4E0D;&#x7528;&#x52A0;nouuid&#x90FD;&#x884C;&#x7684;
#&#x6302;&#x8F7D;&#x4EE5;&#x540E;&#xFF0C;&#x8FDB;&#x5165;&#x8FD9;&#x4E2A;&#x76EE;&#x5F55;&#x8FDB;&#x884C;&#x67E5;&#x770B;&#x80FD;&#x770B;&#x7684;&#x6570;&#x636E;&#x7684;&#x539F;&#x56E0;&#x662F;&#xFF08;&#x8FD9;&#x91CC;&#x9762;&#x7684;&#x6570;&#x636E;&#x662F;&#x6765;&#x6E90;&#x4E8E;&#x539F;&#x903B;&#x8F91;&#x5377;&#x7684;&#xFF0C;&#x5E76;&#x975E;&#x5DF2;&#x7ECF;&#x5C06;&#x8FD9;&#x4E9B;&#x6570;&#x636E;&#x5907;&#x4EFD;&#x4E86;&#xFF0C;&#x56E0;&#x4E3A;&#x4E4B;&#x540E;&#x539F;&#x903B;&#x8F91;&#x5377;&#x7684;&#x6570;&#x636E;&#x4FEE;&#x6539;&#x4EE5;&#x540E;&#xFF0C;&#x624D;&#x4F1A;&#x5907;&#x4EFD;&#x88AB;&#x4FEE;&#x6539;&#x6570;&#x636E;&#x7684;&#x521D;&#x59CB;&#x6570;&#x636E;&#xFF09;

#&#x6062;&#x590D;&#x5FEB;&#x7167;&#xFF08;&#x4F7F;&#x7528;&#x5FEB;&#x7167;&#x6570;&#x636E;&#x8FD8;&#x539F;&#x4FEE;&#x6539;&#x8FC7;&#x7684;&#x6570;&#x636E;&#xFF09;
umount /dev/vg0/data-snapshot  #&#x5148;&#x53D6;&#x6D88;&#x6302;&#x8F7D;
umount /dev/vg0/data  #&#x5148;&#x53D6;&#x6D88;&#x6302;&#x8F7D;
lvconvert --merge /dev/vg0/data-snapshot #&#x5229;&#x7528;&#x5FEB;&#x7167;&#x8FD8;&#x539F;&#x539F;&#x6765;&#x7684;&#x903B;&#x8F91;&#x5377;&#x6570;&#x636E;
#merge -- &#x5408;&#x5E76;&#xFF0C;&#x878D;&#x5165;

#&#x8FD8;&#x539F;&#x4EE5;&#x540E;&#xFF0C;&#x5FEB;&#x7167;&#x4F1A;&#x81EA;&#x52A8;&#x5220;&#x9664;

Original: https://www.cnblogs.com/heyongshen/p/16439477.html
Author: 背对背依靠
Title: Linux 逻辑卷管理器(LVM)

相关阅读3

Title: Linux sudo实现授权

sudo:superuser do,实现普通用户执行root命令的授权工具。

&#x4E00;&#x822C;&#x7528;&#x6237;&#x7BA1;&#x7406;&#x7CFB;&#x7EDF;&#x7684;&#x65B9;&#x5F0F;&#x662F;&#x5229;&#x7528;su&#x5207;&#x6362;&#x4E3A;&#x8D85;&#x7EA7;&#x7528;&#x6237;&#x3002;&#x4F46;&#x662F;&#x4F7F;&#x7528;su&#x7684;&#x7F3A;&#x70B9;&#x4E4B;&#x4E00;&#x5728;&#x4E8E;&#x5FC5;&#x987B;&#x8981;&#x5148;&#x544A;&#x77E5;&#x8D85;&#x7EA7;&#x7528;&#x6237;&#x7684;&#x5BC6;&#x7801;&#x3002;

sudo&#x4F7F;&#x4E00;&#x822C;&#x7528;&#x6237;&#x4E0D;&#x9700;&#x8981;&#x77E5;&#x9053;&#x8D85;&#x7EA7;&#x7528;&#x6237;&#x7684;&#x5BC6;&#x7801;&#x5373;&#x53EF;&#x83B7;&#x5F97;&#x6743;&#x9650;
#&#x8FC7;&#x7A0B;&#xFF1A;
&#xFF08;1&#xFF09;&#x8D85;&#x7EA7;&#x7528;&#x6237;&#x6388;&#x6743;&#xFF1A;&#x9996;&#x5148; &#x8D85;&#x7EA7;&#x7528;&#x6237; &#x5C06;&#x666E;&#x901A;&#x7528;&#x6237;&#x7684;&#x540D;&#x5B57;&#x3001;&#x53EF;&#x4EE5;&#x6267;&#x884C;&#x7684;&#x7279;&#x5B9A;&#x547D;&#x4EE4;&#x3001;&#x6309;&#x7167;&#x54EA;&#x79CD;&#x7528;&#x6237;&#x6216;&#x7528;&#x6237;&#x7EC4;&#x7684;&#x8EAB;&#x4EFD;&#x6267;&#x884C;&#x7B49;&#x4FE1;&#x606F;&#xFF0C;&#x767B;&#x8BB0;&#x5728;&#x7279;&#x6B8A;&#x7684;&#x6587;&#x4EF6;&#x4E2D;&#xFF08;&#x901A;&#x5E38;&#x662F;/etc/sudoers&#xFF09;&#xFF0C;&#x5373;&#x5B8C;&#x6210;&#x5BF9;&#x8BE5;&#x7528;&#x6237;&#x7684;&#x6388;&#x6743;&#xFF08;&#x6B64;&#x65F6;&#x8BE5;&#x7528;&#x6237;&#x79F0;&#x4E3A;&#x201C;sudoer&#x201D;&#xFF09;&#xFF1B;

&#xFF08;2&#xFF09;&#x7BA1;&#x7406;&#x5458;&#x786E;&#x8BA4;&#x7528;&#x6237;&#x7684;&#x8EAB;&#x4EFD;&#xFF1A;&#x5728;&#x4E00;&#x822C;&#x7528;&#x6237;&#x9700;&#x8981;&#x53D6;&#x5F97;&#x7279;&#x6B8A;&#x6743;&#x9650;&#x65F6;&#xFF0C;&#x5176;&#x53EF;&#x5728;&#x547D;&#x4EE4;&#x524D;&#x52A0;&#x4E0A;&#x201C;sudo&#x201D;&#xFF0C;&#x6B64;&#x65F6;sudo&#x5C06;&#x4F1A;&#x8BE2;&#x95EE;&#x8BE5;&#x7528;&#x6237;&#x81EA;&#x5DF1;&#x7684;&#x5BC6;&#x7801;&#xFF08;&#x4EE5;&#x786E;&#x8BA4;&#x7EC8;&#x7AEF;&#x673A;&#x524D;&#x7684;&#x662F;&#x8BE5;&#x7528;&#x6237;&#x672C;&#x4EBA;&#xFF09;&#xFF0C;&#x56DE;&#x7B54;&#x540E;&#x7CFB;&#x7EDF;&#x5373;&#x4F1A;&#x5C06;&#x8BE5;&#x547D;&#x4EE4;&#x7684;&#x8FDB;&#x7A0B;&#x4EE5;&#x8D85;&#x7EA7;&#x7528;&#x6237;&#x7684;&#x6743;&#x9650;&#x8FD0;&#x884C;&#x3002;

&#xFF08;3&#xFF09;&#x4EE5;&#x8D85;&#x7EA7;&#x7528;&#x6237;&#x8EAB;&#x4EFD;&#x6267;&#x884C;&#x547D;&#x4EE4;&#xFF1A;&#x4E4B;&#x540E;&#x7684;&#x4E00;&#x6BB5;&#x65F6;&#x95F4;&#x5185;&#xFF08;&#x9ED8;&#x8BA4;&#x4E3A;5&#x5206;&#x949F;&#xFF0C;&#x53EF;&#x5728;/etc/sudoers&#x81EA;&#x5B9A;&#x4E49;&#xFF09;&#xFF0C;&#x4F7F;&#x7528;sudo&#x4E0D;&#x9700;&#x8981;&#x518D;&#x6B21;&#x8F93;&#x5165;&#x5BC6;&#x7801;&#x3002;

sudo的组成:

  • 软件包
  • 配置文件
  • 授权规则配置文件
&#x8F6F;&#x4EF6;&#x5305;&#xFF1A;sudo

&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#xFF1A;/etc/sudo.conf  #&#x4E00;&#x822C;&#x4E0D;&#x7528;&#x4FEE;&#x6539;

&#x6388;&#x6743;&#x89C4;&#x5219;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#xFF1A;#
    /etc/sudoers #&#x8FD9;&#x4E2A;&#x6587;&#x4EF6;&#x4E0D;&#x5EFA;&#x8BAE;&#x76F4;&#x63A5;&#x6539;&#xFF0C;&#x56E0;&#x4E3A;&#x6539;&#x9519;&#x4E86;&#x5C31;&#x4F1A;&#x5F71;&#x54CD;&#x6388;&#x6743;x

    /etc/sudoers.d  #&#x53EF;&#x4EE5;&#x628A;&#x6388;&#x6743;&#x6587;&#x4EF6;&#x653E;&#x5728;&#x8FD9;&#x4E2A;&#x76EE;&#x5F55;&#x4E0B;&#x9762;&#xFF0C;&#x9632;&#x6B62;&#x6240;&#x6709;&#x6388;&#x6743;&#x89C4;&#x5219;&#x653E;&#x5728;&#x4E00;&#x8D77;&#x592A;&#x81C3;&#x80BF;

    #&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#x4E2D;&#x652F;&#x6301;&#x4F7F;&#x7528;&#x901A;&#x914D;&#x7B26; glob

&#x5B89;&#x5168;&#x7F16;&#x8F91;&#x6388;&#x6743;&#x89C4;&#x5219;&#x6587;&#x4EF6;&#x548C;&#x8BED;&#x6CD5;&#x68C0;&#x67E5;&#x5DE5;&#x5177;&#xFF1A; visudo &#x2248; vim /etc/sudoers

    /usr/sbin/visudo  #&#x5EFA;&#x8BAE;&#x8FD9;&#x4E2A;&#x547D;&#x4EE4;&#x6765;&#x6539;&#x7528;&#x6237;&#x7684;&#x6388;&#x6743;&#xFF0C;&#x5728;&#x7F16;&#x8F91;&#x7684;&#x65F6;&#x5019;&#x6709;&#x8BED;&#x6CD5;&#x63D0;&#x793A;&#x529F;&#x80FD;&#xFF0C;&#x683C;&#x5F0F;&#x9519;&#x8BEF;&#x4F1A;&#x63D0;&#x793A;

sudo工具授权文件的编写格式

#&#x683C;&#x5F0F;&#xFF1A;
&#x6388;&#x6743;&#x7528;&#x6237;  &#x767B;&#x5165;&#x7684;&#x4E3B;&#x673A;=(&#x4EE3;&#x8868;&#x7528;&#x6237;)   &#x80FD;&#x6267;&#x884C;&#x7684;&#x64CD;&#x4F5C;
user      host=(runas)           command

user: &#x8868;&#x793A;&#x7ED9;&#x8C01;&#x6388;&#x6743;  #%group &#x8868;&#x793A;&#x5BF9;&#x7EC4;&#x8FDB;&#x884C;&#x6388;&#x6743;

host: &#x8868;&#x793A;&#x5728;&#x54EA;&#x4E2A;&#x4E3B;&#x673A;&#x767B;&#x5F55; ALL&#x8868;&#x793A;&#x6240;&#x6709;&#x4E3B;&#x673A;

(runas)&#xFF1A;&#x8868;&#x793A;&#x4EE5;&#x54EA;&#x4E2A;&#x7528;&#x6237;&#x7684;&#x8EAB;&#x4EFD;&#x8FD0;&#x884C; &#x4E00;&#x822C;&#x662F;root

command: &#x8868;&#x793A;&#x80FD;&#x6267;&#x884C;&#x90A3;&#x4E9B;&#x64CD;&#x4F5C;&#xFF08;&#x547D;&#x4EE4;&#x9700;&#x8981;&#x5199;&#x7EDD;&#x5BF9;&#x8DEF;&#x5F84;&#xFF09; ALL&#x8868;&#x793A;&#x6240;&#x6709;

#&#x5176;&#x4E2D;NOPASSWD:command &#x8868;&#x793A;&#x4E0D;&#x7528;&#x9A8C;&#x8BC1;&#x8FD9;&#x4E2A;&#x7528;&#x6237;&#x7684;&#x5BC6;&#x7801;
User&#x7684;&#x5F62;&#x5F0F;:
username #&#x7528;&#x6237;&#x540D;

#uid  #uid&#x7684;&#x5F62;&#x5F0F;

%group_name  #&#x7EC4;&#x7684;&#x5F62;&#x5F0F;

%#gid  #gid&#x7684;&#x5F62;&#x5F0F;

host&#x7684;&#x5F62;&#x5F0F;:
ip&#x6216;hostname  #ip&#x5730;&#x5740;&#x6216;&#x8005;&#x4E3B;&#x673A;&#x540D;

network(/netmask)  #ip&#x5730;&#x5740;/&#x5B50;&#x7F51;&#x63A9;&#x7801;

command&#x7684;&#x5F62;&#x5F0F;:
command name #&#x547D;&#x4EE4;&#x7684;&#x540D;&#x5B57;

directory #&#x8FD9;&#x4E2A;&#x76EE;&#x5F55;&#x91CC;&#x9762;&#x7684;&#x6240;&#x6709;&#x547D;&#x4EE4;&#x90FD;&#x6388;&#x6743;

sudoedit #sudoedit&#x662F;&#x4E00;&#x4E2A;&#x7F16;&#x8F91;&#x6388;&#x6743;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#x7684;&#x5DE5;&#x5177;&#x3002;&#x8868;&#x793A;&#x88AB;&#x6388;&#x6743;&#x7684;&#x7528;&#x6237;&#x53EF;&#x4EE5;&#x7F16;&#x8F91;sudo&#x7684;&#x6388;&#x6743;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#xFF08;/etc/sudoers&#xFF09;
#&#x8303;&#x4F8B;&#xFF1A;&#x6388;&#x6743;tom&#x7528;&#x6237;&#x5177;&#x6709;&#x6302;&#x8F7D;&#x5149;&#x76D8;&#x7684;&#x529F;&#x80FD;

tom ALL=(root) /usr/bin/mount /dev/cdrom /mnt

sudo的别名

  • 用户别名
  • 主机别名
  • 代表者别名
  • 操作别名
sudo&#x6388;&#x6743;&#x7684;&#x65F6;&#x5019;&#x5141;&#x8BB8;&#x52A0;&#x81EA;&#x5B9A;&#x4E49;&#x7684;&#x522B;&#x540D;

&#x56DB;&#x79CD;&#x522B;&#x540D;&#xFF1A;
User_Alias #&#x88AB;&#x6388;&#x6743;&#x7684;&#x7528;&#x6237;

Runas_Alias #&#x4EE3;&#x8868;&#x8C01;

Host_Alias  #&#x4E3B;&#x673A;

Cmnd_Alias #&#x6267;&#x884C;&#x7684;&#x64CD;&#x4F5C;

#&#x522B;&#x540D;&#x5FC5;&#x987B;&#x662F;&#x5927;&#x5199;&#x5B57;&#x6BCD;&#x548C;&#x6570;&#x5B57;&#x3001;&#x4E0B;&#x5212;&#x7EBF;&#x7684;&#x7ED3;&#x5408;

#&#x5B9A;&#x4E49;&#x522B;&#x540D;&#x7684;&#x683C;&#x5F0F;&#xFF1A;
&#x5B9A;&#x4E49;&#x522B;&#x540D;&#x7C7B;&#x578B; &#x522B;&#x540D;&#x7684;&#x540D;&#x79F0; = &#x503C;1&#xFF0C;...,&#x503C;n

范例

User_Alias &#xA0;NETADMIN= netuser1,netuser2 #&#x5B9A;&#x4E49;&#x7528;&#x6237;&#x522B;&#x540D;

Cmnd_Alias NETCMD = /usr/sbin/ip,/usr/sbin/ifcon #&#x5B9A;&#x4E49;&#x64CD;&#x4F5C;&#x522B;&#x540D;

NETADMIN ALL=&#xFF08;root&#xFF09; NETCMD

sudo命令:

sudo -i -u tom 切换身份功能和 su 相似,但不一样  #因为sudo必须提前授权,而且要输入自已的密码确认自己的身份,而su的话是需要切换者的密码。

#su switch user

sudo [-u user] COMMAND

-V 显示版本信息等配置信息

-u user 默认为root #表示代表谁执行这个操作

-l,ll 列出用户在主机上可用的和被禁止的命令

-v 再延长密码有效期限5分钟,更新时间戳

范例

#&#x4FEE;&#x6539;&#x9A8C;&#x8BC1;&#x5BC6;&#x7801;&#x95F4;&#x9694;&#x4E3A;2&#x5206;&#x949F;
[root@centos8 ~]#vim /etc/sudoers
    Defaults &#xA0; env_reset , timestamp_timeout=2

#sudo -V &#x53EF;&#x4EE5;&#x67E5;&#x770B;&#x7528;&#x6237;&#x7684;&#x9ED8;&#x8BA4;&#x65F6;&#x95F4;&#x95F4;&#x9694;&#x3002;
#ubuntu 默认用户具有sudo权限

#它是将普通用户都加到了sudo这个组里面了。

root@ubuntu1804:~# grep %sudo /etc/sudoers

%sudo ALL=(ALL:ALL) ALL #ALL:ALL 任何用户:任何组
&#x4FEE;&#x6539;ubuntu&#x7684;visudo&#x7684;&#x9ED8;&#x8BA4;&#x7F16;&#x8F91;&#x5668;

#ubuntu&#x7684;visudo&#x9ED8;&#x8BA4;&#x662F;&#x4F7F;&#x7528;nano&#x5DE5;&#x5177;&#x6253;&#x5F00;&#x7684;

export EDITOR=vim

Original: https://www.cnblogs.com/heyongshen/p/16547058.html
Author: 背对背依靠
Title: Linux sudo实现授权