Bitmap续篇-基于Bitmap瞅瞅不一样的Percentile

Hbase的WAL机制 简介WAL(Write-Ahead-Log)预写日志是Hbase的RegionServer在处理数据插入和删除的过程中用来记录操作内容的一种日志。在每次Put、Delete等一条记录时,首先将其数据写入到RegionServer对应的HLog文件中去。客户端向RegionServer端提交数据的时候,会先写入WAL日志,只有当WAL日志写入成功的时候,客户端才会被告诉提交数据成功。如果写WAL失败... 阅读详情

在这里插入图片描述

作者:杨承波
GrowingIO 大数据工程师,主要负责 SaaS 分析和广告模块的技术设计与开发,目前专注于 GrowingIO 物化视图引擎的建设。

本篇文章主要讲解基于 GrowingIO 内部数据存储结构 Bitmap 实现的 Percentile,并简单介绍一下 Hive Percentile,Spark Percentile,Bitmap Percentile 之间的差异。

讲解具体函数算法实现之前,先搞清楚下面两个问题:

  • Percentile 函数【以下简称:分位数】,在实际应用场景下的作用是什么?

  • 今天你是否还想起,Bitmap 是什么东西?

1. 分位数是个什么玩意儿🔢

1.1 分位数

😱分位数是啥?

针对一个从小到大的有序集合,找一个数来将集合按分位对应比例拆解成两个集合。

注意:分位数并非是指数据集合中的某个元素,而是找到一个数来拆解集合

🤔 来点儿晕头转向的东西,90 分位怎么出?

这个数将样本集合分成左右两个集合,而且左边部分的集合占 90%,右边部分占 10%

①元素个数为奇数的集合如何求 90 分位数?

原始集合:【35, 40, 41, 44, 45, 46, 49, 50, 53, 55, 58】

拆解集合:【35, 40, 41, 44, 45, 46, 49, 50, 53】, 55, 【58】

左边集合元素个数:9

右边集合元素个数:1

正好在原始集合中有这个数能将样本按 90 分位比例拆解成两个集合

所以上面样本的 90 分位是 55

②如果换成元素个数为偶数的集合呢?

原始集合:【40, 41, 44, 45, 46, 49, 50, 53, 55, 58】

拆解集合:【40, 41, 44, 45, 46, 49, 50, 53, 55】, X, 【58】

这个数存在于 【55 → 58】

X = 58 - (58 - 55) * 0.9 = 55.3

或 X = 55 + (58 - 55) * (1 - 0.9) = 55.3

90 分位含义:有90%的数据小于等于 55.3,有 10% 的数据大于等于 55.3

1.2 在业务场景中的应用

👉现有【订单支付成功】事件,获取过去七天每个用户做过该事件总次数的 90 分位值,如下图:
在这里插入图片描述
👉还是【订单支付成功】事件,获取昨天每个用户在该事件下实际购买金额的总和,求 75 分位值,如下图:
在这里插入图片描述

2. Percentile 哪家强?

2.1 性能对比

环境准备:Core[16], 内存 2G

对比测试:[基于Bitmap实现的Percentile] VS [SparkSQL内置Percentile_approx]

场景:一定数量的用户以及随机生成对应的count,随机生成分位进行计算分位数,获取百次平均消耗

在这里插入图片描述

x 轴含义: 数据量

y 轴含义: 计算时间, 单位毫秒。

  1. SparkSQL 中 Percentile 仅支持 Int, Long 数据类型,这里为通用考虑,使用 Percentile_approx 进行对比

  2. 以上 Bitmap 存储数据与 Percentile_approx 处理数据完全一致

2.2 Hive Percentile

Hive Sql 中 Percentile 求解时针对的是一列进行操作,即表里的某一个字段,面对动不动几千万的数据处理,如果把每条数据全都加载到内存中,结局只有一个——卡死。

所以 Hive 需要在 UDAF 的计算中将数据进行压缩或预处理,那么 Mapper 是需要在生成时不断通过聚合计算更新,其内部实现基于 histogram。

Hive 的 percentile_approx 实现灵感出自《A Streaming Parallel Decision Tree Algorithm》这篇论文提出 On-line Histogram Building 算法。

什么是 histogram?定义如下:

A histogram is a set of B pairs (called bins) of real numbers {(p1,m1),…,(pB,mB)}, where B is a preset constant integer.

在 histogram 的定义里面,有一个用于标识 bins 数量的常量 B。为何一定要引入这个常量?假设我们有一个简单的 sample 数据集(元素可重复):

[1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9, 10, 10]

其 histogram 为:[(1, 3), (2, 3), (3, 1), (4, 2), (5, 1), (6, 1), (7, 1), (8, 1), (9, 2), (10, 2)]。

可以看出,这个 histogram 内部的 bins(数据点和频率一起构成的 pair) 数组长度实质上就是 sample 数据集的基数(不同元素的个数)。

histogram 的存储开销会随着 sample 数据集的基数线性增长,这意味着如果不做额外的优化,histogram 将无法适应超大规模数据集合的统计需求。常量 B 就是在这种背景下引入的,其目的在于控制 histogram 的 bins 数组长度(内存开销)。

Hive 的 Percentile_approx 由 GenericUDAFPercentileApprox 实现,其核心实现是在 histogram 的 bins 数组前面加上一个用于标识分位点的序列。其 merge 操作结果仅保留 histogram 序列,最后从 histogram 计算结果,源码如下:

/**
   * Gets an approximate quantile value from the current histogram. Some popular
   * quantiles are 0.5 (median), 0.95, and 0.98.
   *
   * @param q The requested quantile, must be strictly within the range (0,1).
   * @return The quantile value.
   */
  public double quantile(double q) {
    assert(bins != null && nusedbins > 0 && nbins > 0);
    double sum = 0, csum = 0;
    int b;
    for(b = 0; b < nusedbins; b++)  {
      sum += bins.get(b).y;
    }
    for(b = 0; b < nusedbins; b++) {
      csum += bins.get(b).y;
      if(csum / sum >= q) {
        if(b == 0) {
          return bins.get(b).x;
        }

        csum -= bins.get(b).y;
        double r = bins.get(b-1).x +
          (q*sum - csum) * (bins.get(b).x - bins.get(b-1).x)/(bins.get(b).y);
        return r;
      }
    }
    return -1; // for Xlint, code will never reach here
  }

2.3 Spark Percentile

  1. Percentile
  • 仅接受 Int, Long,精确计算,底层用 OpenHashMap 计数,然后排序key。

OpenHashMap 为了加快速度,增加了一个假设:

  • 所有数据只插入 Key /更新 Key,不删除 Key。

  • 这个假设在大数据处理/统计的场景下,大多都是成立的。

  • 可以去掉拉链表,使用线性探测的开放定址法来实现哈希表。

OpenHashMap 底层数据为 OpenHashSet,所以本质上是看 OpenHashSet 为啥快。

OpenHashSet 中用 BitSet (位图)来存储是否存在于集合中(位运算),另一个数组存储实际数据,结构如下:

protected var _bitset = new BitSet(_capacity)
protected var _data: Array[T] = _
  _data = new Array[T](_capacity)
  • 俩成员始终保持等长,_bitset 的下标x位置为1时,则 _data 的下标x位置中就有实际数据。

  • 插入数据时,hash(key) 生成 pos,看 _bitset 中对应 pos 是否被占用,有则 ++pos。

OpenHashSet快的原因:

  • 内存利用率高: 去掉了 8B 的指针结构,能够创建更大的哈希表,冲突减少

  • 内存紧凑: 位图操作快

  1. Percentile_approx
    接受 Int, Long, Double,近似计算。使用GK算法。

论文参见《Space-efficient Online Computation of Quantile Summaries》

底层实现通过 QuantileSummaries 实现,主要有两个成员变量:

sample: Array[Stat] : 存放桶,超过1000个桶的时候就压缩(生成新的三元组);
headSampled: ArrayBuffer[Double]:缓冲区,每次达到5000个,就排序后更新到sample.

主要思想是减少空间占用,spark 实现 merge sample 时甚至未处理 samples 已经有序,直接 sortBy:

// TODO: could replace full sort by ordered merge, the two lists are known to be sorted already.
 val res = (sampled ++ other.sampled).sortBy(_.value)
  val comp = compressImmut(res, mergeThreshold = 2 * relativeError * count)
  new QuantileSummaries(other.compressThreshold, other.relativeError, comp, other.count + count)

Stat的定义:

/**
  * Statistics from the Greenwald-Khanna paper.
  * @param value the sampled value
  * @param g the minimum rank jump from the previous value's minimum rank
  * @param delta the maximum span of the rank.
  */
 case class Stats(value: Double, g: Int, delta: Int)

插入函数:每N个数,排序至少1次(merge还有1次),时间复杂度O(NlogN)

def insert(x: Double): QuantileSummaries = {
    headSampled += x
    if (headSampled.size >= defaultHeadSize) {
      val result = this.withHeadBufferInserted
      if (result.sampled.length >= compressThreshold) {
        result.compress()
      } else {
        result
      }
    } else {
      this
    }
  }

获取结果: 时间复杂度O(n)

// Target rank
    val rank = math.ceil(quantile * count).toInt
    val targetError = math.ceil(relativeError * count)
    // Minimum rank at current sample
    var minRank = 0
    var i = 1
    while (i < sampled.length - 1) {
      val curSample = sampled(i)
      minRank += curSample.g
      val maxRank = minRank + curSample.delta
      if (maxRank - targetError <= rank && rank <= minRank + targetError) {
        return Some(curSample.value)
      }
      i += 1
    }

2.4 BitMap 小插曲

干饭人,你是否还记得凯哥之前的分享《GrowingIO基于BitMap的海量数据分析 》

这里只是简单回顾CBitmap和补充一丢丢权重相关的东西

非数值型指标Bitmap怎么存储?

这里只用单个事件 + 单个维度分析,多维度的可参考之前的分享文档,中华传统功夫以点到为止。

在这里插入图片描述
生成CBitmap统计结果

CBitmap: Map(short → Map(dimsSortId → RoaringBitmap(uid)))
在这里插入图片描述

数值型指标Bitmap怎么存储?

上面我们讲述的都是统计的某个指标发生的次数比较小的整数类型数据,那么问题来了:

①当我统计的结果不是个整数呢,换句话说,我们统计的指标是订单金额呢?

②当我统计的结果都是整数,但是吧,有些东西喜欢按”K”作为单位,用你的小脑袋瓜想一想,统计结果中次数从0 → 1024【bit位 0 → 10】就存了个寂寞

计算精度,期望对所有值统计出一个公约数,从而减少存储量,这里引出权重Weight的概念:

例如
  对于 100,200,300, 可以提出一个 100 作为公约数,只保存 1 2 3,
  同理 0.01 0.02 0.03 也可以提出 0.01

以下部分不再详细讲解,有兴趣可以瞅瞅
/**
  * 但是我们实现无法知道数据的分布,只能预估一个值,具体预估流程:
  *   1. 计算一个 high 和 low, high 可以认为是求 log10 + 1,也就是和 1 差的数量级,
  *      low 可以认为是保证精度在 1e-4(精度可以修改) 以内至少要保留的位数,对于整数来说 low = 0
  *   2. 根据所有的 high 和 low,统计一个相对合理的 high 和 low,只要这个 high 对应的数据占比高于平均占比的 1/10 即可
  *   3. high 代表了最大需要将数据放大多少个数量级,low 代表最小可以将数据缩小多少个数量级,
  *      求一个折中值 Math.max(high-n, -1*low) 这里的 n 会影响整数的精度,一开始是 6,后来改为了 7
  *
  * 例如有一系列数字:
  *     10,000 100 10 0.1 0.01
  * 可以求得对应的 high 和 low:
  *     5       3   2  -1  -2
  *     0       0   0   1   2
  * 然后求得合并的 high = 5, low = 2
  * 最后得到 weight = 0.1(n=6), 0.01(n=7)
  *
  * 再举一个极端的例子:
  *     10000...(20个0) 0.00000...1(20个0)
  * 求得的 high 和 low:
  *     21           -21
  *     0             0
  * 求得合并的 high = 21, low = 0
  * 合并得到 weight= 100...(21-7个0)
  */

2.6 Bitmap下实现Percentile

计算逻辑

  1. 将n个变量从小到大排序为数组 x, p 是分位,x[i] 表示 x 数组的第 i 个元素

  2. 设(n - 1) * p% = integerPart + decimalPart,integerPart为整数部分,decimalPart为小数部分,这里的 integerPart 其实是 x 的数组下标,是从0开始的,所以 i = integerPart + 1

  3. 当 decimalPart = 0时,分位数 = x[i]

  4. 当 decimalPart != 0时,分位数 = x[i] + decimalPart * (x[i+1] - x[i])

如果忽略 dimsSortId 的存在,得到一个新的 CBitmap 结构

CBitmap:

Map(short → Map(dimsSortId → RoaringBitmap(uid)))

转化为 Map(short → RoaringBitmap(uid))

之前生成事件指标的Cbitmap如下:

{

1 → {0 → (1), 1 → (1)},

0 → {0 → (2, 3, 4)}

}

转化后的CBitmap如下:

{

1 → (1),

0 → (2, 3, 4)

}

Bitmap 分位数到底咋算

🤔 给点数据,给个需求,先来个简单的,数据如下:

cBitmap = 
{
 3 -> (1001, 1006)
 2 -> (1003, 1005, 1006)
 1 -> (1004)
 0 -> (1001, 1002, 1003)
}
求这个 CBitmap 的 75 分位数?

🤔 把每个用户对应的 cnt 按照顺序拿出来,再按照公式求分位数?

cBitmap转成cnt从小到大排序后的映射关系(uid -> cnt)
【
  (1002 -> 1), 
  (1004 -> 2),
  (1005 -> 4),
  (1003 -> 5),
  (1001 -> 9),
  (1006 -> 12)
】

75分位数求解:
x = (1, 2, 4, 5, 9, 12)
(6 - 1) * 0.75 = 3.75
分位数 = x[i] + decimalPart * (x[i+1] - x[i]) = 5 + 0.75 * (9 - 5) = 8

看似木得问题,实则慢得一匹。。。

从上到下依次遍历每一个 C 位获取每一个用户对应的 cnt,得到 cnt 的排序数组,最后再根据公式才能求出结果。

🤔 简单点儿,求解的方式简单点儿?

既然CBitmap本身就是计次且有序的,为啥不充分利用起来?

对于cbitmap求分位数,前提就是获取排序后第 i 个人和第 i + 1 个人对应的 cnt 数

① 计算终究需要知道 integerPart 是多少?

(6 - 1) * 0.75 = 3.75

i = 3 且有小数部分,需要获取 x[i] 和 x[i+1]

② 由于 cbitmap 中高位的数据一定比低位的数据大,所以 cbitmap 计算第 i 个人可以从高位开始遍历排除数据,拿到第 i 个人的 c 位

  • 先记录几个必要的变量

totalRbm = cbitmap去重后用户集合

currIdx = 当前遍历的c位

currRbm = 当前指针位置对应的 roaringBitmap

persistRbm = 一定是小于当前指针位置的这部分用户 = totalRbm andNot currRbm

preDiscardRbm = 本次遍历准备排除的高位的用户 = totalRbm and currRbm

cBitmap = 
{
 3 -> (1001, 1006)
 2 -> (1003, 1005, 1006)
 1 -> (1004)
 0 -> (1001, 1002, 1003)
}

totalRbm = (1001, 1002, 1003, 1004, 1005, 1006)
currIdx -> currRbm = 3 -> (1001, 1006)
persistRbm = (1002, 1003, 1004, 1005)
preDiscardRbm = (1001, 1006)
  • 排除算法,找到第 i 个用户的c位
  1. 如果 persistRbm 的人数 >= i,说明我们要找的第 i 个人还在 persistRbm 中,并将 persistRbm 置为 totalRbm, currIdx -= 1,重新计算那几个重要变量进入排除算法。

  2. 如果 persistRbm 的人数 < i,说明第 i 个人就在当前的 preDiscardRbm 中,此时需要一个 resCnt 记录当前 currIdx 对应的 count 值【1 << currIdx】,如果之前有值,则需要累加。

    1. 下一步是在 perDiscardRbm 中找到需要的那个人,新的位置 = 之前的 i - persistRbm人数。

    2. 并将 preDiscardRbm 置为 totalRbm, currIdx -= 1,重新计算重要变量进入排除算法。

  3. 遍历完 c 位,即 currIdx = 0 时,累加的 resCnt 即为 x[i] 的结果。

  • 来吧,展示:
    在这里插入图片描述

  • 当还需要获取第 i+1 个位置的用户是否还得重新遍历一次?

将接收变量换成数组,在排除算法中一次遍历获取第 i 个用户和第 i+1 个用户,只需要考虑以下两个情形:

1)当第 i 个用户和第 i+1 个用户在同一 cnt 位上,则后续排除算法的判断逻辑无差异。

2)当出现第 i+1 个用户在 currIdx,而第 i 个用户在 currIdx - 1时,导致 totalRbm 不一致,需要分开进行计算。

  • 最后整合 x[i] 和 x[i+1] 的结果,得到分位数

分位数 = (x[i] + decimalPart * (x[i+1] - x[i])) * weight

总结

本篇主要揭晓基于 BitMap 来作为底层的数据模型实现的 Percentile 算法的优势,Bitmap 的高度压缩在存储方面带来巨大优势的同时,还能根据其数据结构灵活计算统计数据,快速计算许多类似 Percentile 的需求。

BitMap 还有很多的扩展性和亮点,下面列举几个,敬请期待:

  • BitMap 黑科技:避免反序列化使用字节进行 BitMap 运算
  • BitMap 转置算法:不一样的 count 求解方式
  • …

关于 GrowingIO

GrowingIO 是国内领先的一站式数字化增长整体方案服务商。为产品、运营、市场、数据团队及管理者提供客户数据平台、广告分析、产品分析、智能运营等产品和咨询服务,帮助企业在数字化转型的路上,提升数据驱动能力,实现更好的增长。

点击「此处」,获取 GrowingIO 15 天免费试用!

[Hbase] Hbase优化之禁用wal以及Hfile应 1、WAL:write-ahead log 预写日志 灾难恢复,一旦服务器崩溃,通过重放log,即可恢复之前的数据(内存中还没有刷写到磁盘的数据);如果写入wal操作失败,整个操作就认为是失败。 因此,如果开启wal机制,写操作性能会降低; 如果关闭wal机制,数据在内存中未刷写到磁盘时,server突然宕机,产生数据丢失。 解决办法:不开启wal机制,手工刷新memstore的数据... 阅读详情

相关推荐

KiCad自动布线实战:FreeRouting插件安装与使用指南

在PCB设计流程中,布线环节往往占据大量重复性工作,尤其对于中小型双面板,成百上千条飞线的手动连接既繁琐又易出错。自动布线技术通过算法在给定设计规则和元件布局的基础上自动规划走线路径,能显著提升布线效率。FreeRouting作为一款开源自动布线器,与KiCad通过DSN/SES标准中间格式无缝配合,让工程师将精力集中于关键信号和布局优化,而将常规网络交给工具处理。本文从自动布线的原理与边界出发,讲解了FreeRouting的安装、DSN导出、参数设置、自动布线及结果回传的完整流程,并结合实际案例展示了在S

weixin_32025789的博客 278

HBase:Hbase架构以及WAL机制

前言 Hbase是一个分布式、可扩展、支持海量数据存储的NoSQL数据库。当数据量较小时,Hbase的优势不仅体现不出来,反而相比其他传统数据库而言更加消耗性能,但在数据量巨大的情况下,Hbase能达到秒级查询。 Hbase的数据存储于HDFS,HDFS不支持随机写,但一个数据库需要支持增删改查,所以Hbase在底层存储时,实际上是只增不删,每条数据都包含一个时间戳属性,和删除标记,用于判断数据是否有效。 Hbase概念 数据模型 Hbase逻辑上和关系型数据库类似,数据都是存储在一张表中,有行有

啥也不会的博客 2471

微处理器实验报告-实验四

实验四 可编程定时/计数器8253实验 一、实验要求 利用8086外接8253可编程定时/计数器,可以实现方波的产生。 二、实验目的 1、学习8086与8253的连接方法。 2、学习8253的控制方法。 3、掌握8253定时器/计数器的工作方式和编程原理

青竹小轩的博客 5112

(转)HBase WAL简介

【转载原因:解释很清楚】 【转载原文:https://www.jianshu.com/p/65cb8cd81f40】 RegionServer 会将数据保存在内存中(MemStore),直到满足一定条件,将其 flush 到磁盘上。这样可以避免创建很多小文件。内存存储是不稳定的,常见的也是 HBase 使用的解决方案是write-ahead logging(WAL):每次更新操作都会写日志,...

小蚯蚓的博客 1300

Qt+OpenGL+Cesium三件套:打造高性能3D GIS桌面应用的5个关键点

本文深入探讨了如何利用Qt、OpenGL和Cesium数据规范构建高性能桌面级3D GIS应用。文章聚焦于五个关键点:架构选型、OpenGL渲染优化、3D Tiles数据解析与调度、内存与多线程管理,以及高级特性实现,旨在帮助开发者在C++生态中打造不依赖网络、运算能力更强的重型3D地理信息客户端。

weixin_28197941的博客 381

SOI技术解析:绝缘体上硅的结构优势与应用场景

本文深入解析了SOI(绝缘体上硅)技术的核心结构、性能优势与应用场景。SOI通过在硅衬底与器件层之间引入绝缘的埋氧层,实现了优异的电隔离,从而显著降低芯片功耗、提升工作频率并增强抗干扰能力。该技术已广泛应用于5G射频前端、高性能计算、汽车电子及MEMS传感器等关键领域,是推动半导体性能持续提升的重要技术路径。

jj890的博客 403

HBase高级特性:WAL与Snapshot机制

1.背景介绍 HBase是一个分布式、可扩展、高性能的列式存储系统,基于Google的Bigtable设计。HBase提供了一种高效的数据存储和查询方式,可以处理大量数据的读写操作。在HBase中,WAL(Write Ahead Log)和Snapshot机制是两个非常重要的高级特性,它们在HBase的数据持久化和一致性保证方面发挥着重要作用。本文将从以下几个方面进行深入探讨: 背景介绍 核...

AI天才研究院 1478

西门子1200PLC编程实战:OB、FC、FB与DB的深度解析与应用技巧

本文深度解析西门子1200PLC编程中OB、FC、FB与DB四大核心功能块的应用技巧。通过工厂化比喻,阐明OB作为程序总调度、FC作为可重用函数、FB作为带记忆的智能设备以及DB作为数据仓库的角色与关系,并提供实战技巧,帮助工程师构建结构清晰、易于维护的高效PLC程序。

weixin_29280657的博客 441

HBase WAL 解析

WAL(Write-Ahead-Log)是HBase的RegionServer在处理数据插入和删除的过程中用来记录操作内容的一种日志。大致过程如下图所示,首先客户端启动一个操作来修改数据,每一个修改都封装到KeyValue对象实例中,并通过RPC调用发送到含有匹配Region的HRegionServer。一旦KeyValue到达,它们就会被发送管理相应行的HRegion实例。数据被写到WAL,然后被

Kuzury 1万+

Altium Designer应用技巧5: Altium Live账号的获得

为了更好的应用Altium Designer,我们需要得到一个Altium Live账号,但从其英文或者中文官方网站取得,都需要7个工作日的时间,而且对于个人用户来说,并不是100%都能够获取到。本文介绍一种,从俄罗斯Altium官方网站获取账号的方法,可以立即使用。     1、点击http://live.altium-ru.com/#Join网址进入俄罗斯Altium官方网站,Altiu

snmplink的博客 1万+

华为OD机试真题2025双机位B卷 Java&Go 实现【朋友圈个数】

给定一组朋友关系,统计一下该朋友关系网中的朋友圈个数。 朋友圈的定义:一个朋友圈至少由3个朋友组成,且要求同一个朋友圈中的任意两个人都具有直接的朋友关系。 输入描述 输入一个朋友关系列表,如 Fiends =A.B],[A.C],IB,DI,其中的每一个元素 Friendsi表示 Friends[i][0)和 Friends [i][1] 是朋友关系 先输入一个数字 N 代表关系的总数,后面每条关系一行,两个成员以逗号分隔

MISAYAONE的博客 518

HBase之WAL与Flush

WAL实现及拆分、Flush触发

zincooo的博客 862

整理 钢琴 铃木钢琴教程(铃木)

铃木钢琴 超清PDF

TS的博客 1213

HBase 中的 WAL(Write-Ahead Log)是什么?它在数据持久化中的作用是什么?

如需进一步优化性能,可通过调整 WAL 的持久化模式或合并小文件(Log Rolling)来实现。是一种核心机制,用于确保数据的持久性和故障恢复能力。”的机制,平衡了性能与数据安全。WAL 是 HBase 实现数据可靠性的基石,通过“

weixin_45422672的博客 832

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

HBase WAL

预写日志 RegionService内部架构图 预写日志(Write-ahead log,WAL)就是设计来解决宕机之后的操作恢复问题的。数据到达Region的时候是先写入WAL,然后再被加载到Memstore的。就算Region的机器宕掉了,由于WAL的数据是存储在HDFS上的,所以数据并不会丢失。 如何关闭/打开WAL WAL是默认开启的。你可以选择通过调用下面语句: Muta...

初阳 3588

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

HBase中的Write-Ahead Log 详解

HBase 的 WAL 机制是保证数据持久性和系统容错能力的重要组件。通过先写 WAL 再写 MemStore,HBase 确保了系统的高可靠性和一致性。底层的。

goTsHgo的博客 1850

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

hbase 原代码分析 (11) WAL 写日志过程

1) WAL在创建region的时候创建。 2) WAL 存储在HDFS,主要类FSHLog 3) 在put 和delete写入内存之前都会写入WAL,主要是防止机器崩溃时能恢复。 4)用户在协处理器里可以自己调用WALEdit。

chenfenggang的专栏 2679

HBase预写日志WAL机制

预写日志(Write-ahead log,WAL) 最重要的作用是灾难恢复,一旦服务器崩溃,通过重放log,我们可以恢复崩溃之前的数据。如果写入WAL失败,整个操作也将认为失败。 从上图看: 1 客户端对数据执行一个修改操作,如put(),delete(),incr()等。 2 每一个修改被封装到一个KeyValue对象实例,并通过RPC调用发送出来。 3 上述调用成批地发送给含有匹配regio...

Fys的博客 5330

HBase WAL机制

WAL预写日志 客户端向Regionserver提交数据的时候,会优先写WAL日志(Hlog),只有当WAL日志写成功以后,客户端才会告诉提交数据成功,如果写WAL失败则会告诉写数据失败 一个Regionserver上的所有Region共享一个HLog,一次数据的提交是先写WAL,在写metastore 实现了WAL的类叫HLog,当Hregion被实例化时,HLog会被当作一个参数

wang_ying_198的专栏 1288

HBase 预写日志 (WAL)

WAL最重要的作用是灾难恢复,一旦服务器崩溃,通过重放log,我们可以恢复崩溃之前的数据。如果写入WAL失败,整个操作也将认为失败。 图6  WAL   基本流程:首先,客户端初始化一个可能对数据改动的操作,如put(Put),delete(Delete) 和 incrementColumnValue()。这些操作将被封装在一个KeyValue对象实例中,发送给HRegi

mllhxn的专栏 2102

HBase与HDFS之间的WAL(HLog)存储机制答疑解惑

HBase写入流程:第一线程会启动MVCC事务、争夺行锁、写MemeStore缓存、追加本地Log队列缓存、释放行锁、休眠。 第二线程会将本地Log队列缓存写入HDFS,但是缓存在HDFS DataNode尚未落盘。

守护石大数据 1841

MySQL 中的WAL机制

思维导航: 是什么 undo log Redo Log 与 Binlog Redo log 三种状态 redo log 的持久化 Binlog 三种格式 三种状态 binlog 的持久化 两者的联系 状态 Crash-Safe 能力 三步提交的参数配置 组提交优化 " 三步提交 " 三步提交过程总结 三个日志的比较(undo、

qq_40848737的博客 876

HBase的Write Ahead Log (WAL) —— 整体架构、线程模型

解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发、持久化的日志保存与回放机制。每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中。 如果出现HBase服务器宕机,则可以从WAL中回放执行之前没有完成的操作。 本文主要探讨HBase的WAL机制,如何从线程模型、消息机制的层面上,解决这些问题: 1. 由于多个HBase客户端可以对...

weixin_30824599的博客 271

Hbase的wal机制

简介 hbase是基于LSM树的存储系统,它使用日志文件和内存存储来的存储架构将随机写转换成顺序写,以此保证稳定的数据插入速率。而这里说的日志文件即是wal文件,用于在服务器崩溃后回滚还没持久化的数据。 WAL(Write-Ahead-Log)预写日志是Hbase的RegionServer在处理数据插入和删除的过程中用来记录操作内容的一种日志。在每次Put、Delete等一条记录时,首先将...

suojie的博客 1884

HBase的WAL机制

WAL(Write-Ahead-Log)预写日志是HBase的RegionServer在处理数据插入和删除的过程中用来记录操作内容的一种日志。在每次Put、Delete等一条记录时,首先将其数据写入到RegionServer对应的HLog文件的过程。 客户端往RegionServer端提交数据的时候,会先写WAL日志,只有当WAL日志写成功以后,客户端才会被告诉提交数据成功,如果写WAL失败会告知

吃果冻不吐果冻皮 1万+
上一篇: iOS AOP 方案的对比与思考
下一篇: GrowingIO Design 组件库搭建之开发工具
GrowingIO_
博客等级 码龄8年 56粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值