安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

0级事故因使用斐波那契散列,做数据库路由算法

6月14日 断龙塔投稿
  作者:小傅哥
  博客:https:bugstack。cn
  源码:https:github。comfuzhengweijavaalgorithms
  沉淀、分享、成长,让自己和他人都能有所收获!
  2022年,大促备战进行中。为了保障系统在流量洪峰下可以稳定运行,其中一条是需要对分库分表的数据库进行扩容,以满足更大体量的业务承载能力。
  但扩容计划并不顺利,因为扩容后的数据并没有如预期散列到不同的库表,而是集中到了数据库的少部分表。扩容失败。经检查,因为这个数据库路由算法并不是公司统一使用的算法,而是研发自己基于斐波那契散列实现的。
  那为什么使用斐波那契散列会出现这样的问题,是斐波那契算法问题?接下来小傅哥就带着大家一起从数学的角度分析下。一、关于斐波那契
  斐波那契的历史
  斐波那契数列出现在印度数学中,与梵文韵律有关。在梵语诗歌传统中,人们对列举所有持续时间为2单位的长(L)音节与1单位持续时间的短(S)音节并列的模式很感兴趣。用给定的总持续时间计算连续L和S的不同模式会产生斐波那契数:持续时间m单位的模式数量是F(m1)。
  斐波那契数列可以由递归关系定义
  F00,F11,FnFn1Fn2
  F0F1F2F3F4F5F6F7F8F9F10F11F12F13F14F15F16F17F18F1901123581321345589144233377610987159725844181从F2开始任意一位都是前两位之和。从F2开始任意一位与前一位相比的比值,都无限趋近于(51)20。618因此基于黄金分割的计算应用,也被称为斐波那契应用。
  那这个就是斐波那契的基本定义和特性,并且基于这样的特性在计算机科学中,斐波那契常用于;伪随机数生成、AVL二叉树、最大公约数、合并排序算法等。
  而大部分程序员包括小傅哥最开始意识到斐波那契的应用则来自于,Java源码ThreadLocal中HASHINCREMENT0x61c88647这样一个常量的定义。因为这用作数据散列的特殊值0x61c88647就是基于黄金分割点计算得来的,公式:(1L32)(long)((1L32)(Math。sqrt(5)1))2。
  那么既然ThreadLocal是基于斐波那契散列计算的下标索引,那为啥数据库路由算法不能使用同样的方式计算散列索引呢?因为通过验证可以得知,斐波那契散列并不满足严格的雪崩标准(SAC)。接下来小傅哥就带着大家一起来使用数据验证下。二、斐波那契计算
  斐波那契数列可以通过循环、递归以及封闭式表达式(比奈公式)的方式进行计算。读者可在单元测试中验证:https:github。comfuzhengweijavaalgorithms1。循环计算publicdoublefibonacci(intn){doublecurrentVal1;doublepreviousVal0;if(n1)return1;intiterationsCountern1;while(iterationsCounter0){currentValpreviousVpreviousValcurrentValpreviousViterationsCounter1;}returncurrentV}2。递归计算publicintfibonacciRecursion(intn){if(n1n2){return1;}else{return(fibonacciRecursion(n1)fibonacciRecursion(n2));}}3。比奈公式publicdoublefibonacciClosedForm(longposition){intmaxPosition75;if(position1positionmaxPosition){thrownewRuntimeException(Canthandlepositionsmallerthan1orgreaterthan75);}doublesqrtMath。sqrt(5);doublephi(1sqrt)2;returnMath。floor((Math。pow(phi,position))sqrt0。5);}
  封闭式表达式:与由具有常数系数的线性递归定义的每个序列一样,斐波那契数具有封闭形式的表达式。它被称为比奈公式,以法国数学家雅克菲利普玛丽比内命名,尽管亚伯拉罕德莫弗和丹尼尔伯努利已经知道它。三、散列函数分类
  散列函数(英语:Hashfunction)又称散列算法、哈希函数,是一种将任意大小的数据映射到固定大小值的计算方式。散列函数计算结果被称为散列值、散列码,也就是对应的HashMap中哈希桶的索引以及数据库中库表的路由信息。
  例如在Java中对数据的散列算法:HashMap用到的是一次扰动函数下的哈希散列、ThreadLocal用到的斐波那契散列。而通常数据库路由组件用到的是整数模除法散列,这也是实践中最简单和最常用的方法之一。
  接下来就给大家介绍这几种常用的散列算法,其他更多散列可以参考HashFunction
  1。除法散列
  在用来设计散列函数的除法散列法中,通过取K除以M的余数,将关键字K映射到M个槽中的某一个位置上,即散列函数为:h(K)KmodM表格大小通常是2的幂。
  另外除法散列的一个显着缺点是除法在大多数现代架构(包括x86)上都是微编程的,并且可能比乘法慢10倍。2。乘法散列
  乘法散列法整体包含两步:用关键字k乘上常数A(0,并去除kA的小数部分用m乘以这个值,再取结果的底floor公式:h(K)Math。floor〔m(aKmod1)〕
  步骤:假设某计算机的字长为ww位,而kk正好可容于一个字中(k2wk2w)现在选取范围〔0,2w〕内的任意数值ss,ksks即可用R12wR0R12wR0来表示因此(kA)mod1ks2w(kA)mod1ks2w就是将ksks整体向右平移ww位,此时R0R0即为小数部分再乘以2m2m相当于左移mm位,散列值h(k)h(k)为R0R0的前m位。
  乘法散列只需要单个整数乘法和右移,使其成为计算速度最快的哈希函数之一。但乘法散列可能会在变更计算因子后,较高值的输入位不会影响较低值的输出位,问题体现在元素分散不均,不满足严格的雪崩标准。所以通常在会进行异或操作
  乘法散列容易受到导致扩散不良的常见错误的影响较高值的输入位不会影响较低值的输出位。在乘法步骤对此进行校正之前,输入上的变换将保留的最高位的跨度向下移动,并将它们异或或加到键上。所以在输入上的变换将保留的最高位的跨度向下移动,并将它们异或操作或者加到键上。例如HashMap的扰动函数。3。斐波那契散列
  其实斐波那契散列是一种特殊形式的乘法散列,只不过它的乘法因子选择的是一个黄金分割比例值,所以叫做斐波那契散列。
  斐波那契散列的特性在于将大数映射到小数的计算结果在表空间上是均匀分布的,且计算满足乘法散列效率高。那为什么并不能使用它作为数据库路由算法呢?四、雪崩标准测试
  在数据库路由实现方面,通常我们都是使用整数模除法散列求模的方式进行元素的索引计算。那既然乘法散列效率高,斐波那契散列分散均匀,为什么不使用这样的方式处理数据库路由算法呢?
  在检索的资料中并没有一个专门的文章来说明这一事项,这也倒置很多在学习过HashMap、ThreadLocal源码的研发人员尝试把这两种源码中的乘法散列算法搬到数据库路由算法中使用。在保证每次扩容数据库表都是2的次幂的情况下,并没有出现什么样的问题。那么对于这样情况下,是否隐藏着什么潜在的风险呢?
  那么为了证实斐波那契散列是否可以用在数据库路由散列算法中,我们可以尝试使用严格雪崩标准(SAC)进行验证测试。
  那么什么是严格雪崩标准(SAC),在密码学中,雪崩效应是密码算法的理想属性,通常是分组密码和密码散列函数,其中如果输入发生轻微变化(例如,翻转单个位),输出会发生显着变化(例如,50输出位翻转)
  SAC建立在完整性和雪崩的概念之上,由Webster和Tavares于1985年引入。SAC的高阶概括涉及多个输入位。满足最高阶SAC的最大非线性函数,也称为完全非线性函数。
  简单来说,当我们对数据库从8库32表扩容到16库32表的时候,每一个表中的数据总量都应该以50的数量进行减少。这样才是合理的。
  好,那么接下来我们就来做下雪崩测试;准备10万个单词用作样本数据。对比测试除法散列、乘法散列、斐波那契散列。基于条件1、2,对数据通过不同的散列算法分两次路由到8库32表和16库32表中,验证每个区间内数据的变化数量,是否在50左右。准备一个excel表,来做数据的统计计算。
  测试代码publicMapInteger,MapInteger,IntegerhashFunction(intdbCount,inttbCount,LonghashIncrementVal,inthashType){intsizedbCounttbCSystem。out。print(库数:dbCount表数:tbCount总值:size幂值:Math。log(size)Math。log(2));intHASHINCREMENT(int)((nullhashIncrementVal?size:hashIncrementVal)(Math。sqrt(5)1)2);System。out。print(黄金分割:HASHINCREMENTsize(double)HASHINCREMENTsize);MapInteger,MapInteger,IntegermapnewConcurrentHashMap();SetStringwordsFileUtil。readWordList(Usersfuzhengwei1024githubjavaalgorithmslogicsrcmainjavamathfibonacci103976个英语单词库。txt);System。out。println(单词总数:words。size()r);for(Stringword:words){intidx0;switch(hashType){散列:斐波那契散列intidx(size1)(word。hashCode()HASHINCREMENTHASHINCREMENT);case0:idx(word。hashCode()HASHINCREMENT)(size1);散列:哈希散列扰动函数case1:idx(size1)(word。hashCode()(word。hashCode()16));散列:哈希散列case2:idx(size1)(word。hashCode()(word。hashCode()16));散列:整数求模case3:idxMath。abs(word。hashCode())}计算路由索引intdbIdxidxtbCount1;inttbIdxidxtbCount(dbIdx1);保存路由结果if(map。containsKey(dbIdx)){MapInteger,IntegerdbCountMapmap。get(dbIdx);if(dbCountMap。containsKey(tbIdx)){dbCountMap。put(tbIdx,dbCountMap。get(tbIdx)1);}else{dbCountMap。put(tbIdx,1);}}else{MapInteger,IntegerdbCountMapnewHashMap();dbCountMap。put(tbIdx,1);map。put(dbIdx,dbCountMap);}}}整个方法的目的在于得出不同的哈希算法,对10万个单词散列到指定的分库分表中,所体现的结果。1。斐波那契散列1。1最小黄金分割
  斐波那契散列也是乘法散列的一种体现形式,只不过它选择了一个黄金分割点作为乘积因子。例如ThreadLocal中的0x61c88647。但如果说我们只是按照一个指定范围长度内做黄金分割计算,并拿这个结果当成乘法散列的因子,那么10万单词将不会均匀的散列到8个库,32张表内。如图:TestpublicvoidtesthashFunction0hashnull(){MapInteger,MapInteger,Integermapfibonacci。hashFunction(8,32,null,0);SetIntegerkeysmap。keySet();for(Integerkey:keys){CollectionIntegervaluesmap。get(key)。values();for(Integerv:values){System。out。print(v);}System。out。println();}}库数:8表数:32总值:256幂值:8。0黄金分割:21474836472568388607。99609375单词总数:103976
  如果你的斐波那契散列值是根据库表的值进行黄金切割的,那么在最初的库表范围较小的阶段,将有部分区域无法使用。这是因为得到的黄金分割点的二进制值没法覆盖整个区域,也就做不到合适的乘法散列计算。参考:https:bugstack。cnmdalgorithmlogicmath20221030bits。html《程序员数学:位运算》1。2最小黄金分割
  基于最小黄金分割的计算,是没法做到均匀散列的。所以你看到的ThreadLocal默认就给你一个0x61c88647而不是随着扩容长度实时计算的切割值。好那么我们接下来也使用这个值来做计算,看看8库到16库后,数据的雪崩结果。TestpublicvoidtesthashFunction0(){MapInteger,MapInteger,Integermapfibonacci。hashFunction(8,32,1L32,0);SetIntegerkeysmap。keySet();for(Integerkey:keys){CollectionIntegervaluesmap。get(key)。values();for(Integerv:values){System。out。print(v);}System。out。println();}}分别测试dbCount8、dbCount16库数:8表数:32总值:512幂值:9。0黄金分割:21474836475124194303。998046875单词总数:103976库数:16表数:32总值:512幂值:9。0黄金分割:21474836475124194303。998046875单词总数:103976
  从8库扩到16库以后,满足50数据变化的,只有2库2表和3库20表。其他数据变化都不满足严格的雪崩测试。1。3任意扩容库表
  通常情况下做分库分表会考虑到以后的扩容操作,那如果说按照2的次幂扩容第一次是8库32表,之后是16库32表,在之后32库32表。那么这样扩容下去,其实是扛不住的。所以大多数时候希望是从8库扩到9库,而不是一下翻倍。那我们来测试下9库32表,斐波那契散列的分散效果。MapInteger,MapInteger,Integermapfibonacci。hashFunction(9,32,1L32,0);SetIntegerkeysmap。keySet();for(Integerkey:keys){CollectionIntegervaluesmap。get(key)。values();for(Integerv:values){System。out。print(v);}System。out。println();}}库数:9表数:32总值:512幂值:9。0黄金分割:21474836475124194303。998046875单词总数:103976
  因为9库不满足2的次幂,也就没法直接乘法散列。所以相当于斐波那契散列失效了。这如果是线上的生产环境,将发生灾难性的事故。2。整数求模散列2。1基础散列计算
  整数求模以数据库表总数为除数,与哈希值的绝对值进行除法散列计算。一般在数据库路由中非常常用。另外如果根据用户ID做散列路由,但由于ID长度波动范围较大,则可以按照指定长度统一切割后使用。TestpublicvoidtesthashFunction3(){MapInteger,MapInteger,Integermapfibonacci。hashFunction(8,32,null,3);SetIntegerkeysmap。keySet();for(Integerkey:keys){CollectionIntegervaluesmap。get(key)。values();for(Integerv:values){System。out。print(v);}System。out。println();}}分别测试dbCount8、dbCount16库数:8表数:32总值:512幂值:9。0黄金分割:21474836475124194303。998046875单词总数:103976库数:16表数:32总值:512幂值:9。0黄金分割:21474836475124194303。998046875单词总数:103976
  在使用除法散列方式后,满足50数据变化的有5个表。看着并不多,但这相当于是斐波那契散列下的3倍。同时其他表数据接近50的也要大于斐波那契散列。2。2任意扩容计算
  接下来我们任意从8库扩容到9库,看看数据的变化。TestpublicvoidtesthashFunction3(){MapInteger,MapInteger,Integermapfibonacci。hashFunction(9,32,null,3);SetIntegerkeysmap。keySet();for(Integerkey:keys){CollectionIntegervaluesmap。get(key)。values();for(Integerv:values){System。out。print(v);}System。out。println();}}库数:9表数:32总值:512幂值:9。0黄金分割:21474836475124194303。998046875单词总数:103976
  103976(932)361,那么也就说扩容后的数据,基本在361范围波动,就满足了均匀散列的目的。所以在数据库散列算法中,除法散列是较靠谱且稳定的。五、常见面试题散列算法有哪些种?HashMap、ThreadLocal、数据库路由都是用了什么散列算法?乘法散列为什么要用2的幂值作为每次的扩容条件?你有了解过0x61c88647是怎么计算的吗?斐波那契散列的使用场景是什么?TheFibonacciAssociation:https:en。wikipedia。orgwikiTheFibonacciAssociation哈希函数:https:en。wikipedia。orgwikiHashfunction斐波那契数:https:en。wikipedia。orgwikiFibonaccinumberMathematics散列函数:https:zh。wikipedia。orgwikiE695A3E58897E587BDE695B8雪崩效应:https:en。wikipedia。orgwikiAvalancheeffectFibonacciHashing:TheOptimizationthattheWorldForgot(or:aBetterAlternativetoIntegerModulo):https:probablydance。com20180616fibonaccihashingtheoptimizationthattheworldforgotorabetteralternativetointegermodulo斐波那契数:https:en。wikipedia。orgwikiFibonaccinumberRelationtothegoldenratioC中具有面向对象设计模式的数据结构和算法:https:book。huihoo。comdatastructuresandalgorithmswithobjectorienteddesignpatternsinchtmlpage214。html
投诉 评论 转载

央行周来袭市场屏息以待行情走势早报现货黄金价格本周重新走低,但下行空间受限。尽管美国三季度GDP恢复增长,且劳动力市场依然强劲,美联储11月份铁定连续第四次加息75个基点。但消费者支出放缓显示……0级事故因使用斐波那契散列,做数据库路由算法作者:小傅哥博客:https:bugstack。cn源码:https:github。comfuzhengweijavaalgorithms沉淀、分享、成长,让……所有女生都该人手一本的护肤工具书美如初见护肤的真相很多女生是不是这样,关注了100个美妆博主,但还是搞不清自己的肤质,很多化妆品成份倒背如流,但还是不会交了很多智商税,并且什么成份在化妆品中能起多少作用并不了解,如果以上的情况……大幂幂,创造了姐就是女王的时代说起杨幂大家应该都陌生,但是大家都是从什么时候认识和知道她的呢?说说我吧,我是在我上小学的时候,偶然看到一部正在热播剧《仙剑三》,看到那个在雪天出生的女孩唐雪见。当时我觉得她可……官宣坏消息!确诊右脚舟骨应力性骨折,他可是湖人最准的外线呀官宣坏消息!确诊右脚舟骨应力性骨折,他可是湖人最准的外线呀!新赛季对于一心想要重返季后赛的洛杉矶湖人而言,可以说很不友好!开赛三场比赛他们无一例外地输球,如今0胜3负垫底……32!兰帕德神了5轮10分掀翻欧冠冠军,创保级奇迹,球迷狂欢本赛季,埃弗顿沦为保级队,在兰帕德的带领下,他们近几轮爆发,5轮比赛拿下10分,击败了欧冠冠军切尔西,以及前英超冠军莱斯特城。对阵水晶宫,埃弗顿则以32的比分获胜,兰帕德的球队……马斯克的星链计划,不单单是一个商业的事情?王建宇院士我们要有要把互联网搬到天上去,这是怎么回事?12月22日,在2022网易未来大会的创新力论坛上,中国著名光电技术专家、中国科学院院士王建宇给出了答案。据王建宇介绍,马斯克提……李春江心仪外援出状况,孙悦最新工作曝光,北京首钢旧将再度爆发李春江执教再遇新阻碍,孙悦最新工作曝光,北京首钢旧将不留情面。上海男篮是本赛季CBA所有球队中表现最令人失望的球队了,在组建了超级豪华的阵容之后球队的战绩却是联盟倒数第二,李春……谁还在用网易严选?导语:陪跑者的孤注一掷出品丨数科社作者丨林木有一种退网叫做罗永浩式退网,有一种退出叫做网易严选式退出。2020年双十一,网易严选凭借着高调退出噱头狠狠收……每日一味抗癌中药淫羊藿,补肾阳效佳!用于阳虚及肾虚型肿瘤淫羊藿小檗科植物淫羊藿、箭叶淫羊藿、巫山淫羊藿和柔毛淫羊藿等的干燥地上部分。产于湖北、西藏东南部、云南、四川和贵州等地。夏秋季茎叶茂盛时采割,除去茎、粗梗及杂质,晒干或阴……东北企业号称亚洲铝王,创始人曾是中国首富,如今负债910亿在2021年,辽宁忠旺精制铝业有限公司由于发展出现困难,经过多方解决,都无法将所面临的问题解决,因此导致旗下三位非执行董事辞职。说到这家铝业公司,其创始人曾经还是我国的首富,然……新闻动态妖神记大电影正式启动新闻动态《妖神记》大电影正式启动美盛2017090818:24美盛动漫、横店影视、若鸿文化正式签署合作协议联手开发《妖神记》大电影今年8月,美盛文化旗下子公司……
本泽马很高兴大罗能亲临颁奖现场,他是我无法企及的高度OPPOReno8Pro斩获多渠道销量冠军,Reno7沦为百体检时若发现颈动脉斑块,需要进行治疗吗?医生告诉你答案新尚居家云赴约活力腕表冰岛某公司招员工,给5万美元搬迁费,一周工作4天,每天拍冰岛荣耀新生代千元5G手机上市,5000mAh22。5W快充,搭什么条件才可以顺产,孕妈妈快看过来干炸里脊用淀粉还是用面粉,教你调糊方法,金黄酥脆,放久也不软物理学家杨振宁百岁了,和小54岁妻子翁帆的爱情让人羡慕提升自我的最好方式走出舒适区建议中年女人裤子最好选九分,到了秋天这样穿,实用保暖又时髦jvc哪个系列的音质好,杰伟世耳机属于什么档次什么原因导致宝宝营养性贫血寒雨连天夜入吴,平明送客楚山孤。意思翻译、赏析孕期焦虑症饮食疗法出租商品房合同诺贝尔和平奖得主莫拉拉为阿富汗姐妹担心游戏早报网传暴雪取消与网易合作开发魔兽MMORPG手游关于独立作文800字议论文职场成功人士的习惯用润滑剂多了会怎样?用润滑剂会有妇科病吗?商界现形记主要内容是什么解析甄子丹的成名往事,和他爱过的3个女人令你我讨厌的小麻烦,却孕育出市值超千亿美金的公司

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利