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

给小白演示分库分表案例

8月8日 溷元楼投稿
  受群里小伙伴之邀,搞一个分库分表案例,这样让很多没用过分库分表的心里也有个底,不然永远看到的都是网上的各种概念和解决方案性的文章。需求
  由于用户表过于庞大,采取相关SQL优化,还是不能满足,所以现对其进行做分库分表。
  数据库:mysharding
  数据库表:tuser
  建表语句如下:DROPTABLEIFEXISTSCREATETABLEtuser(idbigintNOTNULLAUTOINCREMENT,usernamevarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULL,ageintNOTNULL,genderintNOTNULL,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT4DEFAULTCHARSETutf8;
  关于数据库分库分表通常有两种方案:垂直拆分水平拆分
  下面我们来演示水平拆分,大致思路:通过tuser表的id进行hash,然后再和数据库个数进行取模,得出对应数据库。
  通过hash值和每个数据库中表的个数进行取模,得出对应表名。创建数据库和表
  加入有2000万条数据,那么为了方便演示,我们就暂定分为五个库,每个数据库对应五个表。理想状态:2000万54,那么每个数据库分得400万,每个表分得80万。
  总之,分库分表后,我们的每一张表的数据库和表都与之前的确实不是一个量级了。
  五个数据库:
  每个数据库有五张表:
  建表语句如下:DROPTABLEIFEXISTStuser0;CREATETABLEtuser0(idbigintNOTNULLAUTOINCREMENT,usernamevarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULL,ageintNOTNULL,genderintNOTNULL,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT4DEFAULTCHARSETutf8;DROPTABLEIFEXISTStuser1;CREATETABLEtuser1(idbigintNOTNULLAUTOINCREMENT,usernamevarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULL,ageintNOTNULL,genderintNOTNULL,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT3DEFAULTCHARSETutf8;DROPTABLEIFEXISTStuser2;CREATETABLEtuser2(idbigintNOTNULLAUTOINCREMENT,usernamevarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULL,ageintNOTNULL,genderintNOTNULL,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT3DEFAULTCHARSETutf8;DROPTABLEIFEXISTStuser3;CREATETABLEtuser3(idbigintNOTNULLAUTOINCREMENT,usernamevarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULL,ageintNOTNULL,genderintNOTNULL,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT8DEFAULTCHARSETutf8;DROPTABLEIFEXISTStuser4;CREATETABLEtuser4(idbigintNOTNULLAUTOINCREMENT,usernamevarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULL,ageintNOTNULL,genderintNOTNULL,PRIMARYKEY(id))ENGINEInnoDBAUTOINCREMENT5DEFAULTCHARSETutf8;项目创建
  使用技术栈:JDK8MySQLSpringBootMybatisShardingsphereDruid
  maven相关依赖:dependencygroupIdorg。springframework。bootgroupIdspringbootstarterwebartifactIddependencydependencygroupIdorg。mybatis。spring。bootgroupIdmybatisspringbootstarterartifactIdversion2。1。0versiondependencydependencygroupIdorg。mybatisgroupIdmybatisartifactIdversion3。5。2versiondependencydependencygroupIdmysqlgroupIdmysqlconnectorjavaartifactIdversion8。0。16versionscoperuntimescopedependencydependencygroupIdcom。github。pagehelpergroupIdpagehelperspringbootstarterartifactIdversion1。2。3versiondependencydependencygroupIdorg。springframework。bootgroupIdspringbootstartertestartifactIdscopetestscopedependencydependencygroupIdorg。apache。shardingspheregroupIdshardingjdbcspringbootstarterartifactIdversion4。0。1versiondependencydependencygroupIdcom。alibabagroupIddruidartifactIdversion1。1。17versiondependencydependencygroupIdcom。google。guavagroupIdguavaartifactIdversion29。0jreversiondependency
  配置文件相关配置如下:server。port9002mybatis。mapperlocationsclasspath:mapper。xmlmybatis。typealiasespackagecom。neutral。idmapping。dbshard。pojo连接池配置过滤器设置(第一个stat很重要,没有的话会监控不到SQL)spring。datasource。druid。filtersstat,wall,log4j2WebStatFilter配置启用StatFilterspring。datasource。druid。webstatfilter。enabledtrue添加过滤规则spring。datasource。druid。webstatfilter。urlpattern排除一些不必要的urlspring。datasource。druid。webstatfilter。exclusions。js,。gif,。jpg,。png,。css,。ico,druid开启session统计功能spring。datasource。druid。webstatfilter。sessionstatenabletrue缺省sessionStatMaxCount是1000个spring。datasource。druid。webstatfilter。sessionstatmaxcount1000spring。datasource。druid。webstatfilter。principalsessionnamespring。datasource。druid。webstatfilter。principalcookienamespring。datasource。druid。webstatfilter。profileenableStatViewServlet配置启用内置的监控页面spring。datasource。druid。statviewservlet。enabledtrue内置监控页面的地址spring。datasource。druid。statviewservlet。urlpatterndruid关闭ResetAll功能spring。datasource。druid。statviewservlet。resetenablefalse设置登录用户名spring。datasource。druid。statviewservlet。loginusernameadmin设置登录密码spring。datasource。druid。statviewservlet。loginpasswordadminspring。shardingsphere。props。sql。showfalse数据库名spring。shardingsphere。datasource。namesdp0,dp1,dp2,dp3,dp4datasourcespring。shardingsphere。datasource。dp0。typecom。alibaba。druid。pool。DruidDataSourcespring。shardingsphere。datasource。dp0。driverclassnamecom。mysql。jdbc。Driverspring。shardingsphere。datasource。dp0。urljdbc:mysql:localhost:3306mysharding0?useUnicodetruecharacterEncodingutf8serverTimeZoneCTTallowPublicKeyRetrievaltrueserverTimezoneUTCspring。shardingsphere。datasource。dp0。usernamerootspring。shardingsphere。datasource。dp0。password123456相同的代码部分这里就不贴了对应dp1、dp2、dp3、dp4和上面dp0配置类似,不一样的就是数据库名字不一样因为我使用的本地创建多个数据库演示的,这里就没有必要重复累赘了actualdatanodes这里是配置所有的库。表的集合比如我这里配置的意思是dp0。data0,dp0。data1,dp0。data2,。。。此缩写方式使用了shardingsphere官方推荐的语法tuser逻辑表名在UserMapper。xml中使用spring。shardingsphere。sharding。tables。tuser。actualdatanodesdp{0。。4}。tuser{0。。4}table设置了以data中字段id作为分表的标准,这样到时候就会将id作为参数传入到下面配置的我们自定义的分表方法中做具体操spring。shardingsphere。sharding。tables。tuser。tablestrategy。standard。shardingcolumnidspring。shardingsphere。sharding。tables。tuser。tablestrategy。standard。precisealgorithmclassnamecom。tian。shardingdemo。common。TableShardingAlgorithmdatabase设置了以data中字段id作为分库的标准,这样到时候就会将id作为参数传入到下面配置的我们自定义的分库方法中做具体操作spring。shardingsphere。sharding。tables。tuser。databasestrategy。standard。shardingcolumnidspring。shardingsphere。sharding。tables。tuser。databasestrategy。standard。precisealgorithmclassnamecom。tian。shardingdemo。common。DbShardingAlgorithm
  分库分表的两个分片类:分库publicclassDbShardingAlgorithmimplementsPreciseShardingAlgorithmLong{privateLoggerloggerLoggerFactory。getLogger(DbShardingAlgorithm。class);OverridepublicStringdoSharding(CollectionStringavailableTargetNames,PreciseShardingValueLongshardingValue){StringdatabaseNameavailableTargetNames。stream()。findFirst()。get();for(StringdbName:availableTargetNames){shardingValue。getValue()就是配置的传入的值我们这里选用的是传入sql中的id字段的值StringtargetDbNamedpgenderToTableSuffix(shardingValue。getValue());if(dbName。equals(targetDbName)){匹配到对应的数据库,比如dp0这个数据库名对应数据源处配置的dp0,dp1,。。。logger。info(数据库名dbName);databaseNamedbN}}returndatabaseN}privateStringgenderToTableSuffix(Longvalue){将id字段的值去hash值后去模运算得到分库的数字(就是一种算法而已)intiHashing。murmur3128(1823977)。newHasher()。putString(String。valueOf(value),Charsets。UTF8)。hash()。asInt();hash与表个数进行取模returnString。valueOf(Math。abs(i)5);}}分表publicclassTableShardingAlgorithmimplementsPreciseShardingAlgorithmLong{privateLoggerloggerLoggerFactory。getLogger(TableShardingAlgorithm。class);OverridepublicStringdoSharding(CollectionStringavailableTargetNames,PreciseShardingValueLongshardingValue){StringtableavailableTargetNames。stream()。findFirst()。get();StringtargetNametusergenderToTableSuffix(shardingValue。getValue());for(StringtableName:availableTargetNames){检查计算出来的表名是否存在if(tableName。equals(targetName)){logger。info(表名tableName);tabletableN}}}privateStringgenderToTableSuffix(Longvalue){算出一个hash值int类型intiHashing。murmur3128(8947189)。newHasher()。putString(String。valueOf(value),Charsets。UTF8)。hash()。asInt();hash与表个数进行取模returnString。valueOf(Math。abs(i)5);}}
  下面是业务部分代码,先看UserMapper。xml内容:?xmlversion1。0encodingUTF8?!DOCTYPEmapperPUBLICmybatis。orgDTDMapper3。0ENhttp:mybatis。orgdtdmybatis3mapper。dtdmappernamespacecom。tian。shardingdemo。mapper。UserMapperresultMapidUsertypecom。tian。shardingdemo。entity。UseridcolumnidpropertyidresultcolumnusernamepropertyuserNameresultMapinsertidinsertINSERTINTOtuser(id,username,age,gender)VALUES({id},{userName},{age},{gender});insertselectidselectUserByIdresultMapUserselectfromtuserwhereiftestid!nullid{id}ifwhereselectupdateidupdateAuthorIfNecessaryupdatetusertrimprefixSETsuffixOverrides,iftestuserName!nullanduserName!username{userName},ififtestgender!nullandgender!0gender{gender},ififtestage!nullandage!0age{age},iftrimwhereid{id}updatemapper
  UserMapper接口:importcom。tian。shardingdemo。entity。Uimportorg。apache。ibatis。annotations。Mimportorg。apache。ibatis。annotations。Pimportorg。springframework。stereotype。RMapperRepositorypublicinterfaceUserMapper{UserselectUserById(Param(id)Longid);intupdateAuthorIfNecessary(Useruser);intinsert(Useruser);}
  为了更好地演示,我这里加入了controller层和service层,这也是大家平常开发套路。
  service层代码如下:publicinterfaceIUserService{UserselectUserById(Longid);voidadd(Longid);}ServicepublicclassUserServiceImplimplementsIUserService{ResourceprivateUserMapperuserMOverridepublicUserselectUserById(Longid){returnuserMapper。selectUserById(id);}Overridepublicvoidadd(Longid){UserusernewUser();user。setAge(22);user。setGender(1);user。setId(id);user。setUserName(tianid);userMapper。insert(user);}}
  controller层代码如下:RestControllerRequestMappingpublicclassUserController{ResourceprivateIUserServiceuserSRequestMapping(valueuser{id},methodRequestMethod。GET)publicUserselectUserById(PathVariable(id)Longid){returnuserService。selectUserById(id);}PostMapping(add)publicObjectadd(RequestBodyMapString,Longparams){Longidparams。get(id);userService。add(id);}}
  最后是项目的启动类:SpringBootApplicationMapperScan({com。tian。shardingdemo。mapper})publicclassShardingDemoApplication{publicstaticvoidmain(String〔〕args){SpringApplication。run(ShardingDemoApplication。class,args);}}
  启动项目,启动成功:
  下面我们来演示一下新增数据和查询。添加数据到数据库中
  先来添加数据到数据库中,这里使用的是IDEA中restful工具:
  后台日志:
  再查看数据库表中:
  到此,我们的数据依旧落库,下面我们来演示一下数据查询。数据查询
  浏览器里输入:http:localhost:9002user7
  返回数据:{id:7,userName:tian7,age:22,gender:1}
  后台日志:
  从日志和返回结果可以看出,已经为我们正确的选择到对应的数据库和表了,这样,一个分库分表的查询就成功了。总结
  本文没有太多的概念,直接使用案例演示。相关概念性的文章,还有分库分表解决方案的文章,网上一堆堆的,感兴趣可以自行查阅。
投诉 评论 转载

中超2022年亚冠4队出炉!中超升班马创奇迹时隔12年回归亚北京时间12月29日,中超第20轮比赛全部结束,因为中超冠军已经诞生,而且广州、海港锁定亚冠席位,因此本轮悬念不大,最后的悬念实际上就是谁能拿走最后一个亚冠席位。最终,亚泰作为……谁是世界杯的奇兵?世界杯是天才和巨星魂牵梦萦的梦幻舞台,本届卡塔尔世界杯自然少不了小鬼当家的剧情,巴西的维尼修斯、英格兰的福登和贝林厄姆、西班牙的佩德里和加维、德国的穆夏拉早就在豪门中挑大梁,甚……国内想要使用TikTok?这些你必须得掌握许多人做外贸的小伙伴在使用TikTok时,老是网络问题打不开,那是因为TikTok对国内用户进行封禁了。那么如果你想要使用TikTok是不是就没有办法了?当然不是,虽然TikT……给小白演示分库分表案例受群里小伙伴之邀,搞一个分库分表案例,这样让很多没用过分库分表的心里也有个底,不然永远看到的都是网上的各种概念和解决方案性的文章。需求由于用户表过于庞大,采取相关SQL优……每日美图文案第十二期电影总是很仁慈,能让错过的人再一次相遇。生活不一样,说过再见的人就再也不见了。我理解你小心翼翼地远离人群,只是因为你曾厚待过他们,他们却辜负了你。我们都是一群多么可……CBA战神刘玉栋退役后曾任八一队领队,如今重新出发身居要职他是国内历史上第一个连续两届奥运会担任旗手的运动员,在中国男篮效力期间,他帮助球队获得过四次亚锦赛冠军、两次亚运会冠军。作为中国男篮黄金一代的标志性人物,他满身荣誉却又伤痕累累……孙俪美到国外去了,白色洞洞装也穿出高级感,真优雅到骨子里头条创作挑战赛穿搭不仅仅体现了我们的审美,还体现了我们对生活的态度,所以我们要注意自己的穿搭。穿搭除了服装的版型、色彩符合自身条件外,最重要的莫过于它的设计了,不同时尚元……秋果之王正上市,每天吃几个,腰好肾好腿脚灵活!别错过俗话说五谷为养,五果为助,又到了一年一度收获板栗的时节。栗子被称为秋果之王,不仅味道鲜美、风味独特、粉质细腻,还是补养良药。01hr吃板栗的好处1养胃健脾《本……安徽石台皖南小众旅游地!自驾天路发现地道美味在最美的季节遇见更多的风景石台县二天一夜线路推荐打卡石台风景、住宿、美食全方位安排!线路名称石台天路穿越之旅线路亮点石台天路全长约65……建筑模拟器万丈高楼平地起,高楼遥遥远眺,远处建筑鳞次栉比作者:小黑盒发霉饼干(原创作者创作不易,希望大家多多关注一下原作者)Hello大家早上好,本期给大家带来一期新游鉴赏《ConstructionSimulator(建筑模拟……6人狂轰113分,山西集体大暴走!张宁225兑现天赋,他该进山西队本赛季的表现,忽高忽低极不稳定!球队之前连续击败青岛、广州、吉林、辽宁取得了一波4连胜,但是在面对缺少多位大将的广厦队时,他们却遭遇了1场33分的惨败,主教练杨学增更是怒……低价才是王道!国产旗舰销量反超苹果手机,价格是苹果手机的一半购买手机你最在意的是什么?配置还是价格?对大部分消费者而言,低价才是王道。以iPhone13ProMax为例,都知道这款手机的配置很顶,性能很强,但在近万元的售价面前,很多消费……
手撕面包像云朵一样柔软,越嚼越香,做法和配方都给你经络穴位,一日一学天枢,腹泻便秘双调节外媒报道,乔尔杰维奇将成为中国男篮主教练,杜锋或面临下课?一到秋天皮肤干燥瘙痒?这份简单实用的抗干痒攻略请收好下赛季恐为顶薪逼宫的五大球星,普尔背水一战,欧文自作自受武僧一龙机会来了!前世界搏击冠军被无名之辈击败,或遭一龙KO新倩女幽魂与追光电影二搭?联动前菜先请大家看电影新神榜杨戬看完笑死这不对劲吧?来自我的世界社区的14张梗图现在的青年人急性心肌梗死为什么是呈高发呢?被阿里收购后,业绩不升反降的几个品牌,有的已官宣停服NBA官网记者评最佳新秀阵容,坎宁安和格林领衔,萨格斯落选20场13球13助攻!范尼调教出一全能中锋,曼联冬窗别再错过

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