<small id='eOgdl3K2b'></small> <noframes id='eG0Jiw'>

  • <tfoot id='F0h7D5weR'></tfoot>

      <legend id='w9mNrI4Pg'><style id='IRPYpnDOjG'><dir id='PK96l5pW'><q id='WNcsE0J'></q></dir></style></legend>
      <i id='WO9J'><tr id='oBtyauHQn'><dt id='PQclb9Zo0'><q id='JEIVFG'><span id='64BJlmbpSe'><b id='9ElN5'><form id='ZvrXsJzhn8'><ins id='2j4Lim'></ins><ul id='gtujMEXVvr'></ul><sub id='n6BcUh1R'></sub></form><legend id='2uASYVM'></legend><bdo id='hZRsWzi6'><pre id='JG2BPxO'><center id='h9eU3n'></center></pre></bdo></b><th id='SJ6s5e'></th></span></q></dt></tr></i><div id='awiycIHuY2'><tfoot id='f9OcWrskv'></tfoot><dl id='J04K7qM8'><fieldset id='RI06OnDr1'></fieldset></dl></div>

          <bdo id='2CnmKD'></bdo><ul id='9HnwR'></ul>

          1. <li id='KpHOgt'></li>
            登陆

            《MySQL重要知识点及面试总结》:引荐保藏

            admin 2019-07-18 210人围观 ,发现0个评论
            作者:Snailclimb
            链接:https://segmentfault.com/a/1190000019619667?utm_source=tuicool&utm_medium=referral

            前语:

            这篇花文章是我花了几天时刻对之前总结的MySQL知识点做了完善后的产品,这篇文章能够用来回忆MySQL基础知识以及备战MySQL常见面试问题。

            什么是MySQL?

            MySQL 是一种联系型数据库,在Java企业级开发中十分常用,由于 MySQL 是开源免费的,而且便利扩展。阿里巴巴数据库体系也许多用到了 MySQL,因而它的稳定性是有确保的。MySQL是开放源代码的,因而任何人都能够在 GPL(General Public License) 的答应下下载并依据个性化的需求对其进行修正。MySQL的默许端口号是3306

            业务相关

            什么是业务?

            业务是逻辑上的一组操作,要么都履行,要么都不履行。

            业务最经典也常常被拿出来说比方便是转账了。假定小明要给小红转账1000元,这个转账会触及到两个要害操作便是:将小明的余额削减1000元,将小红的余额增加1000元。万一在这两个操作之间忽然呈现过错比方银行体系溃散,导致小明余额削减而小红的余额没有增加,这样就不对了。业务便是确保这两个要害操作要么都成功,要么都要失利。

            事物的四大特性(ACID)介绍一下?

            1. 原子性: 业务是最小的履行单位,不答应切割。业务的原子性确保动作要么悉数完结,要么彻底不起效果;
            2. 共同性: 履行业务前后,数据坚持共同,多个业务对同一个数据读取的成果是相同的;
            3. 阻隔性: 并发拜访数据库时,一个用户的业务不被其他业务所搅扰,各并发业务之间数据库是独立的;
            4. 耐久性: 一个业务被提交之后。它对数据库中数据的改动是耐久的,即便数据库发作毛病也不应该对其有任何影响。

            并发业务带来哪些问题?

            在典型的运用程序中,多个业务并发运转,常常会操作相同的数据来完结各自的使《MySQL重要知识点及面试总结》:引荐保藏命(多个用户对共同数据进行操作)。并发尽管是有必要的,但或许会导致以下的问题。

            • 脏读(Dirty read): 当一个业务正在拜访数据而且对数据进行了修正,而这种修正还没有提交到数据库中,这时别的一个业务也拜访了这个数据,然后运用了这个数据。由于这个数据是还没有提交的数据,那么别的一个业务读到的这个数据是“脏数据”,依据“脏数据”所做的操作或许是不正确的。
            • 丢掉修正(Lost to modify): 指在一个业务读取一个数据时,别的一个业务也拜访了该数据,那么在榜首个业务中修正了这个数据后,第二个业务也修正了这个数据。这样榜首个业务内的修正成果就被丢掉,因而称为丢掉修正。例如:业务1读取某表中的数据A=20,业务2也读取A=20,业务1修正A=A-1,业务2也修正A=A-1,终究成果A=19,业务1的修正被丢掉。
            • 不行重复读(Unrepeatableread): 指在一个业务内屡次读同一数据。在这个业务还没有结束时,另一个业务也拜访该数据。那么,在榜首个业务中的两次读数据之间,由于第二个业务的修正导致榜首个业务两次读取的数据或许不太相同。这就发作了在一个业务内两次读到的数据是不相同的状况,因而称为不行重复读。
            • 幻读(Phantom read): 幻读与不行重复读相似。它舞女泪歌词发作在一个业务(T1)读取了几行数据,接着另一个并发业务(T2)刺进了一些数据时。在随后的查询中,榜首个业务(T1)就会发现多了一些本来不存在的记载,就好像发作了错觉相同,所以称为幻读。

            不行重复度和幻读差异:

            不行重复读的要点是修正,幻读的要点在于新增或《MySQL重要知识点及面试总结》:引荐保藏许删去。

            例1(相同的条件, 你读取过的数据, 再次读取出来发现值不相同了 ):业务1中的A先生读取自己的薪酬为 1000的操作还没完结,业务2中的B先生就修正了A的薪酬为2000,导 致A再读自己的薪酬时薪酬变为 2000;这便是不行重复读。

            例2(相同的条件, 第1次和第2次读出来的记载数不相同 ):假某薪酬单表中薪酬大于3000的有4人,业务1读取了一切薪酬大于3000的人,共查到4条记载,这时业务2 又刺进了一条薪酬大于3000的记载,业务1再次读取时查到的记载就变为了5条,这样就导致了幻读。

            业务阻隔等级有哪些?MySQL的默许阻隔等级是?

            SQL 《MySQL重要知识点及面试总结》:引荐保藏规范界说了四个阻隔等级:

            • READ-UNCOMMITTED(读取未提交): 最低的阻隔等级,答应读取没有提交的数据改变,或许会导致脏读、幻读或不行重复读
            • READ-COMMITTED(读取已提交): 答应读取并发业务现已提交的数据,能够阻挠脏读,可是幻读或不行重复读仍有或许发作
            • REPEATABLE-READ(可重复读): 对同一字段的屡次读取成果都是共同的,除非数据是被自身业务自己所修正,能够阻挠脏读和不行重复读,但幻读仍有或许发作
            • SERIALIZABLE(可串行化): 最高的阻隔等级,彻底遵守ACID的阻隔等级。一切的业务顺次逐一履行,这样业务之间就彻底不或许发作搅扰,也便是说,该等级能够防止脏读、不行重复读以及幻读

            阻隔等级 脏读 不行重复读 幻影读 READ-UNCOMMITTED √ √ √ READ-COMMITTED √ √ REPEATABLE-READ √ SERIALIZABLE MySQL InnoDB 存储引擎的默许支撑的阻隔等级是 REPEATABLE-READ(可重读)。咱们能够经过SELECT @@tx_isolation;指令来查看

            mysql> SELECT @@tx_isolation;
            +-----------------+
            | @@tx_isolation |
            +-----------------+
            | REPEATABLE-READ |
            +-----------------+
            仿制代码

            这儿需求留意的是:与 SQL 规范不同的当地在于InnoDB 存储引擎在 **REPEATABLE-READ(可重读)业务阻隔等级下运用的是Next-Key Lock 锁算法,因而能够防止幻读的发作,这与其他数据库体系(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默许支撑的阻隔等级是 REPEATABLE-READ(可重读) 现已能够彻底确保业务的阻隔性要求,即达到了 SQL规范的SERIALIZABLE(可串行化)**阻隔等级。

            由于阻隔等级越低,业务恳求的锁越少,所以大部分数据库体系的阻隔等级都是READ-COMMITTED(读取提交内容):,可是你要知道的是InnoDB 存储引擎默许运用 **REPEATABLE-READ(可重读)**并不会有任何功用丢失。

            InnoDB 存储引擎在 分布式业务 的状况下一般会用到**SERIALIZABLE(可串行化)**阻隔等级。

            索引相关

            为什么索引能进步查询速度

            以下内容收拾自: 地址: juejin.im/post/5b55b8… 作者 :Java3y

            先从 MySQL 的根本存储结构说起

            MySQL的根本存储结构是页(记载都存在页里边):

            • 各个数据页能够组成一个双向链表
            • 每个数据页中的记载又能够组成一个单向链表每个数《MySQL重要知识点及面试总结》:引荐保藏据页都会为存储在它里边儿的记载生成一个页目录,在经过主键查找某条记载的时分能够在页目录中运用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记载即可快速找到指定的记载
            • 以其他列(非主键)作为查找条件:只能从最小记载开端顺次遍历单链表中的每条记载。

            所以说,假如咱们写select * from user where indexname = 'xxx'这样没有进行任何优化的sql句子,默许会这样做:

            1. 定位到记载地点的页:需求遍历双向链表,找到地点的页
            2. 从地点的页内里查找相应的记载:由于不是依据主键查询,只能遍历地点页的单链表了

            很显着,在数据量很大的状况下这样查找会很慢!这样的时刻杂乱度为O(n)。

            索引做了些什么能够让咱们查询加快速度呢?其实便是将无序的数据变成有序(相对):

            要找到id为8的记载扼要过程:

            很显着的是:没有用索引咱们是需求遍历双向链表来定位对应的页,现在经过 “目录” 就能够很快地定位到对应的页上了!(二分查找,时刻杂乱度近似为O(logn))

            其实底层结构便是B+树,B+树作为树的一种完成,能够让咱们很快地查找出对应的记载。

            以下内容收拾自:《Java工程师修炼之道》

            什么是最左前缀准则?

            MySQL中的索引能够以必定次序引证多列,这种索引叫作联合索引。如User表的name和city加联合索引便是(name,city),而最左前缀准则指的是,假如查询的时分查询条件准确匹配索引的左面接连一列或几列,则此列就能够被用到。如下:

            select * from user where name=xx and city=xx ; //能够射中索引
            select * from user where name=xx ; // 能够射中索引
            select * from user where city=xx ; // 无法射中索引
            仿制代码

            这儿需求留意的是,查询的时分假如两个条件都用上了,可是次序不同,如 city= xx and name =xx,那么现在的查询引擎会主动优化为匹配联合索引的次序,这样是能够射中索引的。

            由于最左前缀准则,在创立联合索引时,索引字段的次序需求考虑字段值去重之后的个数,较多的放前面。ORDER BY子句也遵从此规矩。

            留意防止冗余索引

            冗余索引《MySQL重要知识点及面试总结》:引荐保藏指的是索引的功用相同,能够射中就肯定能射中 ,那么 便是冗余索引如(name,city )和(name )这两个索引便是冗余索引,能够射中后者的查询肯定是能够射中前者的 在大多数状况下,都应该尽量扩展已有的索引而不是创立新索引。

            MySQLS.7 版别后,能够经过查询 sys 库的 schema_redundant_indexes 表来查看冗余索引

            Mysql如何为表字段增加索引?

            1.增加PRIMARY KEY(主键索引)

            ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 
            仿制代码

            2.增加UNIQUE(仅有索引)

            ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 
            仿制代码

            3.增加INDEX(一般索引)

            ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
            仿制代码

            4.增加FULLTEXT(全文索引)

            ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 
            仿制代码

            5.增加多列索引

            ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
            仿制代码

            存储引擎

            一些常用指令

            查看MySQL供给的一切存储引擎

            mysql> show engines;
            仿制代码

            从上图咱们能够查看出 MySQL 当时默许的存储引擎是InnoDB,而且在5.7版别一切的存储引擎中只要 InnoDB 是业务性存储引擎,也便是说只要 InnoDB 支撑业务。

            查看MySQL当时默许的存储引擎

            咱们也能够经过下面的指令查看默许的存储引擎。

            mysql> show variables like '%storage_engine%';
            仿制代码

            查看表的存储引擎

            show table status like "table_name" ;
            仿制代码

            MyISAM和InnoDB差异

            MyISAM是MySQL的默许数据库引擎(5.5版之前)。尽管功用极佳,而且供给了许多的特性,包括全文索引、紧缩、空间函数等,但MyISAM不支撑业务和行级锁,而且最大的缺陷便是溃散后无法安全康复。不过,5.5版别之后,MySQL引入了InnoDB(业务性数据库引擎),MySQL 5.5版别后默许的存储引擎为InnoDB。

            大多数时分咱们运用的都是 InnoDB 存储引擎,可是在某些状况下运用 MyISAM 也是适宜的比方读密布的状况下。(假如你不介意 MyISAM 溃散回复问题的话)。

            两者的比照:

            1. 是否支撑行级锁 : MyISAM 只要表级锁(table-level locking),而InnoDB 支撑行级锁(row-level locking)和表级锁,默许为行级锁。
            2. 是否支撑业务和溃散后的安全康复: MyISAM 着重的是功用,每次查询具有原子性,其履行数度比InnoDB类型更快,可是不供给业务支撑。可是InnoDB 供给业务支撑业务,外部键等高档数据库功用。 具有业务(commit)、回滚(rollback)和溃散修正才干(crash recovery capabilities)的业务安全(transaction-safe (ACID compliant))型表。
            3. 是否支撑外键: MyISAM不支撑,而InnoDB支撑。
            4. 是否支撑MVCC :仅 InnoDB 支撑。应对高并发业务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个阻隔等级下作业;MVCC能够运用 达观(optimistic)锁 和 失望(pessimistic)锁来完成;各数据库中MVCC完成并不共同。引荐阅览:MySQL-InnoDB-MVCC多版别并发操控
            5. ......

            《MySQL高功用》上面有一句话这样写到:

            不要简单信任“MyISAM比InnoDB快”之类的经验之谈,这个定论往往不是肯定的。在许多咱们已知场景中,InnoDB的速度都能够让MyISAM望尘莫及,尤其是用到了聚簇索引,或许需求拜访的数据都能够放入内存的运用。

            一般状况下咱们挑选 InnoDB 都是没有问题的,可是某事状况下你并不在乎可扩展才干和并发才干,也不需求业务支撑,也不在乎溃散后的安全康复问题的话,挑选MyISAM也是一个不错的挑选。可是一般状况下,咱们都是需求考虑到这些问题的。

            达观锁与失望锁的差异

            失望锁

            总是假定最坏的状况,每次去拿数据的时分都以为他人会修正,所以每次在拿数据的时分都会上锁,这样他人想拿这个数据就会堵塞直到它拿到锁(同享资源每次只给一个线程运用,其它线程堵塞,用完后再把资源转让给其它线程)。传统的联系型数据库里边就用到了许多这种锁机制,比方行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁便是失望锁思维的完成。

            达观锁

            总是假定最好的状况,每次去拿数据的时分都以为他人不会修正,所以不会上锁,可是在更新的时分会判别一下在此期间他人有没有去更新这个数据,能够运用版别号机制和CAS算法完成。达观锁适用于多读的运用类型,这样能够进步吞吐量,像数据库供给的相似于write_condition机制,其实都是供给的达观锁。在Java中java.util.concurrent.atomic包下面的原子变量类便是运用了达观锁的一种完成办法CAS完成的。

            两种锁的运用场景

            从上面临两种锁的介绍,咱们知道两种锁各有优缺陷,不行以为一种好于另一种,像达观锁适用于写比较少的状况下(多读场景),即抵触真的很少发作的时分,这样能够省去了锁的开支,加大了体系的整个吞吐量。但假如是多写的状况,一般会常常发作抵触,这就会导致上层运用会不断的进行retry,这样反倒是降低了功用,所以一般多写的场景下用失望锁就比较适宜。

            达观锁常见的两种完成办法

            达观锁一般会运用版别号机制或CAS算法完成。

            1. 版别号机制

            一般是在数据表中加上一个数据版别号version字段,表明数据被修正的次数,当数据被修正时,version值会加一。当线程A要更新数据值时,在读取数据的一起也会读取version值,在提交更新时,若方才读取到的version值为当时数据库中的version值持平时才更新,不然重试更新操作,直到更新成功。

            举一个简略的比方: 假定数据库中帐户信息表中有一个 version 字段,当时值为 1 ;而当时帐户余额字段( balance )为 $100 。

            1. 操作员 A 此刻将其读出( version=1 ),并从其帐户余额中扣除 $50( $100-$50 )。
            2. 在操作员 A 操作的过程中,操作员B 也读入此用户信息( version=1 ),并从其帐户余额中扣除 $20 ( $100-$20 )。
            3. 操作员 A 完结了修正作业,将数据版别号加一( version=2 ),连同帐户扣除后余额( balance=$50 ),提交至数据库更新,此刻由于提交数据版别大于数据库记载当时版别,数据被更新,数据库记载 version 更新为 2 。
            4. 操作员 B 完结了操作,也将版别号加一( version=2 )企图向数据库提交数据( balance=$80 ),但此刻比对数据库记载版别时发现,操作员 B 提交的数据版别号为 2 ,数据库记载当时版别也为 2 ,不满足 “ 提交版别有必要大于记载当时版别才干履行更新 “ 的达观锁战略,因而,操作员 B 的提交被驳回。

            这样,就防止了操作员 B 用依据 version=1 的旧数据修正的成果掩盖操作员A 的操作成果的或许。

            2. CAS算法

            compare and swap(比较与交流),是一种有名的无锁算法。无锁编程,即不运用锁的状况下完成多线程之间的变量同步,也便是在没有线程被堵塞的状况下完成变量的同步,所以也叫非堵塞同步(Non-blocking Synchronization)。CAS算法触及到三个操作数

            • 需求读写的内存值 V
            • 进行比较的值 A
            • 拟写入的新值 B

            当且仅当 V 的值等于 A时,CAS经过原子办法用新值B来更新V的值,不然不会履行任何操作(比较和替换是一个原子操作)。一般状况下是一个自旋操作,即不断的重试

            关于自旋锁,咱们能够看一下这篇文章,十分不错:《 面试必备之深化了解自旋锁》

            达观锁的缺陷

            ABA 问题是达观锁一个常见的问题

            1 ABA 问题

            假如一个变量V初度读取的时分是A值,而且在预备赋值的时分查看到它仍然是A值,那咱们就能阐明它的值没有被其他线程修正过了吗?很显着是不能的,由于在这段时刻它的值或许被改为其他值,然后又改回A,那CAS操作就会误以为它从来没有被修正过。这个问题被称为CAS操作的 "ABA"问题。

            JDK 1.5 今后的 AtomicStampedReference 类就供给了此种才干,其间的 compareAndSet 办法便是首要查看当时引证是否等于预期引证,而且当时标志是否等于预期标志,假如悉数持平,则以原子办法将该引证和该标志的值设置为给定的更新值。

            2 循环时刻长开支大

            自旋CAS(也便是不成功就一向循环履行直到成功)假如长时刻不成功,会给CPU带来十分大的履行开支。 假如JVM能支撑处理器供给的pause指令那么功率会有必定的进步,pause指令有两个效果,榜首它能够推迟流水线履行指令(de-pipeline),使CPU不会耗费过多的履行资源,推迟的时刻取决于具体完成的版别,在一些处理器上推迟时刻是零。第二它能够防止在退出循环的时分因内存次序抵触(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),然后进步CPU的履行功率。

            3 只能确保一个同享变量的原子操作

            CAS 只对单个同享变量有用,当操作触及跨多个同享变量时 CAS 无效。可是从 JDK 1.5开端,供给了AtomicReference类来确保引证目标之间的原子性,你能够把多个变量放在一个目标里来进行 CAS 操作.所以咱们能够运用锁或许运用AtomicReference类把多个同享变量合并成一个同享变量来操作。

            锁机制与InnoDB锁算法

            MyISAM和InnoDB存储引擎运用的锁:

            • MyISAM 选用表级锁(table-level locking)。
            • InnoDB 支撑行级锁(row-level locking)和表级锁,默许为行级锁

            表级锁和行级锁比照:

            • 表级锁: Mysql中确定 粒度最大 的一种锁,对当时操作的整张表加锁,完成简略,资源耗费也比较少,加锁快,不会呈现死锁。其确定粒度最大,触发锁抵触的概率最高,并发度最低,MyISAM和 InnoDB引擎都支撑表级锁。
            • 行级锁: Mysql中确定 粒度最小 的一种锁,只针对当时操作的行进行加锁。 行级锁能大大削减数据库操作的抵触。其加锁粒度最小,并发度高,但加锁的开支也最大,加锁慢,会呈现死锁。

            具体内容能够参阅: Mysql锁机制简略了解一下

            InnoDB存储引擎的锁的算法有三种:

            • Record lock:单个行记载上的锁
            • Gap lock:空隙锁,确定一个规模,不包括记载自身
            • Next-key lock:record+gap 确定一个规模,包括记载自身

            相关知识点:

            1. innodb关于行的查询运用next-key lock
            2. Next-locking keying为了处理Phantom Problem幻读问题
            3. 当查询的索引含有仅有特点时,将next-key lock降级为record key
            4. Gap锁规划的意图是为了阻挠多个业务将记载刺进到同一规模内,而这会导致幻读问题的发作
            5. 有两种办法显式封闭gap锁:(除了外键束缚和仅有性查看外,其他状况仅运用record lock) A. 将业务阻隔等级设置为RC B. 将参数innodb_locks_unsafe_for_binlog设置为1

            大表优化

            当MySQL单表记载数过大时,数据库的CRUD功用会显着下降,一些常见的优化办法如下:

            1. 约束数据的规模

            必须制止不带任何约束数据规模条件的查询句子。比方:咱们当用户在查询订单前史的时分,咱们能够操控在一个月的规模内;

            2. 读/写别离

            经典的数据库拆分计划,主库担任写,从库担任读;

            3. 笔直分区

            依据数据库里边数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的根本信息,能够将用户表拆分红两个独自的表,乃至放到独自的库做分库。

            简略来说笔直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。 如下图所示,这样来说咱们应该就更简单了解了。

            • 笔直拆分的长处: 能够使得列数据变小,在查询时削减读取的Block数,削减I/O次数。此外,笔直分区能够简化表的结构,易于保护。
            • 笔直拆分的缺陷: 主键会呈现冗余,需求办理冗余列,并会引起Join操作,能够经过在运用层进行Join来处理。此外,笔直分区会让业务变得愈加杂乱;

            4. 水平分区

            坚持数据表结构不变,经过某种战略存储数据分片。这样每一片数据涣散到不同的表或许库中,达到了分布式的意图。 水平拆分能够支撑十分大的数据量。

            水平拆分是指数据表行的拆分,表的行数超越200万行时,就会变慢,这时能够把一张的表的数据拆成多张表来寄存。举个比方:咱们能够将用户信息表拆分红多个用户信息表,这样就能够防止单一表数据量过大对功用形成影响。

            水平拆分能够支撑十分大的数据量。需求留意的一点是:分表仅仅是处理了单一表数据过大的问题,但由于表的数据仍是在同一台机器上,其实关于进步MySQL并发才干没有什么含义,所以 水平拆分最好分库

            水平拆分能够 支撑十分大的数据量存储,运用端改造也少,但 分片业务难以处理 ,跨节点Join功用较差,逻辑杂乱。《Java工程师修炼之道》的作者引荐 尽量不要对数据进行分片,由于拆分会带来逻辑、布置、运维的各种杂乱度 ,一般的数据表在优化妥当的状况下支撑千万以下的数据量是没有太大问题的。假如实在要分片,尽量挑选客户端分片架构,这样能够削减一次和中心件的网络I/O。

            下面弥补一下数据库分片的两种常见计划:

            • 客户端署理: 分片逻辑在运用端,封装在jar包中,经过修正或许封装JDBC层来完成。 当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的完成。
            • 中心件署理: 在运用和数据中心加了一个署理层。分片逻辑共同保护在中心件服务中。 咱们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的完成。

            重视作者:JAVA高档程序员

            我会不定期在微头条发放:(Java工程化、分布式架构、高并发、高功用、深化浅出、微服务架构、Spring、MyBatis、Netty、源码剖析)等技能学习材料,以及Java进阶学习路线图。

            请关注微信公众号
            微信二维码
            不容错过
            Powered By Z-BlogPHP