1.死磕以太坊源码分析之Fetcher同步
2.PostgreSQL-源码学习笔记(5)-索引
3.String源码分析(1)--哈希篇
4.HashMapå®ç°åç
5.十二点哈希查找的哈希哈希硬件实现(一):哈希查找
6.HashMap实现原理一步一步分析(1-put方法源码整体过程)
死磕以太坊源码分析之Fetcher同步
区块数据同步分为被动同步和主动同步,Fetcher负责被动同步,投注主要任务包括接收新区块广播并进行同步。源码新产生的竞猜区块通过NewBlockHashesMsg 和 NewBlockMsg 进行传播,Fetcher对象通过接收这些消息发现新的哈希哈希区块信息。Fetcher在内部将同步过程分为几个阶段,投注众富源码社区并为每个阶段设置状态字段,源码用于记录阶段数据。竞猜首先同步区块哈希,哈希哈希当接收到哈希时,投注会将哈希标记在远程节点上,源码并在本地数据库中查找是竞猜否存在该哈希,若不存在,哈希哈希则放入unknown列表,投注之后通过channel通知本地fetcher模块请求该区块的源码header和body。fetcher模块根据接收的header和body状态,在fetching和completing列表中进行管理。当确认fetching和completing列表中不存在指定区块哈希时,将哈希放入到announced列表,并准备拉取header和body。fetcher模块通过fetchTimer周期性地从announced列表中选择区块哈希,进行header的拉取。拉取header时,选择要下载的区块,从announced转移到fetching中,并发送下载请求。header请求由远程节点通过GetBlockHeadersMsg处理,并返回给本地节点。header处理包括过滤和通知downloader对象。header过滤主要步骤涉及校验、过滤与本地数据库的不匹配块以及同步算法的header等。过滤后的header放入complete或incomplete列表。body同步的过程涉及从complete列表中选择哈希,进行同步body。body请求通过p.RequestBodies发送GetBlockBodiesMsg消息,圆点指标源码并在downloader对象中处理。body过滤主要涉及过滤和同步逻辑,最终导入完整块到数据库。同步区块哈希和区块的整个流程涉及复杂的机制和逻辑,包括DOS攻击的防范、区块高度的限制、header和body的同步等,最终目标是确保本地区块链与远程节点保持同步状态。
PostgreSQL-源码学习笔记(5)-索引
索引是数据库中的关键结构,它加速了查询速度,尽管会增加内存和维护成本,但效益通常显著。在PG中,索引类型丰富多样,包括B-Tree、Hash、GIST、SP-GIST、GIN和BGIN。所有索引本质上都是独立的数据结构,与数据表并存。
查询时,没有索引会导致全表扫描,效率低下。创建索引可以快速定位满足条件的元组,显著提升查询性能。PG中的索引操作函数,如pg_am中的注册,为上层模块提供了一致的接口,这些函数封装在IndexAmRoutine和IndexScanDesc中。
B-Tree索引采用Lehman和Yao的算法,每个非根节点有兄弟指针,页面包含"high key",用于快速扫描。curl 抓取源码PG的B-Tree构建和维护流程涉及BTBuildState、spool、元页信息等结构,包括创建、插入、扫描等操作。
哈希索引在硬盘上实现,支持故障恢复。它的页面结构复杂,包括元页、桶页、溢出页和位图页。插入和扫描索引元组时,需要动态管理元页缓存以提高效率。
GiST和GIN索引提供了更大的灵活性,支持用户自定义索引方法。GiST适用于通用搜索,而GIN专为复合值索引设计,支持全文搜索。它们在创建时需要实现特定的访问方法和函数。
尽管索引维护有成本,但总体上,它们对提高查询速度的价值不可忽视。了解并有效利用索引是数据库优化的重要环节。
String源码分析(1)--哈希篇
本文基于JDK1.8,从Java中==符号的使用开始,解释了它判断的是对象的内存地址而非内容是否相等。接着,通过分析String类的equals()方法实现,说明了在比较字符串时,应使用equals()而非==,因为equals()方法可以准确判断字符串内容是否相等。
深入探讨了String类作为“值类”的特性,即它需要覆盖Object类的ramdisk源码解读equals()方法,以满足比较字符串时逻辑上相等的需求。同时,强调了在覆盖equals()方法时也必须覆盖hashCode()方法,以确保基于散列的集合(如HashMap、HashSet和Hashtable)可以正常工作。解释了哈希码(hashcode)在将不同的输入映射成唯一值中的作用,以及它与字符串内容的关系。
在分析String类的hashcode()方法时,介绍了计算哈希值的公式,包括使用这个奇素数的原因,以及其在计算性能上的优势。进一步探讨了哈希碰撞的概念及其产生的影响,提出了防止哈希碰撞的有效方法之一是扩大哈希值的取值空间,并介绍了生日攻击这一概念,解释了它如何在哈希空间不足够大时制造碰撞。
最后,总结了哈希碰撞与散列表性能的关系,以及在满足安全与成本之间找到平衡的重要性。提出了确保哈希值的最短长度的考虑因素,并提醒读者在理解和学习JDK源码时,可以关注相关公众号以获取更多源码分析文章。
HashMapå®ç°åç
HashMapå¨å®é å¼åä¸ç¨å°çé¢çé常é«ï¼é¢è¯ä¸ä¹æ¯çç¹ãæ以å³å®åä¸ç¯æç« è¿è¡åæï¼å¸æ对æ³çæºç ç人起å°ä¸äºå¸®å©ï¼çä¹åéè¦å¯¹é¾è¡¨æ¯è¾çæã以ä¸é½æ¯æèªå·±çç解ï¼æ¬¢è¿è®¨è®ºï¼åçä¸å¥½è½»å·ã
HashMapä¸çæ°æ®ç»æ为æ£å表ï¼åååå¸è¡¨ãå¨è¿éæä¼å¯¹æ£å表è¿è¡ä¸ä¸ªç®åçä»ç»ï¼å¨æ¤ä¹åæ们éè¦å å顾ä¸ä¸ æ°ç»ãé¾è¡¨çä¼ç¼ºç¹ã
æ°ç»åé¾è¡¨çä¼ç¼ºç¹åå³äºä»ä»¬åèªå¨å åä¸åå¨ç模å¼ï¼ä¹å°±æ¯ç´æ¥ä½¿ç¨é¡ºåºåå¨æé¾å¼åå¨å¯¼è´çãæ 论æ¯æ°ç»è¿æ¯é¾è¡¨ï¼é½æææ¾ç缺ç¹ãèå¨å®é ä¸å¡ä¸ï¼æ们æ³è¦çå¾å¾æ¯å¯»åãå é¤ãæå ¥æ§è½é½å¾å¥½çæ°æ®ç»æï¼æ£å表就æ¯è¿æ ·ä¸ç§ç»æï¼å®å·§å¦çç»åäºæ°ç»ä¸é¾è¡¨çä¼ç¹ï¼å¹¶å°å ¶ç¼ºç¹å¼±åï¼å¹¶ä¸æ¯å®å ¨æ¶é¤ï¼
æ£å表çåæ³æ¯å°keyæ å°å°æ°ç»çæ个ä¸æ ï¼ååçæ¶åéè¿keyè·åå°ä¸æ ï¼indexï¼ç¶åéè¿ä¸æ ç´æ¥ååãé度æå¿«ï¼èå°keyæ å°å°ä¸æ éè¦ä½¿ç¨æ£åå½æ°ï¼åååå¸å½æ°ã说å°åå¸å½æ°å¯è½æ人已ç»æ³å°äºï¼å¦ä½å°keyæ å°å°æ°ç»çä¸æ ã
å¾ä¸è®¡ç®ä¸æ 使ç¨å°äºä»¥ä¸ä¸¤ä¸ªå½æ°ï¼
å¼å¾æ³¨æçæ¯ï¼ä¸æ 并ä¸æ¯éè¿hashå½æ°ç´æ¥å¾å°çï¼è®¡ç®ä¸æ è¿è¦å¯¹hashå¼åindex()å¤çã
Psï¼å¨æ£å表ä¸ï¼æ°ç»çæ ¼åå«å桶ï¼ä¸æ å«å桶å·ï¼æ¡¶å¯ä»¥å å«ä¸ä¸ªkey-value对ï¼ä¸ºäºæ¹ä¾¿ç解ï¼åæä¸ä¼ä½¿ç¨è¿ä¸¤ä¸ªåè¯ã
以ä¸æ¯åå¸ç¢°æç¸å ³ç说æï¼
以ä¸æ¯ä¸æ å²çªç¸å ³ç说æï¼
å¾å¤äººè®¤ä¸ºåå¸å¼ç碰æåä¸æ å²çªæ¯åä¸ä¸ªä¸è¥¿ï¼å ¶å®ä¸æ¯çï¼å®ä»¬çæ£ç¡®å ³ç³»æ¯è¿æ ·çï¼hashCodeåç碰æï¼åä¸æ ä¸å®å²çªï¼èä¸æ å²çªï¼hashCode并ä¸ä¸å®ç¢°æ
ä¸ææå°ï¼å¨jdk1.8以åHashMapçå®ç°æ¯æ£å表 = æ°ç» + é¾è¡¨ï¼ä½æ¯å°ç®å为æ¢æ们è¿æ²¡æçå°é¾è¡¨èµ·å°çä½ç¨ãäºå®ä¸ï¼HashMapå¼å ¥é¾è¡¨çç¨æå°±æ¯è§£å³ä¸æ å²çªã
ä¸å¾æ¯å¼å ¥é¾è¡¨åçæ£å表ï¼
å¦ä¸å¾æ示ï¼å·¦è¾¹çç«æ¡ï¼æ¯ä¸ä¸ªå¤§å°ä¸ºçæ°ç»ï¼å ¶ä¸åå¨çæ¯é¾è¡¨ç头ç»ç¹ï¼æ们ç¥éï¼æ¥æé¾è¡¨ç头ç»ç¹å³å¯è®¿é®æ´ä¸ªé¾è¡¨ï¼æ以认为è¿ä¸ªæ°ç»ä¸çæ¯ä¸ªä¸æ é½åå¨çä¸ä¸ªé¾è¡¨ãå ¶å ·ä½åæ³æ¯ï¼å¦æåç°ä¸æ å²çªï¼ååæå ¥çèç¹ä»¥é¾è¡¨çå½¢å¼è¿½å å°åä¸ä¸ªèç¹çåé¢ã
è¿ç§ä½¿ç¨é¾è¡¨è§£å³å²çªçæ¹æ³å«åï¼æé¾æ³ï¼åå«é¾å°åæ³ï¼ãHashMap使ç¨çå°±æ¯æé¾æ³ï¼æé¾æ³æ¯å²çªåç以åç解å³æ¹æ¡ã
Qï¼æäºæé¾æ³ï¼å°±ä¸ç¨æ å¿åçå²çªåï¼
Aï¼å¹¶ä¸æ¯ï¼ç±äºå²çªçèç¹ä¼ä¸åçå¨é¾è¡¨ä¸è¿½å ï¼å¤§éçå²çªä¼å¯¼è´å个é¾è¡¨è¿é¿ï¼ä½¿æ¥è¯¢æ§è½éä½ãæ以ä¸ä¸ªå¥½çæ£å表çå®ç°åºè¯¥ä»æºå¤´ä¸åå°å²çªåççå¯è½æ§ï¼å²çªåççæ¦çååå¸å½æ°è¿åå¼çååç¨åº¦æç´æ¥å ³ç³»ï¼å¾å°çåå¸å¼è¶ååï¼å²çªåççå¯è½æ§è¶å°ã为äºä½¿åå¸å¼æ´ååï¼HashMapå é¨åç¬å®ç°äºhash()æ¹æ³ã
以ä¸æ¯æ£å表çåå¨ç»æï¼ä½æ¯å¨è¢«è¿ç¨å°HashMapä¸æ¶è¿æå ¶ä»éè¦æ³¨æçå°æ¹ï¼è¿éä¼è¯¦ç»è¯´æã
ç°å¨æä»¬æ¸ æ¥äºæ£å表çåå¨ç»æï¼ç»å¿ç人åºè¯¥å·²ç»åç°äºä¸ä¸ªé®é¢ï¼Javaä¸æ°ç»çé¿åº¦æ¯åºå®çï¼æ 论åå¸å½æ°æ¯å¦ååï¼éçæå ¥å°æ£å表ä¸æ°æ®çå¢å¤ï¼å¨æ°ç»é¿åº¦ä¸åçæ åµä¸ï¼é¾è¡¨çé¿åº¦ä¼ä¸æå¢å ãè¿ä¼å¯¼è´é¾è¡¨æ¥è¯¢æ§è½ä¸ä½³ç缺ç¹åºç°å¨æ£å表ä¸ï¼ä»è使æ£å表失å»åæ¬çæä¹ã为äºè§£å³è¿ä¸ªé®é¢ï¼HashMapå¼å ¥äºæ©å®¹ä¸è´è½½å åã
以ä¸æ¯åæ©å®¹ç¸å ³çä¸äºæ¦å¿µå解éï¼
Psï¼æ©å®¹è¦éæ°è®¡ç®ä¸æ ï¼æ©å®¹è¦éæ°è®¡ç®ä¸æ ï¼æ©å®¹è¦éæ°è®¡ç®ä¸æ ï¼å 为ä¸æ ç计ç®åæ°ç»é¿åº¦æå ³ï¼é¿åº¦æ¹åï¼ä¸æ ä¹åºå½éæ°è®¡ç®ã
å¨1.8åå ¶ä»¥ä¸çjdkçæ¬ä¸ï¼HashMapåå¼å ¥äºçº¢é»æ ã
红é»æ çå¼å ¥è¢«ç¨äºæ¿æ¢é¾è¡¨ï¼ä¸æ说å°ï¼å¦æå²çªè¿å¤ï¼ä¼å¯¼è´é¾è¡¨è¿é¿ï¼éä½æ¥è¯¢æ§è½ï¼ååçhashå½æ°è½ææçç¼è§£å²çªè¿å¤ï¼ä½æ¯å¹¶ä¸è½å®å ¨é¿å ãæ以HashMapå å ¥äºå¦ä¸ç§è§£å³æ¹æ¡ï¼å¨å¾é¾è¡¨å追å èç¹æ¶ï¼å¦æåç°é¾è¡¨é¿åº¦è¾¾å°8ï¼å°±ä¼å°é¾è¡¨è½¬ä¸ºçº¢é»æ ï¼ä»¥æ¤æåæ¥è¯¢çæ§è½ã
十二点哈希查找的硬件实现(一):哈希查找
一、引子:哈希查找的硬件探索 在数据检索的世界中,哈希查找如同一把神秘的钥匙,以其惊人的效率赢得了广泛应用。它通过键值的直接映射,消除了传统查找方式中对键值区分的繁琐,如在ARP表查询中的高效表现。选择一个合适的哈希函数是关键,如简单的加减乘除、取余运算,甚至位操作,都需要考量元素分布的特性。 二、登录页源码碰撞解决:挑战与策略 然而,哈希查找并非一帆风顺,当多个键值映射到同一个位置时,我们面临碰撞的问题。这可能导致查询结果的不确定性。解决之道有开放定址法、链地址法,甚至还有公共溢出区和再哈希法。开放定址法与链地址法则虽能应对冲突,但时间复杂度有所增加。公共溢出区则需要额外的空间,而再哈希法尽管时间复杂度较低,却不能确保总能找到空闲位置。 三、硬件挑战与突破 在硬件层面实现哈希查找并非易事,它涉及复杂的逻辑设计和性能优化。硬件哈希表结构的比较与选择,将在后续章节中详述。感兴趣的读者可以参考我在gitee上的项目:twelvenine/hashtable-verilog,那里包含了详细的源码和性能测试结果,是我们深入理解哈希查找硬件实现的重要资源。 四、结语:期待你的参与 哈希查找的硬件之旅还在继续,每一步都需要我们深入思考和实践。如果你对这些技术有疑问,或者想要分享你的见解,欢迎在评论区留言,或者通过私信与我交流。让我们一起探索哈希查找在硬件世界中的无限可能。HashMap实现原理一步一步分析(1-put方法源码整体过程)
本文分享了HashMap内部的实现原理,重点解析了哈希(hash)、散列表(hash table)、哈希码(hashcode)以及hashCode()方法等基本概念。
哈希(hash)是将任意长度的输入通过散列算法转换为固定长度输出的过程,建立一一对应关系。常见算法包括MD5加密和ASCII码表。
散列表(hash table)是一种数据结构,通过关键码值映射到表中特定位置进行快速访问。
哈希码(hashcode)是散列表中对象的存储位置标识,用于查找效率。
Object类中的hashCode()方法用于获取对象的哈希码值,以在散列存储结构中确定对象存储地址。
在存储字母时,使用哈希码值对数组大小取模以适应存储范围,防止哈希碰撞。
HashMap在JDK1.7中使用数组+链表结构,而JDK1.8引入了红黑树以优化性能。
HashMap内部数据结构包含数组和Entry对象,数组用于存储Entry对象,Entry对象用于存储键值对。
在put方法中,首先判断数组是否为空并初始化,然后计算键的哈希码值对数组长度取模,用于定位存储位置。如果发生哈希碰撞,使用链表解决。
本文详细介绍了HashMap的存储机制,包括数组+链表的实现方式,以及如何处理哈希碰撞。后续文章将继续深入探讨HashMap的其他特性,如数组长度的优化、多线程环境下的性能优化和红黑树的引入。
Redis7.0源码阅读:哈希表扩容、缩容以及rehash
当哈希值相同发生冲突时,Redis 使用链表法解决,将冲突的键值对通过链表连接,但随着数据量增加,冲突加剧,查找效率降低。负载因子衡量冲突程度,负载因子越大,冲突越严重。为优化性能,Redis 需适时扩容,将新增键值对放入新哈希桶,减少冲突。
扩容发生在 setCommand 部分,其中 dictKeyIndex 获取键值对索引,判断是否需要扩容。_dictExpandIfNeeded 函数执行扩容逻辑,条件包括:不在 rehash 过程中,哈希表初始大小为0时需扩容,或负载因子大于1且允许扩容或负载因子超过阈值。
扩容大小依据当前键值对数量计算,如哈希表长度为4,实际有9个键值对,扩容至(最小的2的n次幂大于9)。子进程存在时,dict_can_resize 为0,反之为1。fork 子进程用于写时复制,确保持久化操作的稳定性。
哈希表缩容由 tryResizeHashTables 判断负载因子是否小于0.1,条件满足则重新调整大小。此操作在数据库定时检查,且无子进程时执行。
rehash 是为解决链式哈希效率问题,通过增加哈希桶数量分散存储,减少冲突。dictRehash 函数完成这一任务,移动键值对至新哈希表,使用位运算优化哈希计算。渐进式 rehash 通过分步操作,减少响应时间,适应不同负载情况。定时任务检测服务器空闲时,进行大步挪动哈希桶。
在 rehash 过程中,数据查询首先在原始哈希表进行,若未找到,则在新哈希表中查找。rehash 完成后,哈希表结构调整,原始表指向新表,新表内容返回原始表,实现 rehash 结果的整合。
综上所述,Redis 通过哈希表的扩容、缩容以及 rehash 动态调整哈希桶大小,优化查找效率,确保数据存储与检索的高效性。这不仅提高了 Redis 的性能,也为复杂数据存储与管理提供了有力支持。
死磕以太坊源码分析之Kademlia算法
Kademlia算法是一种点对点分布式哈希表(DHT),它在复杂环境中保持一致性和高效性。该算法基于异或指标构建拓扑结构,简化了路由过程并确保了信息的有效传递。通过并发的异步查询,系统能适应节点故障,而不会导致用户等待过长。
在Kad网络中,每个节点被视作一棵二叉树的叶子,其位置由ID值的最短前缀唯一确定。节点能够通过将整棵树分割为连续、不包含自身的子树来找到其他节点。例如,节点可以将树分解为以0、、、为前缀的子树。节点通过连续查询和学习,逐步接近目标节点,最终实现定位。每个节点都需知道其各子树至少一个节点,这有助于通过ID值找到任意节点。
判断节点间距离基于异或操作。例如,节点与节点的距离为,高位差异对结果影响更大。异或操作的单向性确保了查询路径的稳定性,不同起始节点进行查询后会逐步收敛至同一路径,减轻热门节点的存储压力,加快查询速度。
Kad路由表通过K桶构建,每个节点保存距离特定范围内的节点信息。K桶根据ID值的前缀划分距离范围,每个桶内信息按最近至最远的顺序排列。K桶大小有限,确保网络负载平衡。当节点收到PRC消息时,会更新相应的K桶,保持网络稳定性和减少维护成本。K桶老化机制通过随机选择节点执行RPC_PING操作,避免网络流量瓶颈。
Kademlia协议包括PING、STORE、FIND_NODE、FIND_VALUE四种远程操作。这些操作通过K桶获得节点信息,并根据信息数量返回K个节点。系统存储数据以键值对形式,BitTorrent中key值为info_hash,value值与文件紧密相关。RPC操作中,接收者响应随机ID值以防止地址伪造,并在回复中包含PING操作校验发送者状态。
Kad提供快速节点查找机制,通过参数调节查找速度。节点x查找ID值为t的节点,递归查询最近的节点,直至t或查询失败。递归过程保证了收敛速度为O(logN),N为网络节点总数。查找键值对时,选择最近节点执行FIND_VALUE操作,缓存数据以提高下次查询速度。
数据存储过程涉及节点间数据复制和更新,确保一致性。加入Kad网络的节点通过与现有节点联系,并执行FIND_NODE操作更新路由表。节点离开时,系统自动更新数据,无需发布信息。Kad协议设计用于适应节点失效,周期性更新数据到最近邻居,确保数据及时刷新。