hash函数

Redis 存储结构设计

99封情书 提交于 2019-11-29 13:52:17
Base 2.8.7 Redis是一个包含了很多Key-Value对的大字典,这个字典支持的Value非常丰富,可以为 字符串、哈希表、列表、集合和有序集 ,基于这些类型丰富的value,扩展出了功能强大的操作,例如hmset、lpush、sadd等 字典 字典是Redis最基础的数据结构,一个字典即一个DB,Redis支持多DB Redis字典采用 Hash表 实现,针对碰撞问题,其采用的方法为 “ 链地址法 ” ,即将多个哈希值相同的节点串连在一起, 从而解决冲突问题。 “链地址法”的问题在于当碰撞剧烈时,性能退化严重,例如:当有n个数据,m个槽位,如果m=1,则整个Hash表退化为链表,查询复杂度O(n) 为了避免Hash碰撞攻击,Redis随机化了Hash表种子 Redis的方案是 “双buffer” ,正常流程使用一个buffer,当发现碰撞剧烈(判断依据为当前槽位数和Key数的对比),分配一个更大的buffer,然后 逐步 将数据从老的buffer迁移到新的buffer。 Redis字典结构如下: typedef struct dict { dictType *type; void *privdata; dictht ht[2]; //双buffer int rehashidx; int iterators; } dict; typedef struct dictht

通过建立hash表快速搜索资源

只愿长相守 提交于 2019-11-29 10:44:36
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. 在做某游戏资源管理时采用了建立hash表来快速索引寻获目标纹理的地址,因为采用了<key,val>(<string,struct>)的结构来标识一个目标,所以想到将key直接转化为地址,到网上搜索了下,最为经典的字符串hash算法是 ELFhash (hash的百科中有介绍) inline unsigned int ELF_hash(wchar_t *name) { unsigned long h = 0, g; while(*name) { h = (h << 4) + *name++; if(g = h & 0xf0000000) h ^= g >> 24; h &= ~g; } return (h%65536); } 建立一个256x256大小的hash表 texlist *texlist_headp[256*256]; 这里的每一个元素是一个链表头指针,为什么使用链表呢

各种字符串Hash函数比较

淺唱寂寞╮ 提交于 2019-11-29 10:44:30
转载自: http://www.byvoid.com/blog/string-hash-compare/ 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法。这些函数使用位运算使得每一个字符都对最后的函数值产生影响。另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎不可能找到碰撞。 常用字符串哈希函数有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等等。对于以上几种哈希函数,我对其进行了一个小小的评测。 Hash函数 数据1 数据2 数据3 数据4 数据1得分 数据2得分 数据3得分 数据4得分 平均分 BKDRHash 2 0 4774 481 96.55 100 90.95 82.05 92.64 APHash 2 3 4754 493 96.55 88.46 100 51.28 86.28 DJBHash 2 2 4975 474 96.55 92.31 0 100 83.43 JSHash 1 4 4761 506 100 84.62 96.83 17.95 81.94 RSHash 1 0 4861 505 100 100 51.58 20.51 75.96 SDBMHash 3 2 4849 504 93.1 92.31 57.01 23.08 72

10道Hadoop面试真题及解题思路

一笑奈何 提交于 2019-11-29 09:26:31
搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。 (一)海量日志数据,提取出某日访问百度次数最多的那个IP。 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中。注意到IP是32位的,最多有个2^32个IP。同样可以采用映射的方法, 比如模1000,把整个大文件映射为1000个小文件,再找出每个小文中出现频率最大的IP(可以采用hash_map进行频率统计,然后再找出频率最大 的几个)及相应的频率。然后再在这1000个最大的IP中,找出那个频率最大的IP,即为所求。 算法思想:分而治之+Hash IP地址最多有2^32=4G种取值情况,所以不能完全加载到内存中处理; 可以考虑采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中。这样,每个小文件最多包含4MB个IP地址; 对于每一个小文件,可以构建一个IP为key,出现次数为value的Hash map,同时记录当前出现次数最多的那个IP地址; 可以得到1024个小文件中的出现次数最多的IP,再依据常规的排序算法得到总体上出现次数最多的IP; (二)搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。 假设目前有一千万个记录(这些查询串的重复度比较高

Hash算法相关

可紊 提交于 2019-11-29 04:57:05
一、散列 散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存入到此存储单元中。检索时,用同样的方法计算地址,然后到相应的单元里去取要找的结点。通过散列方法可以对结点进行快速检索。 按散列存储方式构造的存储结构称为散列表。散列技术的核心是散列函数。散列的核心就是:由散列函数决定关键码值(X.key)与散列地址h(X.key)之间的对应关系,通过这种关系来实现组织存储并进行检索。 二、散列函数 1、除余法 2、乘余取整法 3、平方取中法 4、数字分析法 5、基数转换法 6、折叠法 三、冲突解决 1、分离链表法 2、开放地址法 线性探测法 二次探查法 随机探查法 双散列探查法 来源: https://www.cnblogs.com/kingshine007/p/11455283.html

彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联

邮差的信 提交于 2019-11-29 04:17:17
Java集合类是个非常重要的知识点,HashMap、HashTable、ConcurrentHashMap等算是集合类中的重点,可谓“重中之重”,首先来看个问题,如面试官问你:HashMap和HashTable有什么区别,一个比较简单的回答是: 1、HashMap是非线程安全的,HashTable是线程安全的。 2、HashMap的键和值都允许有null值存在,而HashTable则不行。 3、因为线程安全的问题,HashMap效率比HashTable的要高。 能答出上面的三点,简单的面试,算是过了,但是如果再问:Java中的另一个线程安全的与HashMap极其类似的类是什么?同样是线程安全,它与HashTable在线程同步上有什么不同?能把第二个问题完整的答出来,说明你的基础算是不错的了。带着这个问题,本章开始深入解析HashMap和HashTable类应用而生!总想在文章的开头说点儿什么,但又无从说起。从最近的一些面试说起吧,感受就是:知识是永无止境的,永远不要觉得自己已经掌握了某些东西。如果对哪一块知识感兴趣,那么,请多多的花时间,哪怕最基础的东西也要理解它的原理,尽量往深了研究,在学习的同时,记得多与大家交流沟通,因为也许某些东西,从你自己的角度,是很难发现的,因为你并没有那么多的实验环境去发现他们。只有交流的多了,才能及时找出自己的不足,才能认识到:“哦

分布式架构之缓存系统

两盒软妹~` 提交于 2019-11-29 03:20:45
  一个大型稳健成熟的分布式系统的背后,往往会设计众多的支撑组件,将这些支撑系统成为分布式系统的基础设施。进行系统架构设计所依赖的基础设施,还包括分布式协作及配置管理组件、分布式缓存组件、持久化存储组件、分布式消息系统、搜索引擎、以及CDN系统、负载均衡系统、运维自动化系统等,还有实时计算系统、离线计算系统、分布式文件系统、日志收集系统、监控系统、数据仓库等。此处主要讲讲缓存系统组件。 缓存组件层 缓存系统带来的好处: 加速读写。缓存通常是全内存的,比如Redis、Memcache。对内存的直接读写会比传统的存储层如MySQL,性能好很多。由于单台机器的内存资源和承载能力有限,并且如果大量使用本地缓存,也会使相同的数据被不同的节点存储多份,对内存资源造成较大的浪费,因此才催生出了分布式缓存。 降低后端的负载。在高并发环境下,大量的读、写请求涌向数据库,磁盘的处理速度与内存显然不在一个量级,从减轻数据库的压力和提供系统响应速度两个角度来考虑,一般都会在数据库之前加一层缓存。 缓存系统带来的成本: 数据不一致性:在分布式环境下,数据的读写都是并发的,上游有多个应用,通过一个服务的多个部署(为了保证可用性,一定是部署多份的),对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序,也就是说后发出的读请求很可能先完成(读出脏数据) 代码维护成本:加入缓存后

图解一致性hash算法和实现

◇◆丶佛笑我妖孽 提交于 2019-11-28 21:40:33
更多内容,欢迎关注微信公众号:全菜工程师小辉。公众号回复关键词,领取免费学习资料。 一致性hash算法是什么? 一致性hash算法,是麻省理工学院1997年提出的一种算法,目前主要应用于分布式缓存当中。 一致性hash算法可以有效地解决分布式存储结构下动态增加和删除节点所带来的问题。 在Memcached、Key-Value Store、Bittorrent DHT、LVS中都采用了一致性hash算法,可以说一致性hash算法是分布式系统负载均衡的首选算法。 传统hash算法的弊端 常用的算法是对hash结果取余数 (hash() mod N):对机器编号从0到N-1,按照自定义的hash算法,对每个请求的hash值按N取模,得到余数i,然后将请求分发到编号为i的机器。但这样的算法方法存在致命问题,如果某一台机器宕机,那么应该落在该机器的请求就无法得到正确的处理,这时需要将宕掉的服务器使用算法去除,此时候会有(N-1)/N的服务器的缓存数据需要重新进行计算;如果新增一台机器,会有N /(N+1)的服务器的缓存数据需要进行重新计算。对于系统而言,这通常是不可接受的颠簸(因为这意味着大量缓存的失效或者数据需要转移)。 传统求余做负载均衡算法,缓存节点数由3个变成4个,缓存不命中率为75%。计算方法:穷举hash值为1-12的12个数字分别对3和4取模

HashMap、HashTable 和 ConcurrentHashMap 线程安全问题

大城市里の小女人 提交于 2019-11-28 20:31:00
一、HashMap HashMap 是线程不安全的。 JDK 1.7 HashMap 采用数组 + 链表的数据结构,多线程背景下,在数组扩容的时候,存在 Entry 链死循环和数据丢失问题。 JDK 1.8 HashMap 采用数组 + 链表 + 红黑二叉树的数据结构,优化了 1.7 中数组扩容的方案,解决了 Entry 链死循环和数据丢失问题。但是多线程背景下,put 方法存在数据覆盖的问题。 1.7 中扩容引发的线程不安全分析 void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; if (rehash) { e.hash = null == e.key ? 0 : hash(e.key); } int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } } } 这段代码是 HashMap 的扩容操作,重新定位每个桶的下标,并采用头插法将元素迁移到新数组中。头插法会将链表的顺序翻转

mysql索引

会有一股神秘感。 提交于 2019-11-28 18:22:06
/* 所有MySQL列类型可以被索引。根据存储引擎定义每个表的最大索引数和最大索引长度。 所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。大多数存储引擎有更高的限制。 索引的存储类型目前只有两种(btree和hash),具体和存储引擎模式相关: MyISAM btree InnoDB btree MEMORY/Heap hash,btree 默认情况MEMORY/Heap存储引擎使用hash索引 MySQL的btree索引和hash索引的区别 hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像btree(B-Tree)索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 hash 索引的查询效率要远高于 btree(B-Tree) 索引。 虽然 hash 索引效率高,但是 hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以下这些。 (1)hash 索引仅仅能满足=,<=>,IN,IS NULL或者IS NOT NULL查询,不能使用范围查询。 由于 hash 索引比较的是进行 hash 运算之后的 hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 hash 算法处理之后的 hash 值的大小关系,并不能保证和hash运算前完全一样。 (2)hash 索引无法被用来避免数据的排序操作