Merkle 树

图 1.5.6.1 - Merkle 树示例

默克尔树(又叫哈希树)是一种二叉树,由一个根节点、一组中间节点和一组叶节点组成。最下面的叶节点包含存储数据或其哈希值,每个中间节点是它的两个孩子节点内容的哈希值,根节点也是由它的两个子节点内容的哈希值组成。

进一步的,默克尔树可以推广到多叉树的情形。

默克尔树的特点是,底层数据的任何变动,都会传递到其父亲节点,一直到树根。

默克尔树的典型应用场景包括:

  • 快速比较大量数据:当两个默克尔树根相同时,则意味着所代表的数据必然相同。
  • 快速定位修改:例如上例中,如果 D1 中数据被修改,会影响到 N1,N4 和 Root。因此,沿着 Root --> N4 --> N1,可以快速定位到发生改变的 D1;
  • 零知识证明:例如如何证明某个数据(D0……D3)中包括给定内容 D0,很简单,构造一个默克尔树,公布 N0,N1,N4,Root,D0 拥有者可以很容易检测 D0 存在,但不知道其它内容。

摘自:https://yeasy.gitbooks.io/blockchain_guide/content/crypto/merkle_trie.html

假如是 15,16.......30是一个个数据块的hash值,我把这些数据从A传输到B,数据传输到B后,我想验证下传输到B上的数据的有效性型(验证数据是否在传输过程中发生变化),只需要验证A 和 B上所构造的Merkle
 Tree
的root节点值是否一致即可,如果一致,表示数据是有效的,传输过程中没有发生改变。假如在传输过程中,15对应的数据被人篡改,通过Merkle
Tree很容易定位找到(因为此时,节点0,1,3,7,15对应的hash值都发生了变化),定位的时间复杂度为O(log(n))

Merkle Tree的优点

相对于 Hash List,Merkle Tree 的明显的一个好处是可以单独拿出一个分支来(作为一个小树)对部分数据进行校验,这个很多使用场合就带来了哈希列表所不能比拟的方便和高效。

Merkle Hash Tree 简介

上图(来自Wikipedia[1])给出了一个二进制的哈希树(二叉哈希树, 较常用的tiger hash tree也是这个形式). 据称哈希树经常应用在一些分布式系统或者分布式存储中的反熵机制(Anti-entropy),也有称做去熵的.这些应用包括 Amazon的Dynamo 还有Apache的Cassandra数据库, 通过去熵可以去做到各个不同节点的同步, 即保持各个节点的信息都是同步最新.

哈希树的特点很鲜明: 叶子节点存储的是数据文件,而非叶子节点存储的是其子节点的哈希值(称为MessageDigest) 这些非叶子节点的Hash被称作路径哈希值, 叶子节点的Hash值是真实数据的Hash值. 因为使用了树形结构, MT的时间复杂度为 O(logn)

比如下图中, 我们如果使用SHA1算法来做校验值, 比如数据块8对应的哈希值是H23

, 则按照这个路径来看 应该有

H11=SHA1(H23∥H24)
H5=SHA1(H11∥H12)
H2=SHA1(H5∥H6)
H0=SHA1(H1∥H2)

其中 ∥

是表联接的意思.

应用举例

Amazon Dynamo中同步[4]

在Dynamo中,每个节点保存一个范围内的key值,不同节点间存在有相互交迭的key值范围。在去熵操作中,考虑的仅仅是某两个节点间共有的 key值范围。MT的叶子节点即是这个共有的key值范围内每个key的hash,通过叶子节点的hash自底向上便可以构建出一颗MT。Dynamo首 先比对MT根处的hash,如果一致则表示两者完全一致,否则将其子节点交换并继续比较的过程, 知道定位到有差异的数据块. 这种同步方式在分布式中有着节省网络传输量的优点.

摘自:http://yishanhe.net/blog/merkle-hash-tree

Merkle 树——空间换时间,分而治之的hash表,通过根节点是由它的两个子节点内容的哈希值组成来校验数据完整性,定位篡改的数据位置的更多相关文章

  1. Redis学习笔记~关于空间换时间的查询案例

    回到目录 空间与时间 空间换时间是在数据库中经常出现的术语,简单说就是把查询需要的条件进行索引的存储,然后查询时为O(1)的时间复杂度来快速获取数据,从而达到了使用空间存储来换快速的时间响应!对于re ...

  2. Redis基础知识之————空间换时间的查询案例

    空间与时间 空间换时间是在数据库中经常出现的术语,简单说就是把查询需要的条件进行索引的存储,然后查询时为O(1)的时间复杂度来快速获取数据,从而达到了使用空间存储来换快速的时间响应!对于redis这个 ...

  3. 你好,C++(28)用空间换时间 5.2 内联函数 5.3 重载函数

    5.2  内联函数 通过5.1节的学习我们知道,系统为了实现函数调用会做很多额外的幕后工作:保存现场.对参数进行赋值.恢复现场等等.如果函数在程序内被多次调用,且其本身比较短小,可以很快执行完毕,那么 ...

  4. 计数排序(O(n+k)的排序算法,空间换时间)

    计数排序就是利用空间换时间,时间复杂度O(n+k) n是元素个数,k是最大数的个数: 统计每个数比他小的有多少,比如比a[i]小的有x个,那么a[i]应该排在x+1的位置 代码: /* * @Auth ...

  5. JDK1.8 LongAdder 空间换时间: 比AtomicLong还高效的无锁实现

    我们知道,AtomicLong的实现方式是内部有个value 变量,当多线程并发自增,自减时,均通过CAS 指令从机器指令级别操作保证并发的原子性. // setup to use Unsafe.co ...

  6. leetcode-383-Ransom Note(以空间换时间)

    题目描述: Given an arbitrary ransom note string and another string containing letters from all the magaz ...

  7. Elasticsearch实战 | 必要的时候,还得空间换时间!

    1.应用场景 实时数据流通过kafka后,根据业务需求,一部分直接借助kafka-connector入Elasticsearch不同的索引中. 另外一部分,则需要先做聚类.分类处理,将聚合出的分类结果 ...

  8. HDU4548美素数——筛选法与空间换时间

    对于数论的学习比较的碎片化,所以开了一篇随笔来记录一下学习中遇到的一些坑,主要通过题目来讲解 本题围绕:素数筛选法与空间换时间 HDU4548美素数 题目描述 小明对数的研究比较热爱,一谈到数,脑子里 ...

  9. 【C语言学习笔记】空间换时间,查表法的经典例子!知识就是这么学到的~

    我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移植性那些角度. 在我们嵌入式中,我们需要根据实际资源的情况来设计我们的代码.比如当我们能用 ...

随机推荐

  1. linux下常用网页查看下载工具--wget

    http://www.linuxidc.com/Linux/2015-06/118256.htm 5 个基于Linux命令行的文件下载和网站浏览工具 rTorrent.wget.cURL.w3m.El ...

  2. 使用phpize建立php扩展(Cannot find config.m4)

    php源码:/root/soft/php-5.3.4php安装: /usr/local/php [root@ns root]# phpizeCannot find config.m4.Make sur ...

  3. php-fpm重启失败报错

    php-fpm启动命令:/usr/local/php5/sbin/php-fpm 报错:ERROR: unable to bind listening socket for address '127. ...

  4. 九度OJ 1337:寻找最长合法括号序列 (DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:839 解决:179 题目描述: 给你一个长度为N的,由'('和')'组成的括号序列,你能找出这个序列中最长的合法括号子序列么?合法括号序列的 ...

  5. 九度OJ 1001:A+B for Matrices

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:17682 解决:7079 题目描述: This time, you are supposed to find A+B where A and ...

  6. Linux根目录下重要文件夹

    bin存放系统命令的目录,普通用户和超级用户都可以执行,不过放在这里的命令在单用户模式下也可以执行 sbin保存和系统环境设置相关的命令,只有超级用户可以使用这些命令进行系统环境的设置,但有些命令可以 ...

  7. Js格式化json字符串

    var formatJson = function(json, options) { var reg = null, formatted = '', pad = 0, PADDING = ' '; / ...

  8. linux shell 字符串操作详解(获取长度、查找,替换)

    在做shell批处理程序时候,常常会涉及到字符串相关操作.有许多命令语句,如:awk,sed都能够做字符串各种操作. 事实上shell内置一系列操作符号,能够达到相似效果,大家知道,使用内部操作符会省 ...

  9. Shell传参的多种方式

    Shell 传参的多种方式 使用$1 $2 这种类似占位符的方式 # 命令行调用 start.sh 8080 9090 # 脚本中获取 port1=$1 # 8080 port2=$2 # 9090 ...

  10. AbstractQueuedSynchronizer(一)

    应该将子类定义为非公共内部帮助器类,一般并发包类用内部类Sync sync来继承并实现.为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量.事件,等等)提供一个框架.此类的设计目 ...