为您推荐:
精华内容
最热下载
问答
  • 2.03MB weixin_46429290 2021-08-28 11:31:38
  • 日志清理compact策略4.1 日志compact的使用场景4.2 compact的工作模式4.3 tombstone 消息4.4 低流量topic的注意事项4.5 简单总结compact的配置5. kafka创建修改topic的命令5.1. 创建topic的时候指定配置5.2 topic

    1. kafka日志清理策略概述

    kafka log的清理策略有两种:delete,compact,默认是delete
    这个对应了kafka中每个topic对于record的管理模式

    1. delete:一般是使用按照时间保留的策略,当不活跃的segment的时间戳是大于设置的时间的时候,当前segment就会被删除
    2. compact: 日志不会被删除,会被去重清理,这种模式要求每个record都必须有key,然后kafka会按照一定的时机清理segment中的key,对于同一个key只保留罪行的那个key.同样的,compact也只针对不活跃的segment
      配置为
    cleanup.policy: delete
    cleanup.policy: compact
    

    如果没有特殊说明,本文中的配置均为kafka-1.1, 且为topic级别是设置

    2. kafka segment

    在学习日志清理策略之前,首先了解一下kafka是如何存储和管理日志的,因为他的管理都是基于segment的,所以有必要先了解清楚这个
    segement的产生策略。

    2.1 segmnet 的作用

    1. kafka的日志存储和消费,对外的最小粒度是partion,也就是producer和consumer最小的选择粒度是某个topic的某些partition。
    2. 每个partition又多个segment组成,这些segment一般是按照时间顺序产生的。
    3. 在单个partition中只有一个处于active的segment,这个segment是正在写入的segment(假设为segmentA),当segmentA的大小达到一定的程度(或者是经过了一定的时长),就会产生一个新的segmentB,这个时候segmentA就不再有数据写入了,变成了不活跃的segment,而segmentB就是当前Active的segment.
    4. 日志清理的策略总是针对不活跃的segment进行的。

    2.2 segment生成相关的配置

    1. segment.bytes: 每个segment的大小,达到这个大小会产生新的segment, 默认是1G
    2. segment.ms: 配置每隔n ms产生一个新的segment,默认是168h,也就是7天

    这两个配置是同时起作用的,那个条件先满足都会执行产生新的segment的动作
    在这里,我们就需要注意,需要理解这两个配置在日志的不同场景下可能带来的影响,在下面介绍具体的日志清理策略的时候会再回来看这一块儿。

    3. 日志清理delete策略

    3.1 delete 相关配置

    假如对某个topic(假设为user_topic)设置了 cleanup.policy: delete
    那么当前topic使用的log删除策略就是 delete,这个策略会周期性的检查partion中的不活跃的segment,根据配置采用两种方式删除一些旧的segment.

    retention.bytes: 总的segment的大小限制,达到这个限制后会删除旧的segment,默认值为-1,就是不会删除
    retention.ms: segment的最后写入record的时间-当前时间 > retention.ms 的segment会被删除,默认是168h, 7天
    

    一些其他的辅助性配置

    log.retention.check.interval.ms: 每隔多久检查一次是否有可以删除的log,默认是300s,5分钟 这个是broker级别的设置
    file.delete.delay.ms: 在彻底删除文件前保留的时间,默认为1分钟   这个是broker级别的设置
    

    在delete的日志策略下,我们来讨论一下,假如我们想要日志保留3天
    我们可以通过设置

    retention.ms: 259200000
    

    假设我们保留其他的配置不便。想想一下这个场景:
    日志产生的很慢,3天还没有达到1g,这个时候根据segment的产生策略,还只有一个segment,而且这个segment是活跃的,所以不能被删除,即使到了第4天可能依然不能被删除。这个时候如果我们依然想要优化存储,就可以使用另一个配置来使删除依然能够按时触发,对的,我们可以设置

    segment.ms: 43200000 # 12个小时
    

    这样的话,每隔12个小时,只有有新的数据进来,都会产生一个新的segment,这样的话,就可以触发3天的删除策略了。
    所以,比较重要的一点是,对于流量比较低的topic,要注意控制 segment.ms< retention.ms

    3.2 简单总结

    kafka启用delete的清理策略的时候需要注意配置

    cleanup.policy: delete
    segment.bytes: 每个segment的大小,达到这个大小会产生新的segment, 默认是1G
    segment.ms: 配置每隔n ms产生一个新的segment,默认是168h,也就是7天
    retention.bytes: 总的segment的大小限制,达到这个限制后会删除旧的segment,默认值为-1,就是不会删除
    retention.ms: segment的最后写入record的时间-当前时间 > retention.ms 的segment会被删除,默认是168h, 7天
    

    对于低流量的topic需要关注使用segment.ms 来配合日志的清理

    4. 日志清理compact策略

    4.1 日志compact的使用场景

    日志清理的compact策略,对于那种需要留存一份全量数据的需求比较有用,什么意思呢,比如,

    我用flink计算了所有用户的粉丝数,而且每5分钟更新一次,结果都存储到kafka当中。
    这个时候kafka相当于是一个数据总线,任何需要用户粉丝数的业务部门都可以从kafka中拿到这个数据。
    这个时候如果数据的保存使用delete策略,为了保存所有用户的粉丝数,只能设置不删除,也就是

    retention.bytes: -1
    retention.ms: Long.MAX #这个值需要自己去设置实际的数值值
    
    

    这样的话,数据会无限膨胀,而且,很多数据是无意义的,因为业务方从kafka中消费数据的时候,实际上只是想知道用户的当前粉丝数是多少,不关注一个月前这个用户有多少粉丝数,但是这些数据都在kafka中存储,会造成无意义的消费。
    kafka提供了一种叫做compact的清理策略,这个策略可以很好的帮助我们应对这种情况。

    kafka的compact 策略要求每个record都要有key,kafka是根据key来进行去重合并的。每个key至少保留一个最新的值。

    4.2 compact的工作模式

    对于每一个kafka partition的日志,以segment为单位,都会被分为两部分,已清理和未清理的部分。同时,未清理的那部分又分为可以清理的和不可清理的。对于可以清理的segment大致是下面的一个清理思路。
    在这里插入图片描述
    同时对于清理过后的segment如果太小,kafka也会有一定的策略去合并这些segemnt,防止segment碎片化。
    我们通过配置

    cleanup.policy: compact
    

    来开启compact的日志清理策略
    配套的配置还有

    1. min.cleanable.dirty.ratio: 可以进行compact的脏数据的比例,dirtyRatio = dirtyBytes / (cleanBytes + dirtyBytes) 其中dirtyBytes表示可清理部分的日志大小,cleanBytes表示已清理部分的日志大小。这个配置也是为了提升清理的性价比设置的,因为清理数据需要对磁盘进行读写,开销并不小,如果你的数据只有很小的重复比例,实际上是没有清理的必要的。这个值默认是0.5 也就是脏了的数据达到了总数据的50%才会清理,一般情况下我如果开启了compact策略,都会将这个值设置为0.1,感觉这样对于想要消费当前topic的业务方更加友好。

    2. min.compaction.lag.ms: 这个设置了在一条消息在被produer发送到kafka当中之后,多久时间以内不会被compact,为了满足有些想要获取一定时间内的历史快照的业务,默认是0,就是不会根据消息投递的时间来决定消息是否应该被compacted

    4.3 tombstone 消息

    在compact下,还有一类比较特殊的消息,只有key,value值为null的消息,这一类消息如果合并了实际上也是没有意义的,因为没有值,所以kafka在compact的时候会删除value为null的消息,但是并不是在第一次去重的时候立刻删除,而是允许存储的更久一些。有一个特殊的配置来处理。
    delete.retention.ms: 这个配置就是专门针对tombstone类型的消息进行设置的。默认为24小时,也就是这个tombstone在当次compact完成后并不会被清理,在下次compact的时候,他的最后修改时间+delete.retention.ms>当前时间,才会被删掉。

    这里面还有一点需要注意的是,如果你想测试tombstone的删除功能的话,请注意不要使用console-producer,他并不能产生value为null的record,坑死个人的,还是老老实实的用java-client跑一跑吧。

    4.4 低流量topic的注意事项

    同样,因为compact针对的是不活跃的segment,所以我们要对低流量的topic特别小心。
    在流量较低的情况下。假如我们设置

    segment.bytes: 每个segment的大小,达到这个大小会产生新的segment, 默认是1G
    segment.ms: 配置每隔n ms产生一个新的segment,默认是168h,也就是7天
    
    

    这样的话,新的segment没有办法产生,也就无从进行compact了。

    4.5 简单总结compact的配置

    kafka启用delete的清理策略的时候需要注意配置

    cleanup.policy: compact
    segment.bytes: 每个segment的大小,达到这个大小会产生新的segment, 默认是1G
    segment.ms: 配置每隔n ms产生一个新的segment,默认是168h,也就是7天
    retention.bytes: 总的segment的大小限制,达到这个限制后会删除旧的segment,默认值为-1,就是不会删除
    retention.ms: segment的最后写入record的时间-当前时间 > retention.ms 的segment会被删除,默认是168h, 7天
    min.cleanable.dirty.ratio: 脏数据可以容忍的比例,如果你的机器性能可以,而且数据量较大的话,建议这个值设置更小一些,对consumer更友好
    min.compaction.lag.ms: 看业务有需要的话可以设置
    

    对于低流量的topic需要关注使用segment.ms 来配合日志的清理

    5. kafka创建修改topic的命令

    5.1. 创建topic的时候指定配置

    #!/bin/bash
    
    
    ZOOKEEPER="127.0.0.1:2181"
    BROKER="127.0.0.1:9092"
    
    TOPIC="post-count-processed"
    
    ## 删除操作
    ../kafka_2.12-2.2.0/bin/kafka-topics.sh --bootstrap-server $BROKER  --delete --topic $TOPIC
    sleep 3
    
    echo "----------------------"
    
    ../kafka_2.12-2.2.0/bin/kafka-topics.sh --zookeeper ${ZOOKEEPER} --create --topic ${TOPIC} --partitions 1    --replication-factor 3  --config cleanup.policy=compact --config segment.ms=86400000 --config min.cleanable.dirty.ratio=0.1
    
    

    5.2 topic创建时忘了设置,修改方式

    #!/bin/bash
    
    ZOOKEEPER="127.0.0.1:2181"
    BROKER="127.0.0.1:9092"
    TOPIC="post-count-processed"
    
    ./kafka_2.12-2.2.0/bin/kafka-configs.sh --zookeeper ${ZOOKEEPER} --entity-type topics --entity-name ${TOPIC}    --alter --add-config "delete.retention.ms=86400000,segment.ms=3600000,min.cleanable.dirty.ratio=0.1"
    
    

    5.3 查看你的配置

    #!/bin/bash
    
    ZOOKEEPER="127.0.0.1:2181"
    BROKER="127.0.0.1:9092"
    TOPIC="post-count-processed"
    
    ../kafka_2.12-2.2.0/bin/kafka-configs.sh --zookeeper  ${ZOOKEEPER} --entity-type topics --entity-name ${TOPIC} --describe
    
    

    参考
    http://kafka.apache.org/11/documentation.html#compaction
    https://www.linkedin.com/pulse/introduction-topic-log-compaction-apache-kafka-nihit-saxena
    https://blog.csdn.net/u013332124/article/details/82793381

    展开全文
    u013200380 2020-05-31 11:28:07
  • InnoDB的行记录格式, Compact, Redundant, Compressed, Dynamic 目录 Compact行记录格式 Redundant行记录格式 Compressed与Dynamic行记录格式 InnoDB存储引擎和大多数数据库一样(如Oracle和Microsoft SQL Server...

    InnoDB的行记录格式, Compact, Redundant, Compressed, Dynamic
    目录

    Compact行记录格式
    Redundant行记录格式
    Compressed与Dynamic行记录格式

    InnoDB存储引擎和大多数数据库一样(如Oracle和Microsoft SQL Server数据库),记录是以行的形式存储的。这意味着页中保存着表中一行行的数据。到MySQL 5.1时,InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录数据,Redundant是为兼容之前版本而保留的,如果你阅读过InnoDB的源代码,会发现源代码中是用PHYSICAL RECORD(NEW STYLE)和PHYSICAL RECORD(OLD STYLE)来区分两种格式的。MySQL 5.1默认保存为Compact行格式。你可以通过命令SHOW TABLE STATUS LIKE 'table_name’来查看当前表使用的行格式,其中row_format就代表了当前使用的行记录结构类型。例如:

    use mysql;

    show table status like ‘user’\G

    数据库实例的一个作用就是读取页中存放的行记录。如果我们知道规则,那么也可以读取其中的记录,如之前的py_innodb_page_info工具。下面将具体分析各格式存放数据的规则。

    回到顶部
    Compact行记录格式
    Compact行记录是在MySQL 5.0时被引入的,其设计目标是能高效存放数据。简单来说,如果一个页中存放的行数据越多,其性能就越高。Compact行记录以如下方式进行存储:

    Compact行格式的首部是一个非NULL变长字段长度列表,而且是按照列的顺序逆序放置的。当列的长度小于255字节,用1字节表示,若大于255个字节,用2个字节表示,变长字段的长度最大不可以超过2个字节(这也很好地解释了为什么MySQL中varchar的最大长度为65 535,因为2个字节为16位,即216=1=65 535)。第二个部分是NULL标志位,该位指示了该行数据中是否有NULL值,用1表示。该部分所占的字节应该为bytes。接下去的部分是为记录头信息(record header),固定占用5个字节(40位),每位的含义见下表4-1。最后的部分就是实际存储的每个列的数据了,需要特别注意的是,NULL不占该部分任何数据,即NULL除了占有NULL标志位,实际存储不占有任何空间。另外有一点需要注意的是,每行数据除了用户定义的列外,还有两个隐藏列,事务ID列和回滚指针列,分别为6个字节和7个字节的大小。若InnoDB表没有定义Primary Key,每行还会增加一个6字节的RowID列。

    下面用一个具体事例来分析Compact行记录的内部结构:

    create table mytest (

    t1 varchar(10),

    t2 varchar(10),

    t3 char(10),

    t4 varchar(10)

    ) engine=innodb charset=latin1 row_format=compact;

    insert into mytest values(‘a’,‘bb’,‘bb’,‘ccc’);

    insert into mytest values(‘d’,‘ee’,‘ee’,‘fff’);

    insert into mytest values(‘d’,NULL,NULL,‘fff’);

    select * from mytest\G;

    创建了mytest表,有4个列,t1、t2、t4都为varchar变长字段类型,t3为固定长度类型char。接着我们插入了3条有代表性的数据,接着打开mytest.ibd(启用了innodb_file_per_table,若你没有启用该选项,请打开默认的共享表空间文件ibdata1)。在Windows下,可以选择用UltraEdit打开该二进制文件(在Linux环境下,使用hexdump -C -v mytest.ibd>mytest.txt即可),打开mytest.txt文件,找到如下内容:

    复制代码
    0000c070 73 75 70 72 65 6d 75 6d 03 02 01 00 00 00 10 00|supremum……
    0000c080 2c 00 00 00 2b 68 00 00 00 00 00 06 05 80 00 00|,……+h……
    0000c090 00 32 01 10 61 62 62 62 62 20 20 20 20 20 20 20|.2…abbbb
    0000c0a0 20 63 63 63 03 02 01 00 00 00 18 00 2b 00 00 00|ccc……+……
    0000c0b0 2b 68 01 00 00 00 00 06 06 80 00 00 00 32 01 10|+h……2…
    0000c0c0 64 65 65 65 65 20 20 20 20 20 20 20 20 66 66 66|deeeefff
    0000c0d0 03 01 06 00 00 20 ff 98 00 00 00 2b 68 02 00 00|……+h……
    0000c0e0 00 00 06 07 80 00 00 00 32 01 10 64 66 66 66 00|……2…dfff.
    该行记录从0000c078开始,若整理如下,相信你会有更好的理解:
    03 02 01/变长字段长度列表,逆序/
    00/NULL标志位,第一行没有NULL值/
    00 00 10 00 2c/记录头信息,固定5字节长度/
    00 00 00 2b 68 00/RowID我们建的表没有主键,因此会有RowID/
    00 00 00 00 06 05/TransactionID/
    80 00 00 00 32 01 10/Roll Pointer/
    61/列1数据’a’/
    62 62/列2’bb’/
    62 62 20 20 20 20 20 20 20 20/列3数据’bb’/
    63 63 63/列4数据’ccc’/
    复制代码
    现在第一行数据就展现在我们眼前了。需要注意的是,变长字段长度列表是逆序存放的,03 02 01,而不是01 02 03。还需要注意的是InnoDB每行有隐藏列。同时可以看到,固定长度char字段在未填充满其长度时,会用0x20来进行填充。再来分析一下,记录头信息的最后4个字节代表next_recorder,0x6800代表下一个记录的偏移量,当前记录的位置+0x6800就是下一条记录的起始位置。所以InnoDB存储引擎在页内部是通过一种链表的结构来串联各个行记录的。

    第二行我将不做整理,除了RowID不同外,它和第一行大同小异,有兴趣的读者可以用上面的方法自己试试。

    现在我们关注有NULL值的第三行:

    03 01/变长字段长度列表,逆序/

    06/NULL标志位,第三行有NULL值/

    00 00 20 ff 98/记录头信息/

    00 00 00 2b 68 02/RowID/

    00 00 00 00 06 07/TransactionID/

    80 00 00 00 32 01 10/Roll Pointer/

    64/列1数据’d’/

    66 66 66/列4数据’fff’/

    第三行有NULL值,因此NULL标志位不再是00而是06了,转换成二进制为00000110,为1的值即代表了第2列和第3列的数据为NULL,在其后存储列数据的部分,我们会发现没有存储NULL,只存储了第1列和第4列非NULL的值。这个例子很好地说明了:不管是char还是varchar类型,NULL值是不占用存储空间的。

    回到顶部
    Redundant行记录格式
    Redundant是MySQL 5.0版本之前InnoDB的行记录存储方式,MySQL 5.0支持Redundant是为了向前兼容性。Redundant行记录以如下方式存储:

    从上图可以看到,不同于Compact行记录格式,Redundant行格式的首部是一个字段长度偏移列表,同样是按照列的顺序逆序放置的。当列的长度小于255字节,用1字节表示;若大于255个字节,用2个字节表示。第二个部分为记录头信息(record header),不同于Compact行格式,Redundant行格式固定占用6个字节(48位),每位的含义见表4-2。从表中可以看到,n_fields值代表一行中列的数量,占用10位,这也很好地解释了为什么MySQL一个行支持最多的列为1023。另一个需要注意的值为1byte_offs_flags,该值定义了偏移列表占用1个字节还是2个字节。最后的部分就是实际存储的每个列的数据了。

    创建一张和mytest内容完全一样、但行格式为Redundant的表mytest2

    create table mytest2 engine=innodb row_format=redundant as (select * from mytest);

    show table status like ‘mytest2’\G

    select * from mytest2\G

    现在row_format变为Redundant。同样,通过hexdump将表空间mytest2.ibd导出到文本文件mytest2.txt。打开文件,找到类似如下行:

    复制代码
    0000c070 08 03 00 00 73 75 70 72 65 6d 75 6d 00 23 20 16|……supremum.#.
    0000c080 14 13 0c 06 00 00 10 0f 00 ba 00 00 00 2b 68 0b|……+h.
    0000c090 00 00 00 00 06 53 80 00 00 00 32 01 10 61 62 62|……S……2…abb
    0000c0a0 62 62 20 20 20 20 20 20 20 20 63 63 63 23 20 16|bb ccc#.
    0000c0b0 14 13 0c 06 00 00 18 0f 00 ea 00 00 00 2b 68 0c|……+h.
    0000c0c0 00 00 00 00 06 53 80 00 00 00 32 01 1e 64 65 65|……S……2…dee
    0000c0d0 65 65 20 20 20 20 20 20 20 20 66 66 66 21 9e 94|ee fff!…
    0000c0e0 14 13 0c 06 00 00 20 0f 00 74 00 00 00 2b 68 0d|……t……+h.
    0000c0f0 00 00 00 00 06 53 80 00 00 00 32 01 2c 64 00 00|……S……2.,d…
    0000c100 00 00 00 00 00 00 00 00 66 66 66 00 00 00 00 00|……fff……

    整理可以得到如下内容:
    23 20 16 14 13 0c 06/长度偏移列表,逆序/
    00 00 10 0f 00 ba/记录头信息,固定6个字节/
    00 00 00 2b 68 0b/RowID/
    00 00 00 00 06 53/TransactionID/
    80 00 00 00 32 01 10/Roll Point/
    61/列1数据’a’/
    62 62/列2数据’bb’/
    62 62 20 20 20 20 20 20 20 20/列3数据’bb’Char类型/
    63 63 63/列4数据’ccc’/
    复制代码
    23 20 16 14 13 0c 06,逆转为06,0c,13,14,16,20,23。分别代表第一列长度6,第二列长度6(6+6=0x0C),第三列长度为7(6+6+7=0x13),第四列长度1(6+6+7+1=0x14),第五列长度2(6+6+7+1+2=0x16),第六列长度10(6+6+7+1+2+10=0x20),第七列长度3(6+6+7+1+2+10+3=0x23)。

    记录头信息中应该注意48位中22~32位,为0000000111,表示表共有7个列(包含了隐藏的3列),接下去的33位为1,代表偏移列表为一个字节。

    后面的信息就是实际每行存放的数据了,这与Compact行格式大致相同。

    请注意是大致相同,因为如果我们来看第三行,会发现对于NULL的处理两者是不同的。

    21 9e 94 14 13 0c 06/长度偏移列表,逆序/

    00 00 20 0f 00 74/记录头信息,固定6个字节/

    00 00 00 2b 68 0d/RowID/

    00 00 00 00 06 53/TransactionID/

    80 00 00 00 32 01 10/Roll Point/

    64/列1数据’a’/

    00 00 00 00 00 00 00 00 00 00/列3数据NULL/

    66 66 66/列4数据’fff’/

    这里与之前Compact行格式有着很大的不同了,首先来看长度偏移列表,我们逆序排列后得到06 0c 13 14 94 9e 21,前4个值都很好理解,第5个NULL变为了94,接着第6个列char类型的NULL值为9e(94+10=0x9e),之后的21代表14+3=0x21。可以看到对于varchar的NULL值,Redundant行格式同样不占用任何存储空间,因而char类型的NULL值需要占用空间。

    当前表mytest2的字符集为Latin1,每个字符最多只占用1个字节。若这里将表mytest2的字符集转换为utf8,第三列char固定长度类型就不再是只占用10个字节了,而是10×3=30个字节,Redundant行格式下char固定字符类型将会占据可能存放的最大值字节数。

    回到顶部
    Compressed与Dynamic行记录格式
    InnoDB Plugin引入了新的文件格式(file format,可以理解为新的页格式),对于以前支持的Compact和Redundant格式将其称为Antelope文件格式,新的文件格式称为Barracuda。Barracuda文件格式下拥有两种新的行记录格式Compressed和Dynamic两种。新的两种格式对于存放BLOB的数据采用了完全的行溢出的方式,在数据页中只存放20个字节的指针,实际的数据都存放在BLOB Page中,而之前的Compact和Redundant两种格式会存放768个前缀字节。

    下图是Barracuda文件格式的溢出行:

    Compressed行记录格式的另一个功能就是,存储在其中的行数据会以zlib的算法进行压缩,因此对于BLOB、TEXT、VARCHAR这类大长度类型的数据能进行非常有效的存储。

    展开全文
    weixin_42714605 2019-06-28 09:18:16
  • 若要启用特定主题的日志清理,请添加特定于日志的属性: 1、log.cleanup.policy=compact log.cleanup.policy策略属性是在代理服务器中定义的代理配置设置。属性文件;它影响集群中所有没有配置覆盖的主题,如本文所述...

    Kafka是一个基于日志的流处理平台,一个topic可以有多个分区(partition),分区是复制的基本单元,在单节点上,一个分区的数据文件可以存储在多个磁盘目录中,每个分区的日志文件存储的时候又会分成一个个的segment,默认日志段(segment)的大小是1GB,segment是日志清理的基本单元,当前正在使用的segment是不会被清理的。对于每一个kafka partition的日志,以segment为单位,都会被分为两部分,已清理和未清理的部分。同时,未清理的那部分又分为可以清理的和不可清理的。

    日志压缩是一种机制,可以提供细粒度的记录保留,而不是基于粗粒度的基于时间的保留。这个想法是选择性地删除记录,在这里我们有一个最新的更新和相同的主键。这样,日志保证至少在每个键上至少有最后一个状态。

    这个保留策略可以设置每个主题,因此一个单个集群可以有一些主题,在这些主题中,保留由大小或时间和其他主题执行,在那里保留由压缩执行。

    压缩还允许删除。带有键和空有效负载的消息将被视为从日志中删除。这个删除标记将导致删除任何先前带有该键的消息(与任何带有该键的新消息一样),但是删除标记的特殊之处在于,它们将在一段时间后从日志中清除,以释放空间。删除不再保留的时间点在上图中被标记为“删除保留点”。

    注意Log Compaction是针对key的,所以在使用时应注意每个消息的key值不为null。

    压缩是在后台通过周期性地重新打开日志段来完成的。清洗不会阻塞读取,并且可以进行节流,最多使用可配置的I/O吞吐量,以避免影响生产者和消费者。压缩日志段的实际过程是这样的:
    在这里插入图片描述
    日志压缩保证了以下内容:
    1、任何保持在日志头部以内的使用者都将看到所写的每条消息;这些消息将具有顺序偏移量。可以使用主题的min.compact .lag.ms来保证消息在被压缩之前必须经过的最短时间。也就是说,它为每个消息在(未压缩的)头部中停留的时间提供了一个下限。可以使用主题的max.compact .lag.ms来保证从编写消息到消息符合压缩条件之间的最大延迟。
    2、始终保持消息的顺序。压缩永远不会重新排序消息,只是删除一些。
    3、消息的偏移量永远不会更改。它是日志中位置的永久标识符。
    4、从日志开始的任何使用者将至少看到所有记录的最终状态,按记录的写入顺序排列。此外,如果使用者在比主题的delete.retention短的时间内到达日志的头部,则会看到已删除记录的所有delete标记。ms设置(默认为24小时)。换句话说:由于删除标记与读取同时发生,所以如果删除标记的延迟超过delete. retain .ms。

    日志压实细节:
    日志清理器处理日志压缩,这是一个后台线程池,用于重新复制日志段文件,删除其键出现在日志头部的记录。每个压实器线程的工作原理如下:
    1、它选择log head与log tail比率最高的log。
    2、它为日志头部的每个键创建了最后偏移量的简要摘要。
    3、它从头到尾重写日志,删除日志中稍后出现的键。新的、干净的段立即被交换到日志中,因此所需的额外磁盘空间只是一个额外的日志段(不是日志的完整副本)。
    4、日志头的摘要本质上只是一个空间紧凑的哈希表。每个条目只使用24个字节。因此,使用8GB的清理缓冲区,一次清理迭代可以清理大约366GB的日志头(假设是1k消息)。

    配置日志清理器:
    默认情况下启用日志清理器。这将启动干净线程池。若要启用特定主题的日志清理,请添加特定于日志的属性:
    1、log.cleanup.policy=compact
    log.cleanup.policy策略属性是在代理服务器中定义的代理配置设置。属性文件;它影响集群中所有没有配置覆盖的主题,如本文所述。可以将日志清理器配置为保留日志的未压缩“头”的最小数量。这是通过设置压缩时间延迟来启用的。
    2、log.cleaner.min.compaction.lag.ms
    这可以用来防止对更新超过最小消息年龄的消息进行压缩。如果没有设置,除最后一个段(即当前写入的段)外,所有日志段都有资格进行压缩。即使活动段的所有消息都超过最小压缩时间延迟,也不会压缩活动段。可以配置日志清理器以确保最大延迟,在此之后,未压缩的日志“头”才有资格进行日志压缩。
    3、log.cleaner.max.compaction.lag.ms
    这可以用来防止低生产速率的日志在无限制的时间内不适合压缩。如果没有设置,日志不超过min.clean .dirty。比例未压实。注意,这个压缩截止日期并不是硬保证,因为它仍然受到日志清理线程可用性和实际压缩时间的限制。您将需要监视不可清理分区计数、最大清理时间秒和最大压缩延迟秒指标。

    4. log.cleaner.delete.retention.ms 对于压缩日志保留的最长时间,也是客户端消费消息的最长时间(log.retention.ms是针对未compact的日志提供的删除时间, 而且仅针对非活动日志段, 如果一个过期段有一部分过期,那删还是不删???)


    日志保存清理策略

    属性名含义默认值
    log.cleanup.polict日志清理保存的策略只有delete和compact两种delete
    log.retention.hours日志保存的时间,可以选择hours,minutes和ms168(7day)
    log.retention.bytes删除前日志文件允许保存的最大值-1
    log.segment.delete.delay.ms日志文件被真正删除前的保留时间60000
    log.cleanup.interval.mins每隔一段时间多久调用一次清理的步骤10
    log.retention.check.interval.ms周期性检查是否有日志符合删除的条件(新版本使用)300000

    这里特别说明一下,日志的真正清楚时间。当删除的条件满足以后,日志将被“删除”,但是这里的删除其实只是将该日志进行了“delete”标注,文件只是无法被索引到了而已。但是文件本身,仍然是存在的,只有当过了log.segment.delete.delay.ms 这个时间以后,文件才会被真正的从文件系统中删除。

    展开全文
    asdfsadfasdfsa 2020-03-06 22:15:38
  • 默认 3 hbase.regionserver.compaction.enabled 描述 通过设置true / false启用/禁用压缩。 我们可以使用compaction_switch shell命令进一步动态地切换压缩。 默认 true hbase.hstore.flusher.count 描述 刷新线程...

    模糊概念区分
    StoreFile是HFile的外观。在压缩方面,StoreFile的使用似乎在过去很盛行。

    Store与ColumnFamily是同一件事。 StoreFiles与Store或ColumnFamily相关。

    当MemStore达到给定大小(hbase.hregion.memstore.flush.size)时,它将其内容刷新到StoreFile。存储中的StoreFiles数量随时间增加。压缩是一种通过合并存储来减少存储中StoreFile数量的操作,以提高读取操作的性能。压缩可能会占用大量资源,并且取决于许多因素,压缩可能会助长或阻碍性能。

    Compact分为两类:次要和主要。次要和主要压实在以下方面有所不同。

    minor compact通常会选择少量的较小的相邻StoreFile,然后将它们重写为单个StoreFile。由于潜在的副作用,较小的压缩不会丢弃(过滤掉)删除或过期的版本。有关如何处理与压缩有关的删除和版本的信息,请参见压缩和删除以及压缩和版本。较小压缩的最终结果是给定Store的StoreFiles更少,更大。

    Major Compact的最终结果是每个商店只有一个StoreFile。Major Compact还处理删除标记和最大版本。有关如何处理与压缩有关的删除和版本的信息,请参见压缩和删除以及压缩和版本。

    Compaction and Deletions
    在HBase中发生显式删除时,实际上不会删除数据。而是写一个墓碑标记。逻辑删除标记可防止查询返回数据。在大型压缩期间,实际上会删除数据,并从StoreFile中删除逻辑删除标记。如果由于TTL过期而导致删除,则不会创建逻辑删除。相反,过期的数据将被过滤掉,并且不会写回到压缩的StoreFile中。

    压缩和版本
    创建Column Family时,可以通过指定ColumnFamilyDescriptorBuilder.setMaxVersions(int版本)来指定要保留的最大版本数。缺省值为1。如果存在的版本数量超过指定的最大值,则多余的版本将被滤除,并且不会写回到压缩的StoreFile中。

    Major Compact可能会影响查询结果
    在某些情况下,如果明确删除较新的版本,则可能会无意中恢复较旧的版本。有关更深入的说明,请参阅主要压缩更改查询结果。这种情况只有在压实完成之前才有可能。

    从理论上讲,Major Compact可以提高性能。但是,在高负载的系统上,Major Compact可能需要不适当数量的资源,并对性能产生不利影响。在默认配置中,Major Compact将自动计划为每7天运行一次。有时这不适用于生产中的系统。您可以手动管理主要压缩。请参阅托管压缩。

    压缩不执行区域合并。有关区域合并的更多信息,请参见合并。

    Compact开关
    我们可以在区域服务器上打开和关闭compactions。关闭compactions还会中断任何当前正在进行的压缩。可以使用hbase shell中的“ compaction_switch”命令动态地完成此操作。如果从命令行完成,则此设置将在服务器重新启动时丢失。要持久保存跨区域服务器的更改,请修改hbase-site.xml中的配置hbase.regionserver .compaction.enabled并重新启动HBase。

    Cimpaction policy-HBase 0.96.x和更高版本
    compact大型StoreFiles或一次压缩太多StoreFiles可能导致群集无法处理的IO负载,而不会引起性能问题。 HBase选择要包含在压缩中的StoreFiles(以及压缩是次要压缩还是次要压缩)的方法称为压缩策略。

    在HBase 0.96.x之前,只有一种压缩策略。该原始压缩策略仍然可以作为RatioBasedCompactionPolicy使用。新的压缩默认策略ExploringCompactionPolicy随后又移植到HBase 0.94和HBase 0.95,并且是HBase 0.96和更高版本中的默认策略。它在HBASE-7842中实现。简而言之,ExploringCompactionPolicy尝试选择最佳的StoreFiles集以最少的工作量进行压缩,而RatioBasedCompactionPolicy选择符合条件的第一组。

    无论使用哪种压缩策略,文件选择都由几个可配置的参数控制,并且以多步方式进行。这些参数将在上下文中进行解释,然后在一个表中给出,该表显示了它们的描述,默认值以及更改它们的含义。

    Stuck
    当MemStore太大时,它需要将其内容刷新到StoreFile。但是,存储库配置有数量限制,即StoreFiles,hbase.hstore.blockingStoreFiles的数量,并且如果数量过多,则MemStore刷新必须等待,直到StoreFile计数减少一次或多次压缩。如果MemStore太大而StoreFiles的数量也太多,则该算法被称为“卡住”。默认情况下,我们将等待压缩到hbase.hstore.blockingWaitTime毫秒。如果这段时间到期,即使我们超出了hbase.hstore.blockingStoreFiles计数,我们仍然会进行刷新。

    增大hbase.hstore.blockingStoreFiles计数将允许刷新发生,但是包含许多StoreFiles的商店可能具有更高的读取延迟。尝试弄清楚为什么紧缩没有跟上。是导致这种情况的写入突增,还是定期发生,并且群集的写入量配置不足?

    ExploringCompactionPolicy算法在选择压缩最有利的位置之前,先考虑每个可能的相邻StoreFile组。

    ExploringCompactionPolicy效果特别好的一种情况是,当您批量加载数据并且批量加载创建的StoreFiles比StoreFiles更大时,StoreFiles保存的数据早于批量加载的数据。每次需要压缩时,这都会“欺骗” HBase选择执行大型压缩,并导致大量额外开销。借助ExploringCompactionPolicy,大型压缩的发生频率要低得多,因为小型压缩更为有效。

    通常,ExploringCompactionPolicy是大多数情况的正确选择,因此是默认的压缩策略。您还可以将ExploringCompactionPolicy与实验:条带压缩一起使用。

    可以在hbase-server / src / main / java / org / apache / hadoop / hbase / regionserver / compactions / ExploringCompactionPolicy.java中检查此策略的逻辑。以下是ExploringCompactionPolicy的逻辑的逐步介绍。

    列出商店中所有现有的StoreFiles。该算法的其余部分将过滤该列表,以提供将被选择进行压缩的HFiles子集。

    如果这是用户请求的压缩,请尝试执行请求的压缩类型,而不管通常选择哪种压缩类型。注意,即使用户请求进行大压缩,也可能无法进行大压缩。这可能是因为并非列族中的所有StoreFile都可以压缩,或者是因为列族中的存储太多。

    一些StoreFiles会自动排除在考虑范围之外。这些包括:

    大于hbase.hstore.compaction.max.size的StoreFiles

    由批量加载操作(明确排除压缩)创建的StoreFiles。您可以决定从压缩中排除由批量加载产生的StoreFiles。为此,请在批量加载操作期间指定hbase.mapreduce.hfileoutputformat.compaction.exclude参数。

    遍历第1步中的列表,并列出所有可能的StoreFiles集以压缩在一起。可能的集合是列表中hbase.hstore.compaction.min连续StoreFiles的分组。对于每个集合,执行一些健全性检查,并确定这是否是可以完成的最佳压缩:

    如果此集合中的StoreFiles数量(不是StoreFiles的大小)小于hbase.hstore.compaction.min或大于hbase.hstore.compaction.max,请不要考虑它。

    将这组StoreFiles的大小与到目前为止在列表中找到的最小压缩的大小进行比较。如果这组StoreFiles的大小表示可以完成的最小压缩,则在算法“卡住”的情况下存储它以用作备用,否则将不选择任何StoreFiles。见被卡住。

    对这组StoreFiles中的每个StoreFile进行基于大小的完整性检查。

    如果此StoreFile的大小大于hbase.hstore.compaction.max.size,请不要考虑它。

    如果大小大于或等于hbase.hstore.compaction.min.size,请根据基于文件的比率对其进行完整性检查,以查看它是否太大而无法考虑。

    在以下情况下,完整性检查成功:

    此集合中只有一个StoreFile,或者

    对于每个StoreFile,其大小乘以hbase.hstore.compaction.ratio(或hbase.hstore.compaction.ratio.offpeak(如果已配置非高峰时间且处于非高峰时间),则乘以小于该大小的总和集合中其他HFile的集合。

    如果仍在考虑这组StoreFiles,请将其与先前选择的最佳压缩方式进行比较。如果更好,请用此替代以前选择的最佳压实。

    处理完所有可能的压实列表后,执行发现的最佳压实。如果没有选择要压缩的StoreFiles,但是有多个StoreFiles,则假定算法被卡住(请参阅被卡住),如果是,则执行在步骤3中找到的最小压缩。

    几个参数

    hbase.hregion.memstore.flush.size
    

    描述
    如果内存区的大小超过此字节数,则内存区将刷新到磁盘。 值由运行每个hbase.server.thread.wakefrequency的线程检查。

    默认
    134217728 就是大概128M

    hbase.hregion.majorcompaction
    描述
    两次major compact之间的时间,以毫秒为单位。 设置为0以禁用基于时间的自动major compaction。 用户请求的基于大小的major compact仍将运行。 将该值乘以hbase.hregion.majorcompaction.jitter会导致压缩在给定的时间范围内在某个随机时间开始。 默认值为7天,以毫秒为单位。 如果major compact在您的环境中造成破坏,则可以将其配置为在部署的非高峰时间运行,或者通过将此参数设置为0来禁用基于时间的大型压缩,并在cron作业或其他作业中运行major compact外部机制。

    默认
    604800000 就是7天

    hbase.hstore.compactionThreshold
    

    就是每当有3个storeFile就会进行一次压缩.

    描述
    如果在任何一个Store中都存在超过此数目的StoreFile(每次刷新MemStore都会写入一个StoreFile),则会运行压缩以将所有StoreFile重写为一个StoreFile。 较大的值会延迟压缩,但是当确实发生压缩时,则需要更长的时间才能完成。

    默认
    3

    hbase.regionserver.compaction.enabled
    

    描述
    通过设置true / false启用/禁用压缩。 我们可以使用compaction_switch shell命令进一步动态地切换压缩。

    默认
    true

    hbase.hstore.flusher.count
    

    描述
    刷新线程数。 如果线程较少,则将对MemStore刷新进行排队。 如果线程更多,则刷新将并行执行,从而增加了HDFS的负载,并可能导致更多的压缩。

    默认
    2

    hbase.hstore.blockingStoreFiles
    

    就是说StoreFile超过这个数字,16时,这个region就用不了啦,就是不能对外提供服务.
    描述
    如果在任何一个Store中都存在超过此数目的StoreFile(每次刷新MemStore都写入一个StoreFile),则将阻止对此region进行更新,直到压缩完成或超过hbase.hstore.blockingWaitTime。

    默认
    16

    hbase.hstore.blockingWaitTime
    

    描述
    达到hbase.hstore.blockingStoreFiles定义的StoreFile限制后,区域将阻止更新的时间。 经过这段时间后,即使压缩尚未完成,该区域也将停止阻止更新。

    默认
    90000

    hbase.hstore.compaction.min
    

    描述
    运行压缩之前必须符合压缩条件的最小StoreFiles数。 调整hbase.hstore.compaction.min的目标是避免最终产生太多无法压缩的微小StoreFiles。 每次在存储中有两个StoreFiles时,将此值设置为2都会导致较小的压缩,这可能不合适。 如果将此值设置得太高,则所有其他值都需要相应地进行调整。 对于大多数情况,默认值是适当的(此处为空值,根据代码逻辑,结果为3)。 在以前的HBase版本中,参数hbase.hstore.compaction.min被命名为hbase.hstore.compactionThreshold。

    默认
    没有

    hbase.hstore.compaction.max
    

    描述
    无论合格的StoreFiles数量如何,一次较小的压缩将选择的StoreFiles的最大数量。 实际上,hbase.hstore.compaction.max的值控制完成一次压缩的时间长度。 将其设置为更大意味着压缩中将包含更多StoreFiles。 在大多数情况下,默认值为适当。

    默认
    10

    展开全文
    u010711495 2020-11-30 14:50:14
  • weixin_36442042 2020-12-30 22:31:36
  • young_0609 2019-11-01 16:44:12
  • cizhen4018 2008-01-14 15:34:22
  • u010039418 2020-04-01 21:39:00
  • u011095039 2020-12-28 16:59:50
  • u011402289 2019-05-09 14:38:16
  • weixin_39732027 2021-01-19 01:18:11
  • 48KB weixin_38724229 2021-04-11 10:20:55
  • weixin_34029680 2012-11-12 12:03:17
  • qin_zhimou 2014-11-26 16:58:58
  • weixin_34342860 2021-02-03 14:34:25
  • weixin_29084231 2021-01-27 15:27:44
  • lianggx3 2020-09-24 14:38:57
  • weixin_33963189 2017-06-02 10:39:00
  • u013948190 2015-07-15 07:52:21
  • LJFPHP 2019-07-24 16:43:41
  • enginetanmary 2007-08-10 14:53:00
  • az9996 2021-09-22 10:24:13

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,815
精华内容 4,726
关键字:

启用compact