Allen

写代码是热爱,写到世界充满爱

  • HomePage
  • Categories
  • Archives
  • Essay
  • Tags
总文章数 379
所有文章 友链 关于我

Allen

写代码是热爱,写到世界充满爱

  • HomePage
  • Categories
  • Archives
  • Essay
  • Tags

1-分库分表知多少

阅读数:306次 2018-06-25
字数统计: 10.2k字   |   阅读时长: 36分

文章导航

× 文章目录
  1. 1. 1. 体验一下面试官对于分库分表这个事儿的一个连环炮
  2. 2. 2. 聊一下你们公司是怎么玩儿分库分表的?
    1. 2.1. 1. 面试题
    2. 2.2. 2. 面试官心里分析
    3. 2.3. 3. 面试题剖析
      1. 2.3.1. (1)为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)
      2. 2.3.2. (2)用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?
      3. 2.3.3. (3)你们具体是如何对数据库如何进行垂直拆分或水平拆分的?
  3. 3. 3. 如何把系统不停机迁移到分库分表的?
    1. 3.1. 1. 面试题
    2. 3.2. 2. 面试官心里分析
    3. 3.3. 3. 面试题剖析
      1. 3.3.1. (1)停机迁移方案
      2. 3.3.2. (2)双写迁移方案
  4. 4. 4. 如何设计可以动态扩容缩容的分库分表方案?
    1. 4.1. 1. 面试题
    2. 4.2. 2. 面试官心里分析
    3. 4.3. 3. 面试题剖析
      1. 4.3.1. (1)停机扩容
      2. 4.3.2. (2)优化后的方案
  5. 5. 5. 分库分表之后全局id怎么生成?
    1. 5.1. 1. 面试题
    2. 5.2. 2. 面试官心里分析
    3. 5.3. 3. 面试题剖析
      1. 5.3.1. (1)数据库自增id
      2. 5.3.2. (2)uuid
      3. 5.3.3. (3)获取系统当前时间
      4. 5.3.4. (4)snowflake算法
  6. 6. 6. 说说MySQL读写分离的原理?主从同步延时咋解决?
    1. 6.1. 1. 面试题
    2. 6.2. 2. 面试官心里分析
    3. 6.3. 3. 面试题剖析
      1. 6.3.1. (1)如何实现mysql的读写分离?
      2. 6.3.2. (2)MySQL主从复制原理的是啥?
      3. 6.3.3. (3)mysql主从同步延时问题(精华)

1. 体验一下面试官对于分库分表这个事儿的一个连环炮

(1)为什么要分库分表(设计高并发系统的时候,数据库层面该如何设计)?用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?你们具体是如何对数据库如何进行垂直拆分或水平拆分的?

(2)现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上?

(3)如何设计可以动态扩容缩容的分库分表方案?

(4)分库分表之后,id主键如何处理?

2. 聊一下你们公司是怎么玩儿分库分表的?

1. 面试题

为什么要分库分表(设计高并发系统的时候,数据库层面该如何设计)?用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?你们具体是如何对数据库如何进行垂直拆分或水平拆分的?

2. 面试官心里分析

其实这块肯定是扯到高并发了,因为分库分表一定是为了支撑高并发、数据量大两个问题的。而且现在说实话,尤其是互联网类的公司面试,基本上都会来这么一下,分库分表如此普遍的技术问题,不问实在是不行,而如果你不知道那也实在是说不过去!

3. 面试题剖析

(1)为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)

分库分表的由来

说白了,分库分表是两回事儿,大家可别搞混了,可能是光分库不分表,也可能是光分表不分库,都有可能。我先给大家抛出来一个场景。

假如我们现在是一个小创业公司(或者是一个BAT公司刚兴起的一个新部门),现在注册用户就20万,每天活跃用户就1万,每天单表数据量就1000,然后高峰期每秒钟并发请求最多就10。。。天,就这种系统,随便找一个有几年工作经验的,然后带几个刚培训出来的,随便干干都可以。

结果没想到我们运气居然这么好,碰上个CEO带着我们走上了康庄大道,业务发展迅猛,过了几个月,注册用户数达到了2000万!每天活跃用户数100万!每天单表数据量10万条!高峰期每秒最大请求达到1000!同时公司还顺带着融资了两轮,紧张了几个亿人民币啊!公司估值达到了惊人的几亿美金!这是小独角兽的节奏!

好吧,没事,现在大家感觉压力已经有点大了,为啥呢?因为每天多10万条数据,一个月就多300万条数据,现在咱们单表已经几百万数据了,马上就破千万了。但是勉强还能撑着。高峰期请求现在是1000,咱们线上部署了几台机器,负载均衡搞了一下,数据库撑1000 QPS也还凑合。但是大家现在开始感觉有点担心了,接下来咋整呢。。。。。。

再接下来几个月,我的天,CEO太牛逼了,公司用户数已经达到1亿,公司继续融资几十亿人民币啊!公司估值达到了惊人的几十亿美金,成为了国内今年最牛逼的明星创业公司!天,我们太幸运了。

但是我们同时也是不幸的,因为此时每天活跃用户数上千万,每天单表新增数据多达50万,目前一个表总数据量都已经达到了两三千万了!扛不住啊!数据库磁盘容量不断消耗掉!高峰期并发达到惊人的5000~8000!别开玩笑了,哥。我跟你保证,你的系统支撑不到现在,已经挂掉了!

好吧,所以看到你这里你差不多就理解分库分表是怎么回事儿了,实际上这是跟着你的公司业务发展走的,你公司业务发展越好,用户就越多,数据量越大,请求量越大,那你单个数据库一定扛不住。

比如你单表都几千万数据了,你确定你能抗住么?绝对不行,单表数据量太大,会极大影响你的sql执行的性能,到了后面你的sql可能就跑的很慢了。一般来说,就以我的经验来看,单表到几百万的时候,性能就会相对差一些了,你就得分表了。

分表是啥意思?就是把一个表的数据放到多个表中,然后查询的时候你就查一个表。比如按照用户id来分表,将一个用户的数据就放在一个表中。然后操作的时候你对一个用户就操作那个表就好了。这样可以控制每个表的数据量在可控的范围内,比如每个表就固定在200万以内。

分库是啥意思?就是你一个库一般我们经验而言,最多支撑到并发2000,一定要扩容了,而且一个健康的单库并发值你最好保持在每秒1000左右,不要太大。那么你可以将一个库的数据拆分到多个库中,访问的时候就访问一个库好了。

这就是所谓的分库分表,为啥要分库分表?你明白了吧

(2)用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?

这个其实就是看看你了解哪些分库分表的中间件,各个中间件的优缺点是啥?然后你用过哪些分库分表的中间件。

比较常见的包括:cobar、TDDL、atlas、sharding-jdbc、mycat

cobar:阿里b2b团队开发和开源的,属于proxy层方案。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库join和分页等操作。

TDDL:淘宝团队开发的,属于client层方案。不支持join、多表查询等语法,就是基本的crud语法是ok,但是支持读写分离。目前使用的也不多,因为还依赖淘宝的diamond配置管理系统。

atlas:360开源的,属于proxy层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在5年前了。所以,现在用的公司基本也很少了。

sharding-jdbc:当当开源的,属于client层方案。确实之前用的还比较多一些,因为SQL语法支持也比较多,没有太多限制,而且目前推出到了2.0版本,支持分库分表、读写分离、分布式id生成、柔性事务(最大努力送达型事务、TCC事务)。而且确实之前使用的公司会比较多一些(这个在官网有登记使用的公司,可以看到从2017年一直到现在,是不少公司在用的),目前社区也还一直在开发和维护,还算是比较活跃,个人认为算是一个现在也可以选择的方案。

mycat:基于cobar改造的,属于proxy层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于sharding jdbc来说,年轻一些,经历的锤炼少一些。

所以综上所述,现在其实建议考量的,就是sharding-jdbc和mycat,这两个都可以去考虑使用。

sharding-jdbc这种client层方案的优点在于不用部署,运维成本低,不需要代理层的二次转发请求,性能很高,但是如果遇到升级啥的需要各个系统都重新升级版本再发布,各个系统都需要耦合sharding-jdbc的依赖;

mycat这种proxy层方案的缺点在于需要部署,自己及运维一套中间件,运维成本高,但是好处在于对于各个项目是透明的,如果遇到升级之类的都是自己中间件那里搞就行了。

通常来说,这两个方案其实都可以选用,但是我个人建议中小型公司选用sharding-jdbc,client层方案轻便,而且维护成本低,不需要额外增派人手,而且中小型公司系统复杂度会低一些,项目也没那么多;

但是中大型公司最好还是选用mycat这类proxy层方案,因为可能大公司系统和项目非常多,团队很大,人员充足,那么最好是专门弄个人来研究和维护mycat,然后大量项目直接透明使用即可。

我们,数据库中间件都是自研的,也用过proxy层,后来也用过client层

(3)你们具体是如何对数据库如何进行垂直拆分或水平拆分的?

数据库如何拆分

水平拆分的意思,就是把一个表的数据给弄到多个库的多个表里去,但是每个库的表结构都一样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全部数据。水平拆分的意义,就是将数据均匀放更多的库里,然后用多个库来抗更高的并发,还有就是用多个库的存储容量来进行扩容。

垂直拆分的意思,就是把一个有很多字段的表给拆分成多个表,或者是多个库上去。每个库表的结构都不一样,每个库表都包含部分字段。一般来说,会将较少的访问频率很高的字段放到一个表里去,然后将较多的访问频率很低的字段放到另外一个表里去。因为数据库是有缓存的,你访问频率高的行字段越少,就可以在缓存里缓存更多的行,性能就越好。这个一般在表层面做的较多一些。

这个其实挺常见的,不一定我说,大家很多同学可能自己都做过,把一个大表拆开,订单表、订单支付表、订单商品表。

还有表层面的拆分,就是分表,将一个表变成N个表,就是让每个表的数据量控制在一定范围内,保证SQL的性能。否则单表数据量越大,SQL性能就越差。一般是200万行左右,不要太多,但是也得看具体你怎么操作,也可能是500万,或者是100万。你的SQL越复杂,就最好让单表行数越少。

好了,无论是分库了还是分表了,上面说的那些数据库中间件都是可以支持的。就是基本上那些中间件可以做到你分库分表之后,中间件可以根据你指定的某个字段值,比如说userid,自动路由到对应的库上去,然后再自动路由到对应的表里去。

你就得考虑一下,你的项目里该如何分库分表?一般来说,垂直拆分,你可以在表层面来做,对一些字段特别多的表做一下拆分;水平拆分,你可以说是并发承载不了,或者是数据量太大,容量承载不了,你给拆了,按什么字段来拆,你自己想好;分表,你考虑一下,你如果哪怕是拆到每个库里去,并发和容量都ok了,但是每个库的表还是太大了,那么你就分表,将这个表分开,保证每个表的数据量并不是很大。

而且这儿还有两种分库分表的方式,一种是按照range来分,就是每个库一段连续的数据,这个一般是按比如时间范围来的,但是这种一般较少用,因为很容易产生热点问题,大量的流量都打在最新的数据上了;或者是按照某个字段hash一下均匀分散,这个较为常用。

range来分,好处在于说,后面扩容的时候,就很容易,因为你只要预备好,给每个月都准备一个库就可以了,到了一个新的月份的时候,自然而然,就会写新的库了;缺点,但是大部分的请求,都是访问最新的数据。实际生产用range,要看场景,你的用户不是仅仅访问最新的数据,而是均匀的访问现在的数据以及历史的数据

hash分法,好处在于说,可以平均分配没给库的数据量和请求压力;坏处在于说扩容起来比较麻烦,会有一个数据迁移的这么一个过程

3. 如何把系统不停机迁移到分库分表的?

1. 面试题

现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上?

2. 面试官心里分析

你看看,你现在已经明白为啥要分库分表了,你也知道常用的分库分表中间件了,你也设计好你们如何分库分表的方案了(水平拆分、垂直拆分、分表),那问题来了,你接下来该怎么把你那个单库单表的系统给迁移到分库分表上去?

所以这都是一环扣一环的,就是看你有没有全流程经历过这个过程

友情提示

假设,你现有有一个单库单表的系统,在线上在跑,假设单表有600万数据

3个库,每个库里分了4个表,每个表要放50万的数据量

假设你已经选择了一个分库分表的数据库中间件,sharding-jdbc,mycat,都可以

你怎么把线上系统平滑地迁移到分库分表上面去

sharding-jdbc:自己上官网,找一个官网最基本的例子,自己写一下,试一下,跑跑看,是非常简单的

mycat:自己上官网,找一个官网最基本的例子,自己写一下,试一下看看

1个小时以内就可以搞定了

3. 面试题剖析

这个其实从low到高大上有好几种方案

(1)停机迁移方案

长时间停机分库分表

我先给你说一个最low的方案,就是很简单,大家伙儿凌晨12点开始运维,网站或者app挂个公告,说0点到早上6点进行运维,无法访问。。。。。。

接着到0点,停机,系统挺掉,没有流量写入了,此时老的单库单表数据库静止了。然后你之前得写好一个导数的一次性工具,此时直接跑起来,然后将单库单表的数据哗哗哗读出来,写到分库分表里面去。

导数完了之后,就ok了,修改系统的数据库连接配置啥的,包括可能代码和SQL也许有修改,那你就用最新的代码,然后直接启动连到新的分库分表上去。

验证一下,ok了,完美,大家伸个懒腰,看看看凌晨4点钟的北京夜景,打个滴滴回家吧

但是这个方案比较low,谁都能干,我们来看看高大上一点的方案

(2)双写迁移方案

不停机双写方案

这个是我们常用的一种迁移方案,比较靠谱一些,不用停机,不用看北京凌晨4点的风景

简单来说,就是在线上系统里面,之前所有写库的地方,增删改操作,都除了对老库增删改,都加上对新库的增删改,这就是所谓双写,同时写俩库,老库和新库。

然后系统部署之后,新库数据差太远,用之前说的导数工具,跑起来读老库数据写新库,写的时候要根据gmt_modified这类字段判断这条数据最后修改的时间,除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。

接着导万一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。反复循环,直到两个库每个表的数据都完全一致为止。

接着当数据完全一致了,就ok了,基于仅仅使用分库分表的最新代码,重新部署一次,不就仅仅基于分库分表在操作了么,还没有几个小时的停机时间,很稳。所以现在基本玩儿数据迁移之类的,都是这么干了。

4. 如何设计可以动态扩容缩容的分库分表方案?

1. 面试题

如何设计可以动态扩容缩容的分库分表方案?

2. 面试官心里分析

(1)选择一个数据库中间件,调研、学习、测试

(2)设计你的分库分表的一个方案,你要分成多少个库,每个库分成多少个表,3个库每个库4个表

(3)基于选择好的数据库中间件,以及在测试环境建立好的分库分表的环境,然后测试一下能否正常进行分库分表的读写

(4)完成单库单表到分库分表的迁移,双写方案

(5)线上系统开始基于分库分表对外提供服务

(6)扩容了,扩容成6个库,每个库需要12个表,你怎么来增加更多库和表呢?

这个是你必须面对的一个事儿,就是你已经弄好分库分表方案了,然后一堆库和表都建好了,基于分库分表中间件的代码开发啥的都好了,测试都ok了,数据能均匀分布到各个库和各个表里去,而且接着你还通过双写的方案咔嚓一下上了系统,已经直接基于分库分表方案在搞了。

那么现在问题来了,你现在这些库和表又支撑不住了,要继续扩容咋办?这个可能就是说你的每个库的容量又快满了,或者是你的表数据量又太大了,也可能是你每个库的写并发太高了,你得继续扩容。

这都是玩儿分库分表线上必须经历的事儿

3. 面试题剖析

(1)停机扩容

这个方案就跟停机迁移一样,步骤几乎一致,唯一的一点就是那个导数的工具,是把现有库表的数据抽出来慢慢倒入到新的库和表里去。但是最好别这么玩儿,有点不太靠谱,因为既然分库分表就说明数据量实在是太大了,可能多达几亿条,甚至几十亿,你这么玩儿,可能会出问题。

从单库单表迁移到分库分表的时候,数据量并不是很大,单表最大也就两三千万

写个工具,多弄几台机器并行跑,1小时数据就导完了

3个库+12个表,跑了一段时间了,数据量都1亿~2亿了。光是导2亿数据,都要导个几个小时,6点,刚刚导完数据,还要搞后续的修改配置,重启系统,测试验证,10点才可以搞完

(2)优化后的方案

一开始上来就是32个库,每个库32个表,1024张表

我可以告诉各位同学说,这个分法,第一,基本上国内的互联网肯定都是够用了,第二,无论是并发支撑还是数据量支撑都没问题

每个库正常承载的写入并发量是1000,那么32个库就可以承载32 * 1000 = 32000的写并发,如果每个库承载1500的写并发,32 * 1500 = 48000的写并发,接近5万/s的写入并发,前面再加一个MQ,削峰,每秒写入MQ 8万条数据,每秒消费5万条数据。

有些除非是国内排名非常靠前的这些公司,他们的最核心的系统的数据库,可能会出现几百台数据库的这么一个规模,128个库,256个库,512个库

1024张表,假设每个表放500万数据,在MySQL里可以放50亿条数据

每秒的5万写并发,总共50亿条数据,对于国内大部分的互联网公司来说,其实一般来说都够了

谈分库分表的扩容,第一次分库分表,就一次性给他分个够,32个库,1024张表,可能对大部分的中小型互联网公司来说,已经可以支撑好几年了

一个实践是利用32 * 32来分库分表,即分为32个库,每个库里一个表分为32张表。一共就是1024张表。根据某个id先根据32取模路由到库,再根据32取模路由到库里的表。

刚开始的时候,这个库可能就是逻辑库,建在一个数据库上的,就是一个mysql服务器可能建了n个库,比如16个库。后面如果要拆分,就是不断在库和mysql服务器之间做迁移就可以了。然后系统配合改一下配置即可。

比如说最多可以扩展到32个数据库服务器,每个数据库服务器是一个库。如果还是不够?最多可以扩展到1024个数据库服务器,每个数据库服务器上面一个库一个表。因为最多是1024个表么。

这么搞,是不用自己写代码做数据迁移的,都交给dba来搞好了,但是dba确实是需要做一些库表迁移的工作,但是总比你自己写代码,抽数据导数据来的效率高得多了。

哪怕是要减少库的数量,也很简单,其实说白了就是按倍数缩容就可以了,然后修改一下路由规则。

对2 ^ n取模

orderId 模 32 = 库
orderId / 32 模 32 = 表

1
2
3
4
259        3        8
1189 5 5
352 0 11
4593 17 15

1、设定好几台数据库服务器,每台服务器上几个库,每个库多少个表,推荐是32库 * 32表,对于大部分公司来说,可能几年都够了

2、路由的规则,orderId 模 32 = 库,orderId / 32 模 32 = 表

3、扩容的时候,申请增加更多的数据库服务器,装好mysql,倍数扩容,4台服务器,扩到8台服务器,16台服务器

4、由dba负责将原先数据库服务器的库,迁移到新的数据库服务器上去,很多工具,库迁移,比较便捷

5、我们这边就是修改一下配置,调整迁移的库所在数据库服务器的地址

6、重新发布系统,上线,原先的路由规则变都不用变,直接可以基于2倍的数据库服务器的资源,继续进行线上系统的提供服务

分库分表扩容方案

上图文字补充:

每台数据库服务器上弄32个库

128个库,每个库是32张表,

128台数据库服务器,每个数据库服务器就是1个库,每个库32张表。

5. 分库分表之后全局id怎么生成?

1. 面试题

分库分表之后,id主键如何处理?

2. 面试官心里分析

其实这是分库分表之后你必然要面对的一个问题,就是id咋生成?因为要是分成多个表之后,每个表都是从1开始累加,那肯定不对啊,需要一个全局唯一的id来支持。所以这都是你实际生产环境中必须考虑的问题。

3. 面试题剖析

分库分表的id主键问题

(1)数据库自增id

这个就是说你的系统里每次得到一个id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个id。拿到这个id之后再往对应的分库分表里去写入。

这个方案的好处就是方便简单,谁都会用;缺点就是单库生成自增id,要是高并发的话,就会有瓶颈的;如果你硬是要改进一下,那么就专门开一个服务出来,这个服务每次就拿到当前id最大值,然后自己递增几个id,一次性返回一批id,然后再把当前最大id值修改成递增几个id之后的一个值;但是无论怎么说都是基于单个数据库。

适合的场景:你分库分表就俩原因,要不就是单库并发太高,要不就是单库数据量太大;除非是你并发不高,但是数据量太大导致的分库分表扩容,你可以用这个方案,因为可能每秒最高并发最多就几百,那么就走单独的一个库和表生成自增主键即可。

并发很低,几百/s,但是数据量大,几十亿的数据,所以需要靠分库分表来存放海量的数据

(2)uuid

好处就是本地生成,不要基于数据库来了;不好之处就是,uuid太长了,作为主键性能太差了,不适合用于主键。

适合的场景:如果你是要随机生成个什么文件名了,编号之类的,你可以用uuid,但是作为主键是不能用uuid的。

1
UUID.randomUUID().toString().replace(“-”, “”) -> sfsdf23423rr234sfdaf

(3)获取系统当前时间

这个就是获取当前时间即可,但是问题是,并发很高的时候,比如一秒并发几千,会有重复的情况,这个是肯定不合适的。基本就不用考虑了。

适合的场景:一般如果用这个方案,是将当前时间跟很多其他的业务字段拼接起来,作为一个id,如果业务上你觉得可以接受,那么也是可以的。你可以将别的业务字段值跟当前时间拼接起来,组成一个全局唯一的编号,订单编号,时间戳 + 用户id + 业务含义编码

(4)snowflake算法

snowflake算法

twitter开源的分布式id生成算法,就是把一个64位的long型的id,1个bit是不用的,用其中的41 bit作为毫秒数,用10 bit作为工作机器id,12 bit作为序列号

1 bit:不用,为啥呢?因为二进制里第一个bit为如果是1,那么都是负数,但是我们生成的id都是正数,所以第一个bit统一都是0

41 bit:表示的是时间戳,单位是毫秒。41 bit可以表示的数字多达2^41 - 1,也就是可以标识2 ^ 41 - 1个毫秒值,换算成年就是表示69年的时间。

10 bit:记录工作机器id,代表的是这个服务最多可以部署在2^10台机器上哪,也就是1024台机器。但是10 bit里5个bit代表机房id,5个bit代表机器id。意思就是最多代表2 ^ 5个机房(32个机房),每个机房里可以代表2 ^ 5个机器(32台机器)。

12 bit:这个是用来记录同一个毫秒内产生的不同id,12 bit可以代表的最大正整数是2 ^ 12 - 1 = 4096,也就是说可以用这个12bit代表的数字来区分同一个毫秒内的4096个不同的id

64位的long型的id,64位的long -> 二进制

0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000

2018-01-01 10:00:00 -> 做了一些计算,再换算成一个二进制,41bit来放 -> 0001100 10100010 10111110 10001001 01011100 00

机房id,17 -> 换算成一个二进制 -> 10001

机器id,25 -> 换算成一个二进制 -> 11001

snowflake算法服务,会判断一下,当前这个请求是否是,机房17的机器25,在2175/11/7 12:12:14时间点发送过来的第一个请求,如果是第一个请求

假设,在2175/11/7 12:12:14时间里,机房17的机器25,发送了第二条消息,snowflake算法服务,会发现说机房17的机器25,在2175/11/7 12:12:14时间里,在这一毫秒,之前已经生成过一个id了,此时如果你同一个机房,同一个机器,在同一个毫秒内,再次要求生成一个id,此时我只能把加1

0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000001

比如我们来观察上面的那个,就是一个典型的二进制的64位的id,换算成10进制就是910499571847892992。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
public class IdWorker{

private long workerId;
private long datacenterId;
private long sequence;

public IdWorker(long workerId, long datacenterId, long sequence){
// sanity check for workerId
// 这儿不就检查了一下,要求就是你传递进来的机房id和机器id不能超过32,不能小于0
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0",maxDatacenterId));
}
System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);

this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = sequence;
}

private long twepoch = 1288834974657L;

private long workerIdBits = 5L;
private long datacenterIdBits = 5L;
private long maxWorkerId = -1L ^ (-1L << workerIdBits); // 这个是二进制运算,就是5 bit最多只能有31个数字,也就是说机器id最多只能是32以内
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 这个是一个意思,就是5 bit最多只能有31个数字,机房id最多只能是32以内
private long sequenceBits = 12L;

private long workerIdShift = sequenceBits;
private long datacenterIdShift = sequenceBits + workerIdBits;
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private long sequenceMask = -1L ^ (-1L << sequenceBits);

private long lastTimestamp = -1L;

public long getWorkerId(){
return workerId;
}

public long getDatacenterId(){
return datacenterId;
}

public long getTimestamp(){
return System.currentTimeMillis();
}

public synchronized long nextId() {
// 这儿就是获取当前时间戳,单位是毫秒
long timestamp = timeGen();

if (timestamp < lastTimestamp) {
System.err.printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
lastTimestamp - timestamp));
}

// 0
// 在同一个毫秒内,又发送了一个请求生成一个id,0 -> 1

if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask; // 这个意思是说一个毫秒内最多只能有4096个数字,无论你传递多少进来,这个位运算保证始终就是在4096这个范围内,避免你自己传递个sequence超过了4096这个范围
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}

// 这儿记录一下最近一次生成id的时间戳,单位是毫秒
lastTimestamp = timestamp;

// 这儿就是将时间戳左移,放到41 bit那儿;将机房id左移放到5 bit那儿;将机器id左移放到5 bit那儿;将序号放最后10 bit;最后拼接起来成一个64 bit的二进制数字,转换成10进制就是个long型
return ((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) |
sequence;
}

0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000


private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}

private long timeGen(){
return System.currentTimeMillis();
}

//---------------测试---------------
public static void main(String[] args) {
IdWorker worker = new IdWorker(1,1,1);
for (int i = 0; i < 30; i++) {
System.out.println(worker.nextId());
}
}

}

怎么说呢,大概这个意思吧,就是说41 bit,就是当前毫秒单位的一个时间戳,就这意思;然后5 bit是你传递进来的一个机房id(但是最大只能是32以内),5 bit是你传递进来的机器id(但是最大只能是32以内),剩下的那个10 bit序列号,就是如果跟你上次生成id的时间还在一个毫秒内,那么会把顺序给你累加,最多在4096个序号以内。

所以你自己利用这个工具类,自己搞一个服务,然后对每个机房的每个机器都初始化这么一个东西,刚开始这个机房的这个机器的序号就是0。然后每次接收到一个请求,说这个机房的这个机器要生成一个id,你就找到对应的Worker,生成。

他这个算法生成的时候,会把当前毫秒放到41 bit中,然后5 bit是机房id,5 bit是机器id,接着就是判断上一次生成id的时间如果跟这次不一样,序号就自动从0开始;要是上次的时间跟现在还是在一个毫秒内,他就把seq累加1,就是自动生成一个毫秒的不同的序号。

这个算法那,可以确保说每个机房每个机器每一毫秒,最多生成4096个不重复的id。

利用这个snowflake算法,你可以开发自己公司的服务,甚至对于机房id和机器id,反正给你预留了5 bit + 5 bit,你换成别的有业务含义的东西也可以的。

这个snowflake算法相对来说还是比较靠谱的,所以你要真是搞分布式id生成,如果是高并发啥的,那么用这个应该性能比较好,一般每秒几万并发的场景,也足够你用了。

6. 说说MySQL读写分离的原理?主从同步延时咋解决?

1. 面试题

你们有没有做MySQL读写分离?如何实现mysql的读写分离?MySQL主从复制原理的是啥?如何解决mysql主从同步的延时问题?

2. 面试官心里分析

这个,高并发这个阶段,那肯定是需要做读写分离的,啥意思?因为实际上大部分的互联网公司,一些网站,或者是app,其实都是读多写少。所以针对这个情况,就是写一个主库,但是主库挂多个从库,然后从多个从库来读,那不就可以支撑更高的读并发压力了吗?

3. 面试题剖析

(1)如何实现mysql的读写分离?

为什么MySQL要读写分离?

其实很简单,就是基于主从复制架构,简单来说,就搞一个主库,挂多个从库,然后我们就单单只是写主库,然后主库会自动把数据给同步到从库上去。

(2)MySQL主从复制原理的是啥?

MySQL主从复制原理

主库将变更写binlog日志,然后从库连接到主库之后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入一个中继日志中。接着从库中有一个SQL线程会从中继日志读取binlog,然后执行binlog日志中的内容,也就是在自己本地再次执行一遍SQL,这样就可以保证自己跟主库的数据是一样的。

这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行SQL的特点,在高并发场景下,从库的数据一定会比主库慢一些,是有延时的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。

而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。

所以mysql实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题。

这个所谓半同步复制,semi-sync复制,指的就是主库写入binlog日志之后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的relay log之后,接着会返回一个ack给主库,主库接收到至少一个从库的ack之后才会认为写操作完成了。

所谓并行复制,指的是从库开启多个线程,并行读取relay log中不同库的日志,然后并行重放不同库的日志,这是库级别的并行。
1)主从复制的原理
2)主从延迟问题产生的原因
3)主从复制的数据丢失问题,以及半同步复制的原理
4)并行复制的原理,多库并发重放relay日志,缓解主从延迟问题

(3)mysql主从同步延时问题(精华)

MySQL主从延迟导致的生产环境的问题

线上确实处理过因为主从同步延时问题,导致的线上的bug,小型的生产事故

show status,Seconds_Behind_Master,你可以看到从库复制主库的数据落后了几ms

其实这块东西我们经常会碰到,就比如说用了mysql主从架构之后,可能会发现,刚写入库的数据结果没查到,结果就完蛋了。。。。

所以实际上你要考虑好应该在什么场景下来用这个mysql主从同步,建议是一般在读远远多于写,而且读的时候一般对数据时效性要求没那么高的时候,用mysql主从同步

所以这个时候,我们可以考虑的一个事情就是,你可以用mysql的并行复制,但是问题是那是库级别的并行,所以有时候作用不是很大

所以这个时候。。通常来说,我们会对于那种写了之后立马就要保证可以查到的场景,采用强制读主库的方式,这样就可以保证你肯定的可以读到数据了吧。其实用一些数据库中间件是没问题的。

一般来说,如果主从延迟较为严重

1、分库,将一个主库拆分为4个主库,每个主库的写并发就500/s,此时主从延迟可以忽略不计
2、打开mysql支持的并行复制,多个库并行复制,如果说某个库的写入并发就是特别高,单库写并发达到了2000/s,并行复制还是没意义。28法则,很多时候比如说,就是少数的几个订单表,写入了2000/s,其他几十个表10/s。
3、重写代码,写代码的同学,要慎重,当时我们其实短期是让那个同学重写了一下代码,插入数据之后,直接就更新,不要查询
4、如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询设置直连主库。不推荐这种方法,你这么搞导致读写分离的意义就丧失了

  • 面试
  • MySql
  • MySql
  • 面试

扫一扫,分享到微信

微信分享二维码
Maven知多少
MySQL基本用法
  1. 1. 1. 体验一下面试官对于分库分表这个事儿的一个连环炮
  2. 2. 2. 聊一下你们公司是怎么玩儿分库分表的?
    1. 2.1. 1. 面试题
    2. 2.2. 2. 面试官心里分析
    3. 2.3. 3. 面试题剖析
      1. 2.3.1. (1)为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)
      2. 2.3.2. (2)用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?
      3. 2.3.3. (3)你们具体是如何对数据库如何进行垂直拆分或水平拆分的?
  3. 3. 3. 如何把系统不停机迁移到分库分表的?
    1. 3.1. 1. 面试题
    2. 3.2. 2. 面试官心里分析
    3. 3.3. 3. 面试题剖析
      1. 3.3.1. (1)停机迁移方案
      2. 3.3.2. (2)双写迁移方案
  4. 4. 4. 如何设计可以动态扩容缩容的分库分表方案?
    1. 4.1. 1. 面试题
    2. 4.2. 2. 面试官心里分析
    3. 4.3. 3. 面试题剖析
      1. 4.3.1. (1)停机扩容
      2. 4.3.2. (2)优化后的方案
  5. 5. 5. 分库分表之后全局id怎么生成?
    1. 5.1. 1. 面试题
    2. 5.2. 2. 面试官心里分析
    3. 5.3. 3. 面试题剖析
      1. 5.3.1. (1)数据库自增id
      2. 5.3.2. (2)uuid
      3. 5.3.3. (3)获取系统当前时间
      4. 5.3.4. (4)snowflake算法
  6. 6. 6. 说说MySQL读写分离的原理?主从同步延时咋解决?
    1. 6.1. 1. 面试题
    2. 6.2. 2. 面试官心里分析
    3. 6.3. 3. 面试题剖析
      1. 6.3.1. (1)如何实现mysql的读写分离?
      2. 6.3.2. (2)MySQL主从复制原理的是啥?
      3. 6.3.3. (3)mysql主从同步延时问题(精华)

Related Issues not found

Please contact @JavaSsun to initialize the comment

© 2018-2024 Allen
Hexo Theme Yilia by Litten
本站总访问量71847次 | 本站访客数64554人
  • 所有文章
  • 友链
  • 关于我

tag:

  • Elasticsearch
  • 面试
  • MQ
  • Redis
  • Nginx
  • Docker
  • Git
  • Dubbo
  • 论文
  • MySql
  • Tools
  • 日志
  • Linux
  • 系统架构
  • Java
  • 源码解析
  • Hexo-yilia
  • Jvm
  • MyBatis
  • SpringBoot
  • Swagger2
  • 算法
  • 分布式
  • Photo
  • HTTP
  • Hystrix
  • SSL
  • ELK
  • IDEA
  • Jwt
  • 定时任务
  • BigData
  • Maven
  • Quartz
  • 人工智能
  • 地图坐标转换
  • 网络编程
  • Python
  • SpringCloud
  • 搬砖结晶
  • OpenCV
  • 推荐系统
  • 目标检测
  • SkLearn
  • 图神经网络
  • PyTorch
  • TensorFlow
  • 数据挖掘
  • 研究生课题-AD检测
  • 研究生成果

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 研究生总结

    2024-05-09

    #论文#人工智能#搬砖结晶#图神经网络#研究生课题-AD检测#研究生成果

  • 12-ROI文件分析

    2023-11-22

    #Tools#人工智能#研究生课题-AD检测

  • 11-DTI预处理

    2023-11-16

    #Tools#人工智能#研究生课题-AD检测

  • 10-GRETNA处理fMRI

    2023-11-05

    #Tools#人工智能#研究生课题-AD检测

  • 9-(图)利用Matlab的spm12工具处理fMRI为ROI

    2023-10-28

    #Tools#人工智能#研究生课题-AD检测

  • 9-(文)利用Matlab的spm12工具处理fMRI为ROI

    2023-10-26

    #Tools#人工智能#研究生课题-AD检测

  • 8-7-FSL软件使用

    2023-10-20

    #Tools#人工智能#研究生课题-AD检测

  • 8-6-FreeSurfer软件使用

    2023-10-16

    #Tools#人工智能#研究生课题-AD检测

  • 8-5-SPM软件使用

    2023-10-10

    #Tools#人工智能#研究生课题-AD检测

  • 8-4-MRI预处理

    2023-09-16

    #Tools#人工智能#研究生课题-AD检测

  • 8-3-UNet提取海马体

    2023-09-10

    #人工智能#研究生课题-AD检测

  • 8-2-ADNI论文数据预处理

    2023-09-02

    #论文#Tools#人工智能#研究生课题-AD检测

  • 8-1-数据预处理工具

    2023-08-05

    #Tools#人工智能#研究生课题-AD检测

  • 7-2-GNN For AD

    2023-07-25

    #论文#人工智能#图神经网络#研究生课题-AD检测

  • 7-1-GNN For Medical Diagnosis

    2023-06-28

    #论文#人工智能#图神经网络#研究生课题-AD检测

  • 6-2-SCI一区论文精读

    2023-05-25

    #论文#人工智能#研究生课题-AD检测

  • 6-1-MRI成像及ADNI简介

    2023-05-10

    #人工智能#研究生课题-AD检测

  • 5-ADNI-实验数据筛选与下载

    2023-04-25

    #人工智能#研究生课题-AD检测

  • 4-AD文献的阅读记录

    2023-04-20

    #论文#人工智能#研究生课题-AD检测

  • 3-指标特征选择

    2023-04-05

    #人工智能#研究生课题-AD检测

  • 2-AD有关课题

    2023-03-25

    #人工智能#研究生课题-AD检测

  • 1-阿尔茨海默病

    2023-03-20

    #人工智能#研究生课题-AD检测

  • 7-SHAP

    2023-03-15

    #人工智能#数据挖掘

  • 6-模型的融合技术大总结与结果部署

    2023-02-25

    #人工智能#数据挖掘

  • 5-模型建立与调参

    2023-02-20

    #人工智能#数据挖掘

  • 4-特征工程

    2023-02-12

    #人工智能#数据挖掘

  • 3-数据清洗和转换技巧

    2023-02-09

    #人工智能#数据挖掘

  • 2-数据的探索性-EDA分析

    2023-02-06

    #人工智能#数据挖掘

  • 1-赛题理解

    2023-02-04

    #人工智能#数据挖掘

  • 0-零基础入门数据挖掘学习路径

    2023-02-03

    #人工智能#数据挖掘

  • 重温深度学习优化算法

    2023-01-28

    #人工智能

  • 重温归一化(MinMaxScaler)和标准化(StandardScaler)

    2023-01-20

    #人工智能

  • 重温Batch Normalization

    2023-01-15

    #人工智能

  • 交叉熵损失函数和平方损失的区别

    2023-01-12

    #人工智能

  • loss不下降的解决方法

    2023-01-10

    #人工智能

  • 重温Seq2Seq和Attention机制

    2023-01-05

    #人工智能

  • 重温LSTM和GRU

    2022-12-28

    #人工智能

  • 重温RNN

    2022-12-25

    #人工智能

  • pytorch_geometric离线安装

    2022-12-19

    #人工智能#图神经网络#PyTorch

  • pytorch_geometric安装

    2022-12-18

    #人工智能#图神经网络#PyTorch

  • 生成式对抗网络GAN的工作原理

    2022-12-13

    #人工智能

  • Ubuntu查看cuda-cudnn等版本命令

    2022-12-10

    #Tools#人工智能

  • CUDA和CuDNN安装

    2022-12-08

    #Tools#人工智能

  • GPU之nvidia-smi命令详解

    2022-12-05

    #Tools#人工智能

  • 1-TensorFlow简介及安装

    2022-12-01

    #人工智能#TensorFlow

  • 入门图神经网络

    2022-11-25

    #人工智能#图神经网络

  • 10-模型的保存加载-模型微调-GPU使用及Pytorch常见报错

    2022-11-06

    #人工智能#PyTorch

  • 9-正则化与标准化大总结

    2022-10-28

    #人工智能#PyTorch

  • 8-Tensorboard可视化与Hook机制

    2022-10-25

    #人工智能#PyTorch

  • 7-优化器和学习率调整策略

    2022-10-23

    #人工智能#PyTorch

  • 6-模型的权值初始化与损失函数介绍

    2022-10-20

    #人工智能#PyTorch

  • 5-nn各网络层介绍

    2022-10-17

    #人工智能#PyTorch

  • Pytorch提取神经网络层结构-层参数及自定义初始化

    2022-10-14

    #人工智能#PyTorch

  • 4-模型创建Module-模型容器Containers及AlexNet网络搭建

    2022-10-12

    #人工智能#PyTorch

  • 3-Pytorch数据读取机制(DataLoader)与图像预处理模块(transforms)

    2022-10-09

    #人工智能#PyTorch

  • 2-Pytorch的动态图-自动求导及逻辑回归

    2022-10-02

    #人工智能#PyTorch

  • 1-Pytorch的数据载体张量与线性回归

    2022-09-28

    #人工智能#PyTorch

  • Pytorch与词向量

    2022-09-25

    #人工智能#PyTorch

  • Pytorch基础理论和简单的神经网络实现

    2022-09-23

    #人工智能#PyTorch

  • Windows下的Pytorch环境搭建

    2022-09-20

    #人工智能#PyTorch

  • 图卷积网络-GCN

    2022-09-15

    #人工智能#图神经网络

  • GCN使用的数据集Cora等

    2022-09-10

    #人工智能#图神经网络

  • 图网络属性介绍

    2022-09-08

    #人工智能#图神经网络

  • 图神经网络理论基础

    2022-09-05

    #人工智能#图神经网络

  • 5-AI上推荐之AutoRec与Deep Crossing模型(改变神经网络的复杂程度)

    2022-08-28

    #人工智能#推荐系统

  • 4-AI上推荐之FM和FFM(九九归一)

    2022-08-17

    #人工智能#推荐系统

  • 梯度提升树GBDT的理论学习与细节补充

    2022-08-05

    #人工智能#推荐系统

  • 梯度下降算法的细节补充(凸函数, 导数, 偏导数,梯度, 方向导数以及负梯度下降最快背后的泰勒身影)

    2022-07-28

    #人工智能#推荐系统

  • 逻辑回归、优化算法和正则化的幕后细节补充

    2022-07-24

    #人工智能#推荐系统

  • 3-AI上推荐之逻辑回归模型与GBDT+LR(特征工程模型化的开端)

    2022-07-20

    #人工智能#推荐系统

  • 奇异值分解(SVD)的原理详解及推导

    2022-07-13

    #人工智能#推荐系统

  • 2-AI上推荐之隐语义模型(LFM)和矩阵分解(MF)

    2022-07-10

    #人工智能#推荐系统

  • 1-AI上推荐之协同过滤

    2022-07-02

    #人工智能#推荐系统

  • R-CNN and Fast R-CNN and Faster R-CNN and SPP

    2022-06-15

    #人工智能#目标检测

  • 10-Harris和Shi-Tomas算法

    2022-06-06

    #人工智能#OpenCV

  • 9-角点特征

    2022-06-03

    #人工智能#OpenCV

  • 8-图像变换-傅里叶变换

    2022-05-29

    #人工智能#OpenCV

  • 7-模板匹配与霍夫变换

    2022-05-15

    #人工智能#OpenCV

  • 6-边缘检测

    2022-05-08

    #人工智能#OpenCV

  • 5-直方图

    2022-04-28

    #人工智能#OpenCV

  • 4-图像平滑

    2022-04-26

    #人工智能#OpenCV

  • 3-形态学操作

    2022-04-22

    #人工智能#OpenCV

  • 2-几何变换

    2022-04-20

    #人工智能#OpenCV

  • 1-图像的基础操作

    2022-04-18

    #人工智能#OpenCV

  • 0-OpenCV简介

    2022-04-15

    #人工智能#OpenCV

  • Ubuntu18.04下安装OpenCV3.4

    2022-04-01

    #人工智能#OpenCV

  • 后 R-CNN时代, Faster R-CNN、SSD、YOLO 各类变体统治下的目标检测综述:Faster R-CNN系列胜了吗?

    2022-03-28

    #人工智能#目标检测

  • SKLearn学习总结

    2022-03-20

    #人工智能#SkLearn

  • 详细了解PyCharm支持的4种Python Interpreter和配置方法

    2022-03-02

    #Tools

  • Pycharm远程连接

    2022-02-26

    #Tools

  • JupyterLab学习总结

    2022-02-19

    #Tools#人工智能

  • Anaconda学习总结

    2022-02-13

    #Tools#人工智能

  • Ubuntu下安装lrzsz工具

    2022-02-08

    #Tools

  • 13-RNN

    2022-02-05

    #人工智能

  • 12-加速深度学习的算法和硬件-讲座

    2022-01-10

    #人工智能

  • 11-深度学习硬件算力基础-GPU与TPU与英特尔神经棒

    2021-12-26

    #人工智能

  • 10-经典卷积神经网络架构案例分析

    2021-12-16

    #人工智能

  • 9-迁移学习与fine-tuning

    2021-12-11

    #人工智能

  • 8-CNNS in Practice-卷积神经网络工程实践技巧

    2021-11-28

    #人工智能

  • 7-训练神经网络-下

    2021-11-09

    #人工智能

  • 6-训练神经网络-上

    2021-11-05

    #人工智能

  • 5-可视化并理解卷积神经网络

    2021-10-25

    #人工智能

  • 4-Convolutional-Neural-Networks

    2021-10-18

    #人工智能

  • 3-神经网络与反向传播

    2021-10-10

    #人工智能

  • 2-损失函数和梯度下降

    2021-09-25

    #人工智能

  • 1-KNN&线性分类器

    2021-09-20

    #人工智能

  • 0-机器学习基础

    2021-09-15

    #人工智能

  • 入门人工智能算法工程师-先来碗毒鸡汤

    2021-07-30

    #人工智能

  • 3-如何高效阅读机器学习顶会论文

    2021-07-15

    #论文

  • 2-论文ABC类与一二区的区别

    2021-06-10

    #论文

  • 1-学术小白

    2021-06-06

    #论文

  • 领域驱动设计在互联网业务开发中的实践

    2020-09-13

    #系统架构

  • 领域驱动设计

    2020-07-12

    #系统架构

  • DDD模式-从天书到实践

    2020-06-28

    #系统架构

  • DDD-马什么梅

    2020-06-14

    #系统架构

  • FaaS-又一个为未来

    2020-05-17

    #系统架构

  • 分布式ID的花拳绣腿

    2020-04-19

    #面试#系统架构#分布式

  • 4-Dockerfile上

    2020-04-08

    #Docker

  • 3-Docker存储卷

    2020-04-07

    #Docker

  • 2-Docker容器网络

    2020-04-06

    #Docker

  • 1-安装_使用Docker

    2020-04-05

    #Docker

  • 45-自增ID用完怎么办

    2020-03-11

    #MySql

  • 44-一些常见问题

    2020-03-09

    #MySql

  • 43-要不要使用分区表

    2020-03-08

    #MySql

  • 42-grant之后要跟着flush privileges吗

    2020-03-07

    #MySql

  • 41-如何最快的复制一张表

    2020-03-06

    #MySql

  • 40-insert语句的锁为什么这么多

    2020-03-04

    #MySql

  • 39-自增主键为什么不是连续的

    2020-03-03

    #MySql

  • 38-都说InnoDB好_那还要不要使用Memory引擎

    2020-03-02

    #MySql

  • 37-什么时候会使用内部临时表

    2020-03-01

    #MySql

  • SpringBoot_RabbitMQ配置参数详解

    2020-02-26

    #MQ

  • RabbitMQ安装

    2020-02-26

    #MQ

  • ELK日志平台-中

    2020-02-11

    #日志#ELK

  • ELK日志平台-上

    2020-02-10

    #日志#ELK

  • Java8新特性

    2020-02-08

    #Java

  • 1-Hystrix知多少

    2020-01-01

    #面试#Hystrix

  • 25-Nginx变量原理-应用

    2019-12-13

    #Nginx

  • 24-详解HTTP过滤模块

    2019-12-12

    #Nginx

  • 23-详解HTTP请求的11个阶段

    2019-12-11

    #Nginx

  • 22-如何找到处理请求的Server指令块

    2019-12-10

    #Nginx

  • 21-Nginx中的正则表达式

    2019-12-09

    #Nginx

  • 20-处理HTTP请求头部流程

    2019-12-09

    #Nginx

  • 19-Nginx中Listen指令用法

    2019-12-08

    #Nginx

  • 18-Nginx冲突的配置指令以谁为准

    2019-12-08

    #Nginx

  • 17-Nginx动态模块

    2019-12-07

    #Nginx

  • 16-Nginx容器

    2019-12-06

    #Nginx

  • 15-Worker集成协同工作的关键

    2019-12-06

    #Nginx

  • 14-Nginx连接池处理网络请求-内存池对性能的影响

    2019-12-05

    #Nginx

  • 13-Nginx模块

    2019-12-04

    #Nginx

  • 12-网络收发与Nginx事件模型

    2019-12-03

    #Nginx

  • 11-Nginx架构_相关流程

    2019-12-02

    #Nginx

  • LinkedHashMap实现原理_探险

    2019-11-28

    #Java#源码解析

  • HashTable实现原理_探险

    2019-11-22

    #Java#源码解析

  • HashMap实现原理_探险

    2019-11-20

    #Java#源码解析

  • LinkList实现原理_探险

    2019-11-17

    #Java#源码解析

  • ArrayList实现原理_探险

    2019-11-16

    #Java#源码解析

  • 10-OpenResty用Lua语言实现简单服务

    2019-11-12

    #Nginx

  • 9-SSL-Nginx

    2019-11-11

    #Nginx#SSL

  • 8-Nginx配置文件简易解析

    2019-11-10

    #Nginx

  • 7-Nginx安装详解

    2019-11-09

    #Nginx

  • 6-GoAccess实现可视化并实时监控access日志

    2019-11-08

    #Nginx#Tools#日志

  • 5-Nginx搭建具备缓存功能的反向代理

    2019-11-05

    #Nginx

  • 4-Nginx搭建静态资源Web服务器

    2019-11-01

    #Nginx

  • SpringBoot中jar为什么可以直接运行

    2019-10-30

    #面试#SpringBoot

  • SpringBoot全局异常处理

    2019-10-29

    #面试#SpringBoot

  • SpringBoot事件和监听器

    2019-10-29

    #面试#SpringBoot

  • SpringBoot启动原理

    2019-10-29

    #面试#SpringBoot

  • 36-为什么临时表可以重名

    2019-10-28

    #MySql

  • 35-join语句如何优化

    2019-10-27

    #MySql

  • 34-到底可不可以使用join

    2019-10-26

    #MySql

  • 33-我查这么多数据_会不会把数据库内存打爆

    2019-10-24

    #MySql

  • 32-为什么有kill不掉的语句

    2019-10-23

    #MySql

  • 31-误删数据后除了跑路_还能怎么办

    2019-10-22

    #MySql

  • 3-Nginx命令行演示-重载-热部署-切割

    2019-10-20

    #Nginx

  • 2-Nginx配置语法

    2019-10-17

    #Nginx

  • 1-Nginx的前世今生

    2019-10-15

    #Nginx

  • 0-Nginx访问日志配置及信息详解

    2019-10-11

    #Nginx

  • 分布式事务

    2019-09-19

    #面试#系统架构#分布式

  • 分布式锁

    2019-09-18

    #面试#系统架构#分布式

  • 分布式锁与事务

    2019-09-16

    #面试#系统架构#分布式

  • 数据结构与算法第四阶段学习图

    2019-09-16

    #算法

  • 数据结构与算法第三阶段学习图

    2019-09-16

    #算法

  • 数据结构与算法第二阶段学习图

    2019-09-16

    #算法

  • 数据结构与算法第一阶段学习图

    2019-09-16

    #算法

  • 2018-2019工作总结

    2019-09-15

    #搬砖结晶

  • 开发常见问题

    2019-09-14

    #Java

  • 52-算法实战(五)_如何用学过的数据结构和算法实现一个短网址系统

    2019-09-14

    #算法

  • 30-用动态的观点看加锁

    2019-09-13

    #MySql

  • 29-如何判断一个数据库是不是出问题了

    2019-09-12

    #MySql

  • 28-读写分离有哪些坑

    2019-09-11

    #MySql

  • 51-算法实战(四)_剖析微服务接口鉴权限流背后的数据结构和算法

    2019-09-09

    #算法

  • 50-算法实战(三)_剖析高性能队列Disruptor背后的数据结构和算法

    2019-09-06

    #算法

  • 49-算法实战(二)_剖析搜索引擎背后的经典数据结构和算法

    2019-09-02

    #算法

  • 27-主库出问题了_从库怎么办

    2019-08-29

    #MySql

  • 26-备库为什么会延迟好几个小时

    2019-08-28

    #MySql

  • 25-MySQL是怎么保证高可用的

    2019-08-27

    #MySql

  • 24-MySQL是怎么保证主备一致的

    2019-08-26

    #MySql

  • 48-算法实战(一)_剖析Redis常用数据类型对应的数据结构

    2019-08-25

    #算法

  • 47-并行算法_如何利用并行处理提高算法的执行效率

    2019-08-20

    #算法

  • 46-索引_如何在海量数据中快速查找某个数据

    2019-08-16

    #算法

  • 45-搜索_如何用A*搜索算法实现游戏中的寻路功能

    2019-08-13

    #算法

  • 44-B+树_MySQL数据库索引是如何实现的

    2019-08-10

    #算法

  • 43-向量空间_如何实现一个简单的音乐推荐系统

    2019-08-08

    #算法

  • 42-概率统计_如何利用朴素贝叶斯算法过滤垃圾短信

    2019-08-05

    #算法

  • 41-位图_如何实现网页爬虫中的URL去重功能

    2019-08-02

    #算法

  • 40-最短路径_地图软件是如何计算出最优出行路径的

    2019-07-28

    #算法

  • 39-拓扑排序_如何确定代码源文件的编译依赖关系

    2019-07-24

    #算法

  • 38-动态规划实战_如何实现搜索引擎中的拼写纠错功能

    2019-07-20

    #算法

  • 23-MySQL是如何保证数据不丢的

    2019-07-19

    #MySql

  • 22-MySQL有哪些“饮鸩止渴”提高性能的方法

    2019-07-18

    #MySql

  • 21-为什么我只改一行的语句_锁还这么多

    2019-07-17

    #MySql

  • 20-幻读是什么_幻读有什么问题

    2019-07-16

    #MySql

  • 19-只查一行的语句为何执行这么慢

    2019-07-15

    #MySql

  • 37-动态规划理论_一篇文章带你彻底搞懂最优子结结构_无后效性_重复子问题

    2019-07-13

    #算法

  • 36-初识动态规划_如何巧妙解解决“双十一”购物时的凑单问题

    2019-07-09

    #算法

  • 35-回溯算法_从电影《蝴蝶效应》中学习回溯算法的核心思想

    2019-07-06

    #算法

  • 34-分治算法_谈一谈大规模计算框架MapReduce中的分治思想

    2019-07-04

    #算法

  • 33-贪心算法_如何用贪心算法实现Huffman压缩编码

    2019-07-01

    #算法

  • 32-AC自动机_如何用多模式串匹配实现敏感词过滤功能

    2019-06-25

    #算法

  • 18-SQL语句逻辑相同_性能却为何差异巨大

    2019-06-23

    #MySql

  • 17-如何正确的显示随机消息

    2019-06-22

    #MySql

  • 16-MySQL中order by是如何工作的

    2019-06-20

    #MySql

  • 15-日志和索引有关问题

    2019-06-18

    #MySql

  • RocketMQ探索

    2019-06-17

    #MQ

  • 14-count(\*)为什么这么慢

    2019-06-16

    #MySql

  • 13-为什么表数据删掉一半而表文件大小不变

    2019-06-15

    #MySql

  • 12-为什么我的MySQL会“抖”一下

    2019-06-13

    #MySql

  • 11-怎么给字符串字段加索引

    2019-06-12

    #MySql

  • 10-MySQL为什么有时候会选错索引

    2019-06-11

    #MySql

  • 3-3-Docker容器用法

    2019-06-10

    #Docker

  • RabbitMQ详解

    2019-06-08

    #MQ

  • 5-分布式会话_锁_事务_高并发系统设计

    2019-06-07

    #面试

  • 3.2-Docker镜像用法

    2019-06-05

    #Docker

  • 4-Zookeeperer使用场景

    2019-06-04

    #面试

  • Dubbo知多少

    2019-06-03

    #面试#Dubbo

  • 3-分布式系统中接口调用顺序性如何保证

    2019-06-03

    #面试#Dubbo

  • 2-分布式系统中接口的幂等性该如何保证_比如不能重复扣款

    2019-06-02

    #面试#Dubbo

  • 1-分布式系统连环炮_Dubbo有关知识点

    2019-06-01

    #面试#Dubbo

  • 9-普通索引和唯一索引如何选择

    2019-05-30

    #MySql

  • 8-事务到底是隔离的还是不隔离的

    2019-05-29

    #MySql

  • 7-行锁功过_怎么减少行锁对性能的影响

    2019-05-28

    #MySql

  • 6-全局锁和表锁_给表加个字段怎么有这么多阻碍

    2019-05-27

    #MySql

  • 5-深入浅出索引(下)

    2019-05-26

    #MySql

  • 4-深入浅出索引(上)

    2019-05-25

    #MySql

  • 3.1-Docker用法

    2019-05-24

    #Docker

  • 2.2-Docker启动报错

    2019-05-23

    #Docker

  • 3-事务隔离_为什么你改了我还看不见

    2019-05-21

    #MySql

  • MySQL重要日志

    2019-05-20

    #面试#MySql

  • 2-日志系统_一条SQL更新语句是如何执行的

    2019-05-20

    #MySql

  • 1-基础架构_一条SQL查询语句是如何执行的

    2019-05-19

    #MySql

  • 2.1-Docker安装与部署

    2019-05-18

    #Docker

  • 1-Docker缘由

    2019-05-12

    #Docker

  • 0-Docker配置国内免费registry_mirror

    2019-05-08

    #Docker

  • 5-分布式搜索引擎如何部署

    2019-04-26

    #Elasticsearch#面试

  • 4-ES如何在几十亿数据场景下优化查询性能

    2019-04-23

    #Elasticsearch#面试

  • 3-ES读写数据的工作原理

    2019-04-22

    #Elasticsearch#面试

  • 2-分布式搜索引擎的架构是如何设计的

    2019-04-21

    #Elasticsearch#面试

  • 1-面试官对分布式搜索引擎的4个连环炮

    2019-04-20

    #Elasticsearch#面试

  • 8-如何设计一个消息队列

    2019-04-10

    #面试#MQ

  • 7-消息队列如何解决延迟_过期失效_积压消息等问题

    2019-04-10

    #面试#MQ

  • JWT学习

    2019-04-09

    #Java#Jwt

  • 6-消息队列如何保证消息的顺序性

    2019-04-08

    #面试#MQ

  • 5-消息队列如何保证可靠性传输(消息丢了怎么办)

    2019-04-07

    #面试#MQ

  • 4-消息队列消费到重复数据怎么办

    2019-04-06

    #面试#MQ

  • 3-消息队列如何保证高可用性

    2019-04-03

    #面试#MQ

  • 2-消息队列引入原原因_优缺点_应用场景_技术选型

    2019-04-02

    #面试#MQ

  • 1-面试官对消息队列的10个连环炮

    2019-04-01

    #面试#MQ

  • Git常见200+条命令

    2019-03-28

    #Git

  • 8-GitLab简单操作

    2019-03-25

    #Git

  • 31-Trie树_如何实现搜索引擎的搜索关键词提示功能

    2019-03-12

    #算法

  • 7-基于GitHub进行团队协作

    2019-03-09

    #Git

  • 30-字符串匹配基础下_如何借助BM算法轻松理解KMP算法

    2019-03-06

    #算法

  • 29-字符串匹配基础中_如何实现文本编辑器中的查找功能

    2019-03-03

    #算法

  • 28-字符串匹配基础上_如何借助哈希算法实现高效字符串匹配

    2019-03-01

    #算法

  • 6-GitHub的认识与使用

    2019-02-25

    #Git

  • 5-Git集成使用禁忌

    2019-02-15

    #Git

  • 27-深度和广度优先搜索_如何找出社交网络中的三度好友关系

    2019-02-13

    #算法

  • 26-图的表示_如何存储微博微信等社交网络中的好友关系

    2019-02-10

    #算法

  • 国内地图坐标系转换

    2019-02-08

    #地图坐标转换

  • 4-Git多人单分支集成协作时的常见场景

    2019-02-08

    #Git

  • 微服务架构-下篇

    2019-02-06

    #系统架构

  • 微服务架构-中篇

    2019-02-03

    #系统架构

  • 微服务架构-上篇

    2019-02-01

    #系统架构

  • Python数据分析工具

    2019-01-30

    #Python

  • Python高级篇

    2019-01-29

    #Python

  • Python中级篇_下

    2019-01-28

    #Python

  • Python中级篇_上

    2019-01-27

    #Python

  • Python初级篇

    2019-01-26

    #Python

  • Python前世今生

    2019-01-25

    #Python

  • 源码分析-MyBatis数据源与连接池

    2019-01-23

    #MyBatis

  • MyBatis初始化做了什么

    2019-01-21

    #MyBatis

  • 3-Git与GitHub简单同步

    2019-01-20

    #Git

  • 2-Git常用场景

    2019-01-18

    #Git

  • 1-Git安装及简单操作

    2019-01-15

    #Git

  • SpringCloud探索与实战

    2019-01-13

    #SpringCloud

  • MyBatis架构与原理

    2019-01-09

    #MyBatis

  • MyBatis原理概括

    2019-01-08

    #MyBatis

  • MyBatis多数据源配置

    2019-01-07

    #MyBatis

  • JVM(八):Jvm知识点概览

    2019-01-06

    #Jvm

  • JVM(七):Jvm调优-工具

    2019-01-05

    #Tools#Jvm

  • JVM(六):Java服务GC参数调优案例

    2019-01-03

    #Jvm

  • JVM(五):GC分析

    2019-01-02

    #Jvm

  • JVM(四):Jvm调优-命令

    2019-01-01

    #Jvm

  • JVM(三):GC算法_垃圾收集器

    2019-01-01

    #Jvm

  • 25-堆的应用_如何获取Top10最热门的搜索关键词

    2018-12-30

    #算法

  • 24-堆和堆排序_为什么说堆排序没有快速排序快

    2018-12-29

    #算法

  • 23-递归树_如何借助树来求解递归算法的时间复杂度

    2018-12-27

    #算法

  • 22-红黑树下_实现红黑树的技巧

    2018-12-25

    #算法

  • 21-红黑树上_为什么工程中都用红黑树这种二叉树

    2018-12-23

    #算法

  • 应用架构演变过程

    2018-12-20

    #Photo

  • MyBatis常用插件

    2018-12-14

    #MyBatis

  • JVM(二):Jvm内存结构

    2018-12-11

    #Jvm

  • JVM(一):Java类加载机制

    2018-12-10

    #Jvm

  • Map-Reduce学习

    2018-11-20

    #BigData

  • 20-二叉树基础下_有了如此高效的散列表—_为什么还需要二叉树

    2018-11-18

    #算法

  • 19-二叉树基础上_什么样的二叉树适合用数组来存储

    2018-11-16

    #算法

  • 18-哈希算法下_哈希算法在分布式系统中有哪些应用

    2018-11-15

    #算法

  • 17-哈希算法上_如何防止数据库中的用户信息被脱库

    2018-11-13

    #算法

  • Hadoop学习

    2018-11-10

    #BigData

  • 16-散列表下_为什么散列表和链表经常一起使用

    2018-11-09

    #算法

  • 15-散列表中_如何打造一个工业级水平的散列表

    2018-11-09

    #算法

  • 14-散列表上_Word文档中的单词拼写检查功能如何实现

    2018-11-08

    #算法

  • 13-跳表_为什么Redis一定要用跳表来实现有序集合

    2018-11-06

    #算法

  • 12-二分查找下_如何快速定位IP对应的省份地址

    2018-11-04

    #算法

  • 11-二分查找上_如何用最省内存的方式实现快速查找功能

    2018-11-02

    #算法

  • 10-排序优化_如何实现一个通用的高性能的排序函数

    2018-11-01

    #算法

  • 9-线性排序_如何根据年龄给100万用户数据排序

    2018-10-28

    #算法

  • 8-排序下_如何用快排思想在O(n)内查找第K大元素

    2018-10-24

    #算法

  • 7-排序上_为什么插入排序比冒泡排序更受欢迎

    2018-10-22

    #算法

  • 6-递归_如何用三行代码找到最终推荐人

    2018-10-20

    #算法

  • 高性能队列-Disruptor

    2018-10-18

    #MQ#Java

  • 5-队列_队列在线程池等有限资源池中的应用

    2018-10-16

    #算法

  • 4-栈_如何实现浏览器的前进和后退功能

    2018-10-13

    #算法

  • Quartz学习

    2018-10-09

    #Java#定时任务#Quartz

  • 3-链表下_如何轻松写出正确的链表代码

    2018-10-06

    #算法

  • 2-链表上_如何实现LRU缓存淘汰算法

    2018-10-06

    #算法

  • 1-数组_为什么很多编程语言中数组都从0开始编号

    2018-10-02

    #算法

  • 复杂度分析-下部

    2018-09-29

    #算法

  • 复杂度分析-上部

    2018-09-28

    #算法

  • 数据结构与算法概览

    2018-09-26

    #算法

  • 请求与响应

    2018-09-17

    #HTTP

  • TextRank基本了解

    2018-09-01

    #算法

  • (5)Hexo踩坑_主题优化

    2018-08-21

    #Hexo-yilia

  • (4)Hexo撰写文章

    2018-08-19

    #Hexo-yilia

  • (3)Hexo常用命令详解

    2018-08-19

    #Hexo-yilia

  • (2)Hexo配置文件详解

    2018-08-17

    #Hexo-yilia

  • 关于Firewalld二三事

    2018-08-15

    #Linux

  • (1)Hexo博客搭建

    2018-08-11

    #Hexo-yilia

  • 修改Vim_tab为4个空格

    2018-08-06

    #Linux

  • CentOs7防火墙开端口测试

    2018-08-01

    #Linux

  • 10-Redis的并发竞争问题及生产环境集群部署架构

    2018-07-30

    #面试#Redis

  • 9-如何保证缓存与数据库双写时的数据一致性

    2018-07-29

    #面试#Redis

  • 8-如何应对缓存雪崩及穿透问题

    2018-07-28

    #面试#Redis

  • 7-Redis集群模式原理

    2018-07-26

    #面试#Redis

  • Redis所需安装包及各种依赖

    2018-07-25

    #Redis

  • 6-Redis挂掉重启后数据如何进行恢复

    2018-07-24

    #面试#Redis

  • 5-Redis高并发高可用有关问题

    2018-07-21

    #面试#Redis

  • 4-Redis过期策略_手写LRU

    2018-07-19

    #面试#Redis

  • 3-Redis常用数据类型及使用场景

    2018-07-18

    #面试#Redis

  • 2-Redis线程模型_单线程效率高的原因

    2018-07-17

    #面试#Redis

  • 1-项目中缓存如何使用

    2018-07-16

    #面试#Redis

  • AWK三剑客

    2018-07-15

    #Linux

  • Maven插件-assembly插件基本使用

    2018-06-28

    #Java#Maven

  • Maven知多少

    2018-06-27

    #Java#Maven

  • 1-分库分表知多少

    2018-06-25

    #面试#MySql

  • MySQL基本用法

    2018-06-21

    #MySql

  • MySQL安装

    2018-06-20

    #MySql

  • Swagger2学习与集成

    2018-05-20

    #SpringBoot#Swagger2

  • SpringBoot面试

    2018-05-16

    #面试#SpringBoot

  • SpringBoot+Docker简单配置

    2018-05-15

    #Docker#SpringBoot

  • Java定时任务

    2018-05-13

    #Java#定时任务

  • Netty知多少

    2018-05-05

    #网络编程

  • Java编程瞎侃

    2018-04-18

    #Java

  • Vim常用操作

    2018-03-25

    #Linux

  • Linux定时任务Crontab详解

    2018-03-23

    #Linux

  • Linux常用插件及乱码

    2018-03-20

    #Linux

  • Linux安装常用软件

    2018-03-19

    #Linux

  • Idea常用插件及个性化配置

    2018-03-18

    #Tools#IDEA

  • Host-Vm相互ping不同到的解决办法

    2018-03-16

    #Linux

  • GitHub
  • 廖雪峰
  • 纯洁的微笑
  • 我没有三颗心脏
  • 阿里巴巴开源镜像网站
一个脱离了高级趣味的人!