文章列表

MySQL面试高频一百问

作者:微信小助手

<p style="white-space: normal;max-width: 100%;min-height: 1em;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: Optima-Regular, PingFangTC-light;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 16px;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color: rgb(127, 127, 127);max-width: 100%;font-size: 14px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击上方“</span><span style="max-width: 100%;font-size: 14px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color: rgb(0, 176, 240);">服务端思维</span></span><span style="color: rgb(127, 127, 127);max-width: 100%;font-size: 14px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">”,选择“</span></span><span style="color: rgb(136, 136, 136);max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">设为星标</span><span style="color: rgb(127, 127, 127);max-width: 100%;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”</span></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: Optima-Regular, PingFangTC-light;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;color: rgb(127, 127, 127);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">回复”</span><span style="max-width: 100%;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 122, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">669</span><span style="max-width: 100%;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;color: rgb(127, 127, 127);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">“获取独家整理的精选资料集</span></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: Optima-Regular, PingFangTC-light;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;color: rgb(127, 127, 127);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">回复”</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(0, 122, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">加群</span><span style="max-width: 100%;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">“加入全国服务端高端社群「后端圈」</span></span></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section powered-by="xiumi.us" style="white-space: normal;"> <section> <section> <section> <p style="text-align: center;"><img class="" data-cropselx1="0" data-cropselx2="562" data-cropsely1="0" data-cropsely2="375" data-ratio="0.6666666666666666" src="/upload/752f2357abb18ffb47778a69733f4575.jpg" data-type="jpeg" data-w="510" style="height: 375px;color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;width: 563px;"></p> <p><span style="max-width: 100%;color: rgb(136, 136, 136);font-size: 12px;letter-spacing: 0.7px;font-family: &quot;Tahoma For Number&quot;, &quot;Chinese Quote&quot;, -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者 |&nbsp;呼延十</span><br></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color: rgb(136, 136, 136);font-size: 12px;letter-spacing: 0.7px;font-family: &quot;Tahoma For Number&quot;, &quot;Chinese Quote&quot;, -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;text-align: start;">出品 |&nbsp;http://h5ip.cn/mPaC</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(171, 25, 66);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: bold;letter-spacing: 0.544px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">前言</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水.</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面试文章,发现其中的一些问题自己也回答不好,虽然知识点大部分都知道,但是无法将知识串联起来.</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">因此决定搞一个MySQL灵魂100问,试着用回答问题的方式,让自己对知识点的理解更加深入一点.</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">此文不会事无巨细的从select的用法开始讲解mysql,主要针对的是开发人员需要知道的一些MySQL的知识点,主要包括索引,事务,优化等方面,以在面试中高频的问句形式给出答案.</span></p> <h2 style="margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.4em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(0, 184, 212);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;line-height: inherit;font-size: 17px;color: rgb(171, 25, 66);box-sizing: border-box !important;overflow-wrap: break-word !important;">索引相关</span><span style="max-width: 100%;color: inherit;line-height: inherit;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">关于MySQL的索引,曾经进行过一次总结,文章链接在这里&nbsp;Mysql索引原理及其优化.</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">1. 什么是索引?</span></strong></span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">索引是一种数据结构,可以帮助我们快速的进行数据的查找.</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&q

MySQL执行show processlist显示的结果中status状态总结

作者:不要哭啦

一般情况下,DBA能从监控mysql的状态列表中查看出数据库的运行端倪,需要注意的是STATUS所表示的不同内容。且需要注意的是TIME字段表示的意思。它表示的只是最后那个STAT状态持续的时间。这个时间是有可能忽大忽小的。而不是SQL开始执行到现在的时间。单位时间是秒。 After create This occurs when the thread creates a table (including internal temporary tables), at the end of the function that creates the table. This state is used even if the table could not be created due to some error. 这个状态当线程创建一个表(包括内部临时表)时,在这个建表功能结束时出现。即使某些错误导致建表失败,也会使用这个状态。 Analyzing The thread is calculating a MyISAM table key distributions (for example, for ANALYZE TABLE). 当计算MyISAM表索引分布时。(比如进行ANALYZE TABLE时) checking permissions The thread is checking whether the server has the required privileges to execute the statement. 这个线程检查服务器是否有具有执行该语句的所需权限。 Checking table The thread is performing a table check operation. 线程正在执行表检查操作。 cleaning up The thread has processed one command and is preparing to free memory and reset certain state variables. 线程处理一个命令,并正准备释放内存和重置某些状态变量。 closing tables The thread is flushing the changed table data to disk and closing the used tables. This should be a fast operation. If not, verify that you do not have a full disk and that the disk is not in very heavy use. 线程正在将变更的表中的数据刷新到磁盘上并正在关闭使用过的表。这应该是一个快速的操作。如果不是这样的话,则应该检查硬盘空间是否已满或者硬盘IO是否达到瓶颈。 converting HEAP to MyISAM The thread is converting an internal temporary table from a MEMORY table to an on-disk MyISAM table. 线程将一个内部临时表转换为磁盘上的MyISAM表。 copy to tmp table The thread is processing an ALTER TABLE statement. This state occurs after the table with the new structure has been created but before rows are copied into it. 线程正在处理一个ALTER TABLE语句。这个状态发生在新的表结构已经创建之后,但是在数据被复制进入之前。 Copying to group table If a statement has different ORDER BY and GROUP BY criteria, the rows are sorted by group and copied to a temporary table. 如果一个语句有不同的ORDER BY和GROUP BY条件,数据会被复制到一个临时表中并且按组排序。 Copying to tmp table The server is copying to a temporary table in memory. 线程将数据写入内存中的临时表。 正在创建临时表以存放部分查询结果 Copying to tmp table on disk The server is copying to a temporary table on disk. The temporary result set has become too large (see Section 8.4.3.3, “How MySQL Uses Internal Temporary Tables”). Consequently, the thread is changing the temporary table from in-memory to diskbased format to save memory. 线程正在将数据写入磁盘中的临时表。临时表的结果集过大(大于tmp_table_size)。所以,线程将临时表由基于内存模式改为基于磁盘模式,以节省内存。 Creating index The thread is processing ALTER TABLE … ENABLE KEYS for a MyISAM table. 线程正在对一个MyISAM表执行ALTER TABLE … ENABLE KEYS语句。 Creating sort index The thread is processing a SELECT that is resolved using an internal temporary table. 线程正在使用内部临时表处理一个SELECT 操作。 creating table The thread is creating a table. This includes creation of temporary tables. 线程正在创建一个表,包括创建临时表。 Creating tmp table The thread is creating a temporary table in memory or on disk. If the table is created in memory but later is converted to an ondisk table, the state during that operation will be Copying to tmp table on disk. 线程正在创建一个临时表在内存或者磁盘上。如果这个表创建在内存上但是之后被转换到磁盘上,这个状态在运行Copying to tmp table on disk 的时候保持。 deleting from main table The server is executing the first part of a multiple-table delete. It is deleting only from the first table, and saving columns and offsets to be used for deleting from the other (reference) tables. 线程正在执行多表删除的第一部分,只从第一个表中删除。并且保存列和偏移量用来从其他(参考)表删除。 deleting from reference tables The server is executing the second part of a multiple-table delete and deleting the matched rows from the other tables. 线程正在执行多表删除的第二部分,并从其他表中删除匹配的行。 discard_or_import_tablespace The thread is processing an ALTER TABLE … DISCARD TABLESPACE or ALTER TABLE … IMPORT TABLESPACE statement. 线程正在执行ALTER TABLE … DISCARD TABLESPACE 或 ALTER TABLE … IMPORT TABLESPACE语句。 end This occurs at the end but before the cleanup of ALTER TABLE, CREATE VIEW, DELETE, INSERT, SELECT, or UPDATE statements. 这个状态出现在结束时,但是在对ALTER TABLE, CREATE VIEW, DELETE, INSERT, SELECT, 或者 UPDATE 语句进行清理之前。 executing The thread has begun executing a statement. 该线程已开始执行一条语句。 Execution of init_command The thread is executing statements in the value of the init_command system variable. 线程正在执行处于init_command系统变量的值中的语句。 freeing items The thread has executed a command. Some freeing of items done during this state involves the query cache. This state is usually followed by cleaning up. 线程已经执行了命令。在这个状态中涉及的查询缓存可以得到一些释放。这个状态通常后面跟随cleaning up状态。 Flushing tables The thread is executing FLUSH TABLES and is waiting for all threads to close their tables. 线程正在执行FLUSH TABLES 并且等待所有线程关闭他们的表。 FULLTEXT initialization The server is preparing to perform a natural-language full-text search. 服务器正在准备进行自然语言全文检索。 init This occurs before the initialization of ALTER TABLE, DELETE, INSERT, SELECT, or UPDATE statements. Actions taken by the server in this state include flushing the binary log, the InnoDB log, and some query cache cleanup operations. For the end state, the following operations could be happening: Removing query cache entries after data in a table is changed Writing an event to the binary log Freeing memory buffers, including for blobs 这个状态出现在线程初始化ALTER TABLE, DELETE, INSERT, SELECT, 或 UPDATE语句之前。服务器在这种状态下进行的操作,包括:刷新全日志、Innodb日志,和一些查询缓存清理操作。 对于end状态,可能会发生下列操作: 在表中的数据变更之后移除查询缓存。 将事务写入全日志。 释放内存缓冲区,包括大的二进制数据块。 Killed Someone has sent a KILL statement to the thread and it should abort next time it checks the kill flag. The flag is checked in each major loop in MySQL, but in some cases it might still take a short time for the thread to die. If the thread is locked by some other thread, the kill takes effect as soon as the other thread releases its lock. 程序对线程发送了KILL语句,并且它应该放弃下一次对KILL标记的检查。这个标记在每一个MySQL的主要循环中被检查,但在某些情况下,它可能需要令线程在很短的时间内死亡。如果这个线程被其他线程锁住了,这个KILL操作会在其他线程释放锁的瞬时执行。 Locked The query is locked by another query. As of MySQL 5.5.3, this state was removed because it was equivalent to the Table lock state and no longer appears in SHOW PROCESSLIST output. 这个查询被其他查询锁住了。 在MySQL 5.5.3版本,这个状态被移除了。因为它相当于表锁状态,并且不再出现在SHOW PROCESSLIST输出中。 logging slow query The thread is writing a statement to the slow-query log. 这个线程正在将语句写入慢查询日志。 NULL This state is used for the SHOW PROCESSLIST state. 没有操作的状态。 login The initial state for a connection thread until the client has been authenticated successfully. 线程连接的初始状态。直到客户端已经成功验证。 manage keys The server is enabling or disabling a table index. 服务器启用或禁用表索引。 Opening tables, Opening table The thread is trying to open a table. This is should be very fast procedure, unless something prevents opening. For example, an ALTER TABLE or a LOCK TABLE statement can prevent opening a table until the statement is finished. It is also worth checking that your table_open_cache value is large enough. 线程正试图打开一张表。这应该是非常快的过程,除非打开受到阻止。一个ALTER TABLE 或LOCK TABLE语句能够阻止打开一张表直到语句运行结束。有必要检查table_open_cache的值是否足够大。 optimizing The server is performing initial optimizations for a query. 服务器执行查询的初步优化。 preparing This state occurs during query optimization. 在查询优化过程中出现这个状态。 Purging old relay logs The thread is removing unneeded relay log files. 线程正在移除不必要的中继日志文件。 query end This state occurs after processing a query but before the freeing items state. 这个状态出现在处理一个查询之后,但是在freeing items状态之前。 Reading from net The server is reading a packet from the network. 服务器正在从网络阅读数据包。 Removing duplicates The query was using SELECT DISTINCT in such a way that MySQL could not optimize away the distinct operation at an early stage. Because of this, MySQL requires an extra stage to remove all duplicated rows before sending the result to the client. 查询正在使用SELECT DISTINCT,这种情况下MySQL不能在早期阶段优化掉一些distinct操作。因此,MySQL需要一个额外的阶段,在将结果发送到客户端之前删除所有重复的行。 removing tmp table The thread is removing an internal temporary table after processing a SELECT statement. This state is not used if no temporary table was created. 线程正在移除一个内置临时表,在执行一条SELECT语句之后。 如果没有临时表产生,那么这个状态不被使用。 rename The thread is renaming a table. 线程正在重命名一张表。 rename result table The thread is processing an ALTER TABLE statement, has created the new table, and is renaming it to replace the original table. 线程正在处理ALTER TABLE语句,创建新的表,并且重命名它来代替原有的表。 Reopen tables The thread got a lock for the table, but noticed after getting the lock that the underlying table structure changed. It has freed the lock, closed the table, and is trying to reopen it. 线程获得了表锁,但是在取得表锁之后才发现该表的底层结构已经发生了变化。线程释放这个锁,关闭表,并试图重新打开该表。 Repair by sorting The repair code is using a sort to create indexes. 修复代码正在使用一个分类来创建索引。 Repair done The thread has completed a multi-threaded repair for a MyISAM table. 线程完成一个多线程的MyISAM表的修复。 Repair with keycache The repair code is using creating keys one by one through the key cache. This is much slower than Repair by sorting. 修复代码正在通过索引缓存一个接一个地使用创建索引。这比通过分类修复要慢很多。 Rolling back The thread is rolling back a transaction. 线程正在回滚一个事务 Saving state For MyISAM table operations such as repair or analysis, the thread is saving the new table state to the .MYI file header. State includes information such as number of rows, the AUTO_INCREMENT counter, and key distributions. 对于MyISAM表的类似repair或analysis操作,线程在.MYI文件的头部保存一个新表的状态。状态信息包括行数、自增数、索引分布等等。 Searching rows for update The thread is doing a first phase to find all matching rows before updating them. This has to be done if the UPDATE is changing the index that is used to find the involved rows. 线程正在进行第一阶段,在更新前寻找所有匹配的行。如果update正在更改用于查找相关行的索引,则必须这么做。 Sending data The thread is reading and processing rows for a SELECT statement, and sending data to the client. Because operations occurring during this this state tend to perform large amounts of disk access (reads), it is often the longest-running state over the lifetime of a given query. 线程正在读取和处理一条SELECT语句的行,并且将数据发送至客户端。由于在此期间会执行大量的磁盘访问(读操作),这个状态在一个指定查询的生命周期中经常是耗时最长的。 setup The thread is beginning an ALTER TABLE operation. 线程正开始进行一个ALTER TABLE操作。 Sorting for group The thread is doing a sort to satisfy a GROUP BY. 线程正在执行一个由GROUP BY指定的排序。 Sorting for order The thread is doing a sort to satisfy a ORDER BY. 线程正在执行一个由ORDER BY指定的排序。 Sorting index The thread is sorting index pages for more efficient access during a MyISAM table optimization operation. 线程正在对索引页进行排序,为了对MyISAM表进行操作时获得更优的性能。 Sorting result For a SELECT statement, this is similar to Creating sort index, but for nontemporary tables. 对于一个SELECT语句,这与创建排序索引相似,但是是对非临时表。 statistics The server is calculating statistics to develop a query execution plan. If a thread is in this state for a long time, the server is probably disk-bound performing other work. 服务器计算统计去规划一个查询。如果一个线程长时间处于这个状态,这个服务器的磁盘可能在执行其他工作。 System lock The thread is going to request or is waiting for an internal or external system lock for the table. If this state is being caused by requests for external locks and you are not using multiple mysqld servers that are accessing the same MyISAM tables, you can disable external system locks with the –skip-external-locking option. However, external locking is disabled by default, so it is likely that this option will have no effect. For SHOW PROFILE, this state means the thread is requesting the lock (not waiting for it). 这个线程正在请求或者等待一个内部的或外部的系统表锁。如果这个状态是由于外部锁的请求产生的,并且你没有使用多个正在访问相同的表的mysqld服务器,那么你可以使用–skip-external-locking选项禁用外部系统锁。然而,外部系统锁默认情况下禁用,因此这个选项可能不会产生效果。对于SHOW PROFILE,这个状态意味着线程正在请求锁。(而非等待) Table lock The next thread state after System lock. The thread has acquired an external lock and is going to request an internal table lock. This state was replaced in MySQL 5.5.6 with Waiting for table level lock. 系统锁定后的下一个线程状态。线程已获得外部锁并且将请求内部表锁。 这个状态在MySQL 5.5.6版本中被Waiting for table level lock取代。 Updating The thread is searching for rows to update and is updating them. 线程寻找更新匹配的行并进行更新。 updating main table The server is executing the first part of a multiple-table update. It is updating only the first table, and saving columns and offsets to be used for updating the other (reference) tables. 线程正在执行多表更新的第一部分,只从第一个表中更新。并且保存列和偏移量用来从其他(参考)表更新。 updating reference tables The server is executing the second part of a multiple-table update and updating the matched rows from the other tables. 线程正在执行多表更新的第二部分,并从其他表中更新匹配的行。 User lock The thread is going to request or is waiting for an advisory lock requested with a GET_LOCK() call. For SHOW PROFILE, this state means the thread is requesting the lock (not waiting for it). 线程正在请求或等待一个GET_LOCK()调用所要求的咨询锁。对于SHOW PROFILE,这个状态意味这线程正在请求锁。(而非等待) User sleep The thread has invoked a SLEEP() call. 线程调用了一个SLEEP()。 Waiting for all running commits to finish A statement that causes an explicit or implicit commit is waiting for release of a read lock. This state was removed in MySQL 5.5.8; Waiting for commit lock is used instead. 一个显式或隐式语句在提交时等待释放读锁。这个状态在MySQL 5.5.8版本中被移除,以Waiting for commit lock代替。 Waiting for commit lock A statement that causes an explicit or implicit commit is waiting for release of a read lock or FLUSH TABLES WITH READ LOCK) is waiting for a commit lock. This state was added in MySQL 5.5.8. 同上,这个状态于MySQL 5.5.8版本加入。 Waiting for global read lock FLUSH TABLES WITH READ LOCK) is waiting for a global read lock. 等待全局读锁。 Waiting for release of readlock The thread is waiting for a global read lock obtained by another thread (with FLUSH TABLES WITH READ LOCK) to be released.This state was removed in MySQL 5.5.8; Waiting for global read lock or Waiting for commit lock are used instead. 等待释放读锁。 Waiting for tables, Waiting for table, Waiting for table flush The thread got a notification that the underlying structure for a table has changed and it needs to reopen the table to get the new structure. However, to reopen the table, it must wait until all other threads have closed the table in question. This notification takes place if another thread has used FLUSH TABLES or one of the following statements on the table in question: FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, or OPTIMIZE TABLE. In MySQL 5.5.6, Waiting for table was replaced with Waiting for table flush. 线程获得一个通知,底层表结构已经发生变化,它需要重新打开表来获取新的结构。然而,重新打开表,它必须等到所有其他线程关闭这个有问题的表。 这个通知产生通常因为另一个线程对问题表执行了FLUSH TABLES或者以下语句之一:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, or OPTIMIZE TABLE. Waiting for lock_type lock The server is waiting to acquire a lock, where lock_type indicates the type of lock: Waiting for event metadata lock (added in MySQL 5.5.8) Waiting for global metadata lock (replaced by Waiting for global read lock in MySQL 5.5.8) Waiting for global read lock (added in MySQL 5.5.8) Waiting for schema metadata lock Waiting for stored function metadata lock Waiting for stored procedure metadata lock Waiting for table level lock Waiting for table metadata lock Waiting for trigger metadata lock (added in MySQL 5.5.8) 等待各个种类的表锁。 Waiting on cond A generic state in which the thread is waiting for a condition to become true. No specific state information is available. 一个普通的状态,线程正在等待一个条件为真。没有特定的状态信息可用。 Waiting to get readlock The thread has issued a FLUSH TABLES WITH READ LOCK statement to obtain a global read lock and is waiting to obtain the lock. This state was removed in MySQL 5.5.8; Waiting for global read lock is used instead. 线程发出了一个FLUSH TABLES WITH READ LOCK语句来获取一个全局读锁,并且等待获得这个锁。这个状态在MySQL 5.5.8被移除,使用Waiting for global read lock 来代替。 Writing to net The server is writing a packet to the network. 服务器正在写一个网络数据包。

面试阿里?如果对别人开源的 RocketMQ 了如指掌,岂不是很加分!

作者:微信小助手

<p style="white-space: normal;" data-mpa-powered-by="yiban.io"><img class="" data-ratio="0.6666666666666666" data-type="png" data-w="127" src="/upload/4c8b91599182ea5ba1ead110e9271956.png" style="height: 55px;vertical-align: bottom;width: 102px;"><br></p> <p style="white-space: normal;color: rgb(153, 80, 51);line-height: normal;"><span style="font-size: 15px;letter-spacing: 1px;">还没关注?伸出中指点这里!</span></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: right;line-height: 2em;"><strong><em style="text-align: right;white-space: normal;font-size: 12px;">转载请联系</em><span style="text-align: right;font-size: 12px;color: rgb(64, 179, 230);">【狸猫技术窝】</span><em style="text-align: right;white-space: normal;font-size: 12px;">获取授权</em></strong></p> <section class="KolEditor" data-tools-id="85858" style="white-space: normal;"> <section class="Powered-by-KolEditor V5" powered-by="KolEditor.us"> <section class=""> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-top: -40px;margin-right: 1.5em;margin-left: 1.5em;padding: 10px;background-color: rgb(226, 230, 0);"> <section class="Powered-by-KolEditor V5" powered-by="KolEditor.us"> <section class=""> <section class="" style="text-align: center;color: rgb(255, 255, 255);"> <section> <span style="color: rgb(0, 0, 0);font-size: 15px;">聊技术、论职场!</span> </section> <section> <span style="color: rgb(0, 0, 0);"><span style="font-size: 15px;">为IT人打造一个“有温度”的</span><strong style="font-size: 15px;"><span style="color: rgb(201, 56, 28);">狸猫技术窝</span></strong></span> </section> </section> </section> </section> </section> </section> </section> </section> <p style="line-height: 2em;">作者:<em><strong>原子弹大侠</strong></em><br></p> <p style="white-space: normal;line-height: 2em;"><em><span style="font-size: 16px;"><strong><span style="font-size: 16px;color: rgb(64, 179, 230);">狸猫技术窝&nbsp;</span></strong></span></em><span style="font-size: 16px;"><strong><span style="font-size: 16px;color: rgb(64, 179, 230);"></span></strong><span style="font-size: 15px;"><span style="font-size: 16px;">特约作者,<span style="color: rgb(25, 31, 37);white-space: pre-wrap;">阿里 P8 高级技术专家</span></span></span></span></p> <p><br></p> <p><br></p> <section class="KolEditor"> <section style="padding: 20px;margin-right: auto;margin-left: auto;background-image: url(https://mmbiz.qpic.cn/mmbiz_png/vnOqylzBGCRNRFasUZTdSrnKiasPJRbicaSnStfclB7YtR607AAtLXNU1LPQ0PJfCcZyXPxLGUz8sYIbNfYszbjg/640?wx_fmt=png);background-size: 100%;background-position: left top;background-repeat: repeat;"> <section style="padding:5px;"> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(1)RocketMQ整体架构</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">如今阿里的开源项目越来越多,比如消息中间件领域的RocketMQ,分布式事务领域的Fescar,熔断限流领域的Sentinal,微服务领域的Dubbo、Nacos等等。<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">而现在越来越多的中小型公司也开始使用阿里开源的各种技术到自己的系统,因此有必要对阿里开源的一些技术的核心工作原理进行了解。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">本文就对消息中间件领域的 RocketMQ 进行原理的分析。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">首先,RocketMQ整体架构中包含了4种角色:</span></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">NameServer</span></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">Broker</span></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">Producer</span></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">Consumer</span></p><p><br></p></li> </ul> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">其中NameServer相当于集群管理服务,主要用于管理整个集群的元数据以及对集群进行管理的。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">Broker相当于单个节点负责数据的读写的,而Producer就是负责生产消息后写入Broker的,Consumer则是从Broker来消费消息。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">而且Broker在部署的时候,一般是分为主备角色的。也就是说,每个Broker都部署一个Master角色在一台机器上,然后另外会部署一个Slave角色在另外一台机器上。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">这样如果某个Broker Master挂了,他的Broker Slave就可以接替继续工作,保证了高可用。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">下图阐述了RocketMQ的整体架构原理:</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="Tencent-attachment-1555491141948-576df81d6bf8d062 author-p-53348239 attrimg img"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="895" src="/upload/ca942516e91abb9b6cc893009a6a81a6.png"></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(2)RocketMQ 工作流程</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">首先需要先启动NameServer,接着启动Broker<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">Broker启动之后就会跟NameServer建立长连接,每隔一段时间发送心跳包过去</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">心跳包里需要包含自己当前存储的数据信息,让NameServer感知到各个Broker的情况,如下图:</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="Tencent-attachment-1555491459261-58a99100816fbade author-p-53348239 attrimg img"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="872" src="/upload/3ae439fe6fa8edaec82eada2608398fc.png"></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">然后呢?你可以创建 Topic,创建 Topic 的时候就会决定这个 Topic 的数据会放在哪些Broker上。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">每个Broker在进行心跳的时候,就可以上报自己当前存储的Topic相关的数据信息给NameServer知道了。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">而NameServer就保存了整个集群的元数据,知道每个Topic当前数据保存在哪些Broker上,如下图:</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="Tencent-attachment-1555492036397-bfa8e9c222dd6eed author-p-53348239 attrimg img"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="929" src="/upload/3d24f3d6b957339cae16f4cc74e67770.png"></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">Producer在生产消息到Topic的时候,先得找NameServer问一下Topic存放在哪些Broker上,然后就可以跟那些Broker建立连接发送消息过去了。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">Consumer要从Topic消费消息,也会找NameServer问一下可以从哪些Broker上消费消息,接着同样会跟Broker建立连接并且开始消费消息,如下图。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="Tencent-attachment-1555492382686-9b2696ceaf1faff4 author-p-53348239 attrimg img"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="921" src="/upload/e79e806524cec9af8de1d70c8de05a5c.png"></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(3)NameServer原理分析</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="author-p-53348239" style="letter-spacing: 2px;">NameServer一般是集群化部署,各个机器上部署的NameServer会互相同步收到的元数据,保证各个NameServer上包含的集群元数据都是相同的。这样的架构可以保证即使任何一个NameServer宕机了也不要紧。<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">NameServer主要的责任就是管理Broker的心跳,如果有人一段时间内没心跳,那么就认为那个Broker已经宕机了,此时要触发对应的Slave切换为Master保证高可用。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">此外,NameServer还要负责管理和维护集群元数据,比如有哪些Topic,每个Topic在哪些Broker上。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">NameServer承受的请求压力是很小的,因为心跳和拉取元数据,其实是很低频的行为,所以一般<strong>部署两三台机器</strong>就足够了。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">但是需要注意的是 ,如果集群里维护了几十万个,甚至几百万个Topic,会导致Broker每次心跳上报Topic数据时,带上几十万个Topic的数据信息,可能多达几十MB,那会导致心跳时网络负载过重。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(4)分布式架构分析</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="author-p-53348239" style="letter-spacing: 2px;">再说说Topic,每个Topic都由很多个队列组成,一个队列代表了这个Topic的部分数据,然后这个Topic的多个队列会均匀分散在多个Broker上。<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">比如说Topic有6个队列,对应有三台Broker,那么每个Broker上就可以放2个队列的数据。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">这样就可以做到每个Topic的数据都可以分布式存储在集群中的多台Broker上,形成了分布式的存储架构,这样就可以利用多台机器的资源来存储数据。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">同时,可以利用多台机器的资源来应对高并发的请求,因为对一个Topic的读写请求,就会均匀的落到多台Broker机器上去了。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">如下图所示,可以看到数据分布式存储的架构。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="Tencent-attachment-1555493494275-5a6cab3b607590b9 author-p-53348239 attrimg img"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="934" src="/upload/59b6690c0cde310fd02b689ef7a1e262.png"></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(5)Broker原理分析</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="author-p-53348239" style="letter-spacing: 2px;">Broker主要就是两点:负责接收Producer写入的消息,同时提供消息给Consumer来读取。<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;"><strong><span style="color: rgb(201, 56, 28);">写入消息时</span></strong>,Broker可以实现高并发高性能的写入。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">这个主要采用的是对磁盘文件进行顺序写的方式,磁盘顺序写的性能是很高的,几乎跟内存随机读写的性能差不多。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">另外,就是优先把数据写入os page cahce,也就是操作系统管理的缓存中。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">写操作系统的内存缓存,那性能就更高了,不需要每次都直接写入物理磁盘中。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;"><span style="color: rgb(201, 56, 28);"><strong>读取消息时</strong></span>,Broker也是主要基于os page cahce读取消息,也就是优先从操作系统管理的内存缓存中读取数据,提供给Consumer来消费。因为是优先读内存,所以同样性能也是很高的。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">通过这种架构,Broker就可以保证高并发以及高性能。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">另外,Broker还实现了高可用的架构。也就是说每个Broker Master都会把自己接收到的数据同步给Broker Slave,实现每个Broker上的数据备份。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">如果Broker Master宕机了,会切换Broker Slave对外提供服务,保证了高可用的架构。</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(6)Consumer原理分析</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">如果我们部署了Consumer在多台机器上,默认也会把Topic下的多个队列的数据均匀的分配给各个Consumer实例来进行消费。<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">比如Topic下一共6个队列,假设部署了3个Consumer实例,此时每个Consumer实例就会消费2个队列的数据,如下图:</span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="Tencent-attachment-1555493795586-ed2deddedc8a4b21 author-p-53348239 attrimg img"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="941" src="/upload/aba341acc992c63658a2a2b70a350dcf.png"></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <p style="white-space: normal;line-height: 2em;"><br></p> <section class="KolEditor" data-tools-id="93344" style="white-space: normal;"> <section style="margin-top: 10px;margin-bottom: 10px;display: flex;justify-content: flex-start;align-items: flex-end;"> <section style="padding: 2px 10px;border-bottom: 1px solid rgb(0, 0, 0);"> <p style="font-size: 15px;text-align: center;"><span style="font-weight: bold;">(7)总结</span></p> </section> <section style="width: 32px;flex-shrink: 0;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="30" src="/upload/524ef0d8d30cff0cd3a6c5ade18e1ec9.png" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p style="white-space: normal;"><br></p> <p style="white-space: normal;line-height: 2em;"><span class="author-p-53348239" style="letter-spacing: 2px;">对于任何一个消息系统,对他的原理进行研究的时候,都应该关注几点:<br></span></p> <p style="white-space: normal;line-height: 2em;"><br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">集群架构(元数据如何管理、集群如何管理)</span></p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">数据模型(Topic、队列等概念)</span></p><p><br></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">分布式架构(消息如何分布式存储)</span></p><p><br></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">消息写入以及读取的原理</span></p><p><br></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">高可用架构(如何进行数据冗余)</span></p><p><br></p></li> <li><p style="line-height: 2em;"><span style="letter-spacing: 2px;">客户端原理</span></p><p><br></p></li> </ul> <p style="white-space: normal;line-height: 2em;"><span style="letter-spacing: 2px;">把这些弄明白之后,才算对一个消息系统有了一定的了解,才能开始尝试把这个消息系统应用于自己公司的生产项目中。</span></p> </section> </section> </section> <p style="white-space: normal;text-align: center;"><span style="font-size: 24px;color: rgb(255, 0, 0);"><strong>END</strong></span><span style="color: rgb(57, 137, 31);font-size: 24px;"></span></p> <p style="white-space: normal;text-align: center;"><br></p> <section class="KolEditor" style="white-space: normal;"> <section style="margin: 10px;padding: 17px 10px 15px 16px;border-width: 1px;border-style: solid;border-color: rgb(246, 73, 13);display: flex;align-items: center;justify-content: center;flex-direction: column;"> <section style="padding-bottom: 5px;display: flex;align-items: center;justify-content: flex-start;border-bottom: 4px solid rgb(246, 73, 13);width: 508px;align-self: flex-start;"> <p style="font-size: 18px;color: rgb(246, 73, 13);font-weight: bold;"><span style="color: rgb(255, 76, 0);">作者简介:</span><span style="color: rgb(40, 40, 40);">&nbsp;</span></p> <p style="margin-left: 20px;font-size: 15px;color: rgb(40, 40, 40);"><br></p> </section> <section style="margin-top: 13px;padding-right: 10px;padding-left: 10px;"> <p style="font-size: 18px;color: rgb(246, 73, 13);font-weight: bold;"><span style="color: rgb(25, 31, 37);white-space: pre-wrap;background-color: rgb(255, 255, 255);font-size: 15px;">原子弹大侠,阿里 P8 高级技术专家</span><br></p> <p style="line-height: 2em;"><span style="color: rgb(25, 31, 37);text-align: left;white-space: pre-wrap;background-color: rgb(255, 255, 255);font-size: 14px;">经历过每日百亿流量的互联网系统架构,尤其对上亿用户场景下的高并发系统架构设计以及性能优化相关领域有深入的研究。</span></p> </section> </section> </section> <p style="white-space: normal;text-align: center;"><br></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="font-size: 14px;">长按下图二维码,即刻关注【<span style="color: rgb(241, 136, 35);"><strong>狸猫技术窝</strong></span>】</span></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 14px;letter-spacing: 0.544px;">阿里、京东、美团、字节跳动</span><br></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="font-size: 14px;"><strong><span style="font-size: 13px;color: rgb(0, 0, 0);">顶尖技术专家</span></strong><span style="font-size: 13px;color: rgb(0, 0, 0);">坐镇</span></span></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 14px;">为IT人打造一个 “有温度” 的技术窝!</span></p> <section class="KolEditor" data-tools-id="79539" style="white-space: normal;"> <section style="margin: 10px auto;display: flex;justify-content: center;align-items: center;"> <section style="padding: 30px;background-image: url(https://mmbiz.qpic.cn/mmbiz_gif/vnOqylzBGCQHu6jrGZMlKlQlriarYFuN2jzLbPCJRlbydFZSlxHHLALHPenWJGC9WFtiaRFyMvicibKbv6nwdHibbiaw/640?wx_fmt=gif);background-position: center center;background-repeat: repeat;"> <p style="text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="0.6666666666666666" data-s="300,640" data-type="jpeg" data-w="258" src="/upload/578288c965b89f74b583291d3fc98c86.jpg"></p> </section> </section> </section> <p><br></p>

基于MySQL数据库下亿级数据的分库分表

作者:微信小助手

<p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">移动互联网时代,海量的用户数据每天都在产生,基于用户使用数据等这样的分析,都需要依靠数据统计和分析,当数据量小时,数据库方面的优化显得不太重要,一旦数据量越来越大,系统响应会变慢,TPS直线下降,直至服务不可用。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">可能有人会问,为何不用Oracle呢?确实,很多开发者写代码时并不会关心SQL的问题,凡是性能问题都交给DBA负责SQL优化,可是,不是每一个项目都会有DBA,也不是所有的项目都会采用Oracle数据库,而且,Oracle数据库在大数据量的背景下,解决性能问题,也不见的是一个非常轻松的事情。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">那么,My<span style="font-size: 15px;">SQL</span>能不能支撑亿级的数据量呢,我的答案是肯定的,绝大部分的互联网公司,它们采用的数据存储方案,绝大部分都是以MySQL为主,不差钱的国企和银行,以Oracle为主,而且有专职的DBA为你服务。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><strong><span style="font-size: 15px;">本文会以一个实际的项目应用为例,层层向大家剖析如何进行数据库的优化。项目背景是企业级的统一消息处理平台,客户数据在5千万加,每分钟处理消息流水1千万,每天消息流水1亿左右。</span></strong></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">虽说My<span style="font-size: 15px;">SQL</span>单表可以存储10亿级的数据,但这个时候性能非常差。既然一张表无法搞定,那么就想办法将数据放到多个地方来解决问题吧,于是,数据库分库分表的方案便产生了,目前比较普遍的方案有三个:分区,分库分表,No<span style="font-size: 15px;">SQL</span>/New<span style="font-size: 15px;">SQL</span>。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">在实际的项目中,往往是这三种方案的结合来解决问题,目前绝大部分系统的核心数据都是以RDBMS存储为主,No<span style="font-size: 15px;">SQL</span>/New<span style="font-size: 15px;">SQL</span>存储为辅。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;"><br></span></p> <h2 style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="color: rgb(64, 118, 0);"><strong><span style="font-size: 15px;">分区</span></strong></span></h2> <p><span style="color: rgb(64, 118, 0);"><strong><span style="font-size: 15px;"><br></span></strong></span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><strong><span style="font-size: 15px;">分区方案</span></strong></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">分区表是由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们也可以直接访问各个分区,存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个相同的索引,从存储引擎的角度来看,底层表和一个普通表没有任何不同,存储引擎也无须知道这是一个普通表还是一个分区表的一部分。这个方案也不错,它对用户屏蔽了sharding的细节,即使查询条件没有sharding column,它也能正常工作(只是这时候性能一般)。不过它的缺点很明显:很多的资源都受到单机的限制,例如连接数,网络吞吐等。如何进行分区,在实际应用中是一个非常关键的要素之一。在我们的项目中,以客户信息为例,客户数据量5000万加,项目背景要求保存客户的银行卡绑定关系,客户的证件绑定关系,以及客户绑定的业务信息。此业务背景下,该如何设计数据库呢。项目一期的时候,我们建立了一张客户业务绑定关系表,里面冗余了每一位客户绑定的业务信息。基本结构大致如下:</span></p> <p style="margin-left: 8px;margin-right: 8px;text-align: center;"><img class="" data-ratio="0.43272727272727274" src="/upload/3bfd863a5e8d83c58d72358a1bab043c.png" data-type="png" data-w="550"></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">查询时,对银行卡做索引,业务编号做索引,证件号做索引。随着需求大增多,这张表的索引会达到10个以上。而且客户解约再签约,里面会保存两条数据,只是绑定的状态不同。假设我们有5千万的客户,5个业务类型,每位客户平均2张卡,那么这张表的数据量将会达到惊人的5亿,事实上我们系统用户量还没有过百万时就已经不行了。My<span style="font-size: 15px;">SQL</span>数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看), 一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放表数据的,一个是myi存表索引的。这三个文件都非常的庞大,尤其是.myd文件,快5个G了。下面进行第一次分区优化,My<span style="font-size: 15px;">SQL</span>支持的分区方式有四种:</span></p> <p style="margin-top: 10px;line-height: 1.5em;text-align: center;margin-left: 8px;margin-right: 8px;"><span style="font-size: 15px;"><img class="" data-ratio="0.4036363636363636" src="/upload/4242eaa962c640edf657f2f79d71f92d.png" data-type="png" data-w="550"></span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">在我们的项目中,range分区和list分区没有使用场景,如果基于绑定编号做range或者list分区,绑定编号没有实际的业务含义,无法通过它进行查询,因此,我们就剩下 HASH 分区和 KEY 分区了, HASH 分区仅支持int类型列的分区,且是其中的一列。看看我们的库表结构,发现没有哪一列是int类型的,如何做分区呢?可以增加一列,绑定时间列,将此列设置为int类型,然后按照绑定时间进行分区,将每一天绑定的用户分到同一个区里面去。这次优化之后,我们的插入快了许多,但是查询依然很慢,为什么,因为在做查询的时候,我们也只是根据银行卡或者证件号进行查询,并没有根据时间查询,相当于每次查询,My</span><span style="font-size: 15px;">SQL</span><span style="font-size: 15px;">都会将所有的分区表查询一遍。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">然后进行第二次方案优化,既然hash分区和key分区要求其中的一列必须是int类型的,那么创造出一个int类型的列出来分区是否可以。分析发现,银行卡的那串数字有秘密。银行卡一般是16位到19位不等的数字串,我们取其中的某一位拿出来作为表分区是否可行呢,通过分析发现,在这串数字中,其中确实有一位是0到9随机生成的,不同的卡串长度,这一位不同,绝不是最后一位,最后位数字一般都是校验位,不具有随机性。我们新设计的方案,基于银行卡号+随机位进行KEY分区,每次查询的时候,通过计算截取出这位随机位数字,再加上卡号,联合查询,达到了分区查询的目的,需要说明的是,分区后,建立的索引,也必须是分区列,否则的话,My<span style="font-size: 15px;">SQL</span>还是会在所有的分区表中查询数据。那么通过银行卡号查询绑定关系的问题解决了,那么证件号呢,如何通过证件号来查询绑定关系。前面已经讲过,做索引一定是要在分区健上进行,否则会引起全表扫描。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">我们再创建了一张新表,保存客户的证件号绑定关系,每位客户的证件号都是唯一的,新的证件号绑定关系表里,证件号作为了主键,那么如何来计算这个分区健呢,客户的证件信息比较庞杂,有身份证号,港澳台通行证,机动车驾驶证等等,如何在无序的证件号里找到分区健。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">为了解决这个问题,我们将证件号绑定关系表一分为二,其中的一张表专用于保存身份证类型的证件号,另一张表则保存其他证件类型的证件号,在身份证类型的证件绑定关系表中,我们将身份证号中的月数拆分出来作为了分区健,将同一个月出生的客户证件号保存在同一个区,这样分成了12个区,其他证件类型的证件号,数据量不超过10万,就没有必要进行分区了。这样每次查询时,首先通过证件类型确定要去查询哪张表,再计算分区健进行查询。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">作了分区设计之后,保存2000万用户数据的时候,银行卡表的数据保存文件就分成了10个小文件,证件表的数据保存文件分成了12个小文件,解决了这两个查询的问题,还剩下一个问题就是,业务编号呢,怎么办,一个客户有多个签约业务,如何进行保存,这时候,采用分区的方案就不太合适了,它需要用到分表的方案。</span></p> <p class=""><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <h2 style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="color: rgb(64, 118, 0);"><strong><span style="font-size: 15px;">分库分表</span></strong></span></h2> <p class=""><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">如何进行分库分表,目前互联网上有许多的版本,比较知名的一些方案:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">阿里的TDDL,DRDS和cobar,</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">京东金融的sharding-jdbc;</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">间组织的MyCAT;</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">360的Atlas;</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">美团的zebra;</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;"></span><span style="font-size: 15px;">其他比如网易、58、京东等公司都有自研的中间件。</span></p></li> </ul> <p style="margin-top: 10px;line-height: 1.5em;text-align: left;margin-left: 8px;margin-right: 8px;"><span style="font-size: 15px;">但是这么多的分库分表中间件方案,归总起来,就两类:client模式和proxy模式。</span></p> <p style="margin-top: 10px;line-height: 1.5em;text-align: center;margin-left: 8px;margin-right: 8px;"><strong><span style="font-size: 15px;"><img class="" data-ratio="0.7890909090909091" src="/upload/c9a8a3e5389599e5c80c2ab9f32afe8d.png" data-type="png" data-w="550"></span></strong></p> <p style="margin-top: 10px;line-height: 1.5em;text-align: left;margin-left: 8px;margin-right: 8px;"><strong><span style="font-size: 15px;">client模式</span></strong></p> <p style="margin-top: 10px;line-height: 1.5em;text-align: center;margin-left: 8px;margin-right: 8px;"><strong style="text-align: justify;"><span style="font-size: 15px;"><img class="" data-ratio="1.1072727272727272" src="/upload/6f8f9f82606a26c486bee4bf7174bbb8.png" data-type="png" data-w="550"></span></strong></p> <p style="margin-top: 10px;line-height: 1.5em;text-align: left;margin-left: 8px;margin-right: 8px;"><strong style="text-align: justify;"><span style="font-size: 15px;">proxy模式</span></strong></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">无论是client模式,还是proxy模式,几个核心的步骤是一样的:SQL解析,重写,路由,执行,结果归并。个人比较倾向于采用client模式,它架构简单,性能损耗也比较小,运维成本低。如果在项目中引入mycat或者cobar,他们的单机模式无法保证可靠性,一旦宕机则服务就变得不可用,你又不得不引入HAProxy来实现它的高可用集群部署方案, 为了解决HAProxy的高可用问题,又需要采用Keepalived来实现。</span></p> <p style="margin-top: 10px;line-height: 1.5em;text-align: center;margin-left: 8px;margin-right: 8px;"><span style="font-size: 15px;"><img class="transparent" data-ratio="1.1090909090909091" src="/upload/9074f0f7c9ad91b55879a43b449aac97.png" data-type="png" data-w="550"></span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">我们在项目中放弃了这个方案,采用了shardingjdbc的方式。回到刚才的业务问题,如何对业务类型进行分库分表。分库分表第一步也是最重要的一步,即sharding column的选取,sharding column选择的好坏将直接决定整个分库分表方案最终是否成功。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">而sharding column的选取跟业务强相关。在我们的项目场景中,sharding column无疑最好的选择是业务编号。通过业务编号,将客户不同的绑定签约业务保存到不同的表里面去,查询时,根据业务编号路由到相应的表中进行查询,达到进一步优化<span style="font-size: 15px;">SQL</span>的目的。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">前面我们讲到了基于客户签约绑定业务场景的数据库优化,下面我们再聊一聊,对于海量数据的保存方案。</span></p> <p class=""><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <h2 style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="color: rgb(64, 118, 0);"><strong><span style="font-size: 15px;">垂直分库</span></strong></span></h2> <p class=""><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">对于每分钟要处理近1000万的流水,每天流水近1亿的量,如何高效的写入和查询,是一项比较大的挑战。还是老办法,分库分表分区,读写分离,只不过这一次,我们先分表,再分库,最后分区。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">我们将消息流水按照不同的业务类型进行分表,相同业务的消息流水进入同一张表,分表完成之后,再进行分库。我们将流水相关的数据单独保存到一个库里面去,这些数据,写入要求高,查询和更新到要求低,将它们和那些更新频繁的数据区分开。分库之后,再进行分区。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;text-align: center;"><span style="font-size: 15px;"><img class="" data-ratio="0.41454545454545455" src="/upload/9e122f5f2bb63391a1dbd7b08fa8c5d1.png" data-type="png" data-w="550"></span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">这是基于业务垂直度进行的分库操作,垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库,以达到系统资源的饱和利用率。这样的分库方案结合应用的微服务治理,每个微服务系统使用独立的一个数据库。将不同模块的数据分库存储,模块间不能进行相互关联查询,如果有,要么通过数据冗余解决,要么通过应用代码进行二次加工进行解决。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">若不能杜绝跨库关联查询,则将小表到数据冗余到大数据量大库里去。假如,流水大表中查询需要关联获得渠道信息,渠道信息在基础管理库里面,那么,要么在查询时,代码里二次查询基础管理库中的渠道信息表,要么将渠道信息表冗余到流水大表中。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">将每天过亿的流水数据分离出去之后,流水库中单表的数据量还是太庞大,我们将单张流水表继续分区,按照一定的业务规则,(一般是查询索引列)将单表进行分区,一个表编程N个表,当然这些变化对应用层是无法感知的。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;"><img class="" data-ratio="1.4036363636363636" src="/upload/fa72f1e813f77d3e654cc1695b850356.png" data-type="png" data-w="550"></span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">分区表的设置,一般是以查询索引列进行分区,例如,对于流水表A,查询需要根据手机号和批次号进行查询,所以我们在创建分区的时候,就选择以手机号和批次号进行分区,这样设置后,查询都会走索引,每次查询My</span><span style="font-size: 15px;">SQL</span><span style="font-size: 15px;">都会根据查询条件计算出来,数据会落在那个分区里面,直接到对应的分区表中检索即可,避免了全表扫描。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">对于每天流水过亿的数据,当然是要做历史表进行数据迁移的工作了。客户要求流水数据需要保存半年的时间,有的关键流水需要保存一年。删数据是不可能的了,也跑不了路,虽然当时非常有想删数据跑路的冲动。其实即时是删数据也是不太可能的了,delete的拙劣表演先淘汰了,truncate也快不了多少,我们采用了一种比较巧妙方法,具体步骤如下:</span></p> <ol class=" list-paddingleft-2" style="margin-left: 8px;margin-right: 8px;"> <li><p style="margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">创建一个原表一模一样的临时表1 create table test_a_serial_1 like test_a_serial;</span></p></li> <li><p style="margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">将原表命名为临时表2 alter table test_a_serial rename test_a_serial_{date};</span></p></li> <li><p style="margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">将临时表1改为原表 alter table able test_a_serial_1 rename able test_a_serial; 此时,当日流水表就是一张新的空表了,继续保存当日的流水,而临时表2则保存的是昨天的数据和部分今天的数据,临时表2到名字中的date时间是通过计算获得的昨日的日期;每天会产生一张带有昨日日期的临时表2,每个表内的数据大约是有1000万。</span></p></li> <li><p style="margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">将当日表中的历史数据迁移到昨日流水表中去 这样的操作都是用的定时任务进行处理,定时任务触发一般会选择凌晨12点以后,这个操作即时是几秒内完成,也有可能会有几条数据落入到当日表中去。因此我们最后还需要将当日表内的历史流水数据插入到昨日表内; insert into test_a_serial_{date}(cloumn1,cloumn2….) select(cloumn1,cloumn2….) from test_a_serial where LEFT(create_time,8) &gt; CONCAT(date); commit;</span></p></li> </ol> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">如此,便完成了流水数据的迁移;</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">根据业务需要,有些业务数据需要保存半年,超过半年的进行删除,在进行删除的时候,就可以根据表名中的_{date}筛选出大于半年的流水直接删表;</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">半年的时间,对于一个业务流水表大约就会有180多张表,每张表又有20个分区表,那么如何进行查询呢?由于我们的项目对于流水的查询实时性要求不是特别高,因此我们在做查询时,进行了根据查询时间区间段进行路由查询的做法。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">大致做法时,根据客户选择的时间区间段,带上查询条件,分别去时间区间段内的每一张表内查询,将查询结果保存到一张临时表内,然后,再去查询临时表获得最终的查询结果。</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">以上便是我们面对大数据量的场景下,数据库层面做的相应的优化,一张每天一亿的表,经过拆分后,每个表分区内的数据在500万左右。这样设计之后,我们还面临了一些其他问题,例如流水的统计问题,这么大量的数据,项目中的统计维度达到100多种,哪怕是每天count100次,也是及其困难多,我们采用了实时计算统计的方式来解决了这个问题,相关的技术涉及到实时计算,消息队列,缓存中间件等内容,尽请期待吧!</span></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;"><span style="font-size: 15px;">推荐阅读:</span><a href="http://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&amp;mid=404422408&amp;idx=1&amp;sn=c7cf904c12e4ecaf3fb953b2931fd21c&amp;chksm=759a1a7c42ed936a1a96a1ac39225824dd296f8e14e395ae117641069b2463061e24e060da5f&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;text-decoration: underline;" data-linktype="2"><span style="font-size: 14px;">分布式数据库概述</span></a><span style="font-size: 14px;">、</span><a href="http://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&amp;mid=2652558110&amp;idx=1&amp;sn=80a68710f69b6909b048b147df93a91a&amp;chksm=f39a366ac4edbf7c89b3126684d01f35f266d98d0d6e88af8657e33ffcbcd263e86932210f3e&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;text-decoration: underline;" data-linktype="2"><span style="font-size: 14px;">MySQL大表优化方案</span></a><span style="font-size: 14px;">、</span><a href="http://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&amp;mid=2652561348&amp;idx=1&amp;sn=b75e95c1ccb006b1afc2a1c13e66604b&amp;chksm=f39a3ab0c4edb3a67f4ceb490b4d28e45869c91f528ede8793a38c352b12fa662d8b89aede66&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;text-decoration: underline;" data-linktype="2"><span style="font-size: 14px;">系列丨MySQL高性能优化规范、SQL处理、分区表、主主/从复制架构</span></a><span style="font-size: 14px;">、</span><a href="http://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&amp;mid=2652560096&amp;idx=1&amp;sn=20ea32a38c4a9049a4210604e5eb9dac&amp;chksm=f39a3f94c4edb68219d813664bd0983523cf53854f8ffd07fecf36d0e7ffe5f07850c53d528a&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;text-decoration: underline;" data-linktype="2"><span style="font-size: 14px;">MySQL在并发场景下的问题及解决思路</span></a><span style="font-size: 14px;">、</span><a href="http://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&amp;mid=404273402&amp;idx=1&amp;sn=c416535c816d9fcdd45e7b7220c84475&amp;chksm=75985d8e42efd49892fa2355e620fdbf732aebe9f0362de376875d575ccf6988ded9ff49df50&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;text-decoration: underline;" data-linktype="2"><span style="font-size: 14px;">腾讯计费平台部:分布式MySQL数据库TDSQL架构分析</span></a></p> <p style="margin-left: 8px;margin-right: 8px;margin-top: 10px;line-height: 1.5em;text-align: left;"><span style="font-size: 15px;">出处:www.cnblogs.com/jpfss/</span></p> <p style="border-color: currentcolor;border-style: none;border-width: medium;margin: 5px 8px 0px;padding: 10px 0px;background: none 0% 0% repeat scroll rgba(0, 0, 0, 0);line-height: normal;"><span style="color: rgb(136, 136, 136);font-size: 14px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。</span></p> <section label="Copyright © 2014 playhudong All Rights Reserved." style="border-color: currentcolor;border-style: none;border-width: medium;-moz-border-top-colors: none;-moz-border-left-colors: none;-moz-border-bottom-colors: none;-moz-border-right-colors: none;margin: 5px 0px 0px;padding: 10px 0px;background: rgba(0, 0, 0, 0) none repeat scroll 0% 0%;"> <img class="" data-ratio="0.05278592375366569" src="/upload/895b409cfe0a5638b397d0f31154356a.png" data-type="png" data-w="341" style="width: 160px;margin: 0px auto;display: block;"> <br> </section> <p style="text-align: center;line-height: 25.6px;font-size: 14px;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;">架构文摘</strong></span></p> <p style="text-align: center;line-height: 25.6px;font-size: 14px;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;">ID:ArchDigest</span></p> <p style="text-align: center;line-height: 25.6px;font-size: 14px;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;">互联网应用架构丨架构技术丨大型网站丨大数据</span></p> <p style="text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="1.0505836575875487" data-s="300,640" src="/upload/34c06f9af7df907d751d410136379287.png" data-type="png" data-w="257" style="width: 163px;height: 171px;"></p> <p style="text-align: center;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;"><span style="color: rgb(255, 255, 255);line-height: 25.6px;font-family: 宋体;font-size: 12px;max-width: 100%;background-color: rgb(79, 97, 40);">更多精彩文章,请点击下方:</span><span style="color: rgb(255, 255, 255);line-height: 25.6px;font-family: 宋体;font-size: 12px;max-width: 100%;background-color: rgb(192, 0, 0);">阅读原文</span></span></p>

微信小程序开发环境配置

作者:不要哭啦

#### 完善jdk第三方包安装: 1. 错误信息:java.security.InvalidKeyException:illegal Key Size ``` jdk8下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html jdk7下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html 下载后将 local_policy.jar US_export_policy.jar 替换JAVA_HOME就是你安装jdk的目录JAVA_HOME\jre\lib\security ``` 2.错误信息:缺少org.bouncycastle.jce.provider.BouncyCastleProvider包 ``` 下载:bcprov-jdk15on-156.jar bcprov-ext-jdk15on-156.jar包 http://www.bouncycastle.org/latest_releases.html 下载后将bcprov-jdk15on-156.jar bcprov-ext-jdk15on-156.jar 替换JAVA_HOME\jre\lib\ext 并且修改JAVA_HOME\jre\lib\security\java.security找到一组 security.provider.XX=org.bouncycastle.jce.provider.BouncyCastleProvider ``` ` 注意XX为数字按照上面已经有的顺序依次 ` 这样就可以通过微信小程序的openId解密用户信息了 3. Unresolved compilation problem: BouncyCastleProvider cannot be resolved to a type ``` 服务器jdk与本地编译jdk不匹配导致,更新jdk即可 ``

linux设置nfs共享目录

作者:じ☆ve宝贝

##### linux设置nfs共享目录 ##### 使用场景 负载均衡多态服务器,上传文件后不同步问题! 两台机器(可以是虚拟机): 10.175.202.119--->a机器 10.171.239.25----->b机器 ##### 一、查看是否安装NFS(portmap是用于RPC传输的) rpm -q nfs-utils portmap (portmap: 不再使用 一般由rpcbind代替) (centos 6.4中portmap 已经被rpcbind取代) ##### 二、安装nfs yum install nfs-utils ##### 三、配置文件 1.首先配置/etc/exports文件 vi /etc/exports 2.添加内容 /home/share 10.171.239.25(rw,async) 10.171.239.26(ro) //多个内容 共享目录 客户机1 客户机2 或者 /data/web/webphoto 10.171.239.25(rw,no_root_squash,async) ro 只读 rw 读写 sync: 资料同步写入到内存与硬盘当中 async:资料会先暂存于内存当中,而非直接写入硬盘 all_squash 所有登录用户指定为nobody no_all_squash 以当前登录的用户所设定的权限(默认设定) anonuid 在使用all_squash时的选择,可以对登录的帐号指定为指定的用户ID帐号 anougid 在使用all_squash时的选择,可以对登录的帐号指定为指定的组ID帐号 root_squash root用户指定为nobody no_root_squash:(允许远程用户以root帐号登录(比较不安全))不讲root用户及所属用户组映射为匿名用户或用户组,默认root是被映射为匿名用户的nfsnobody,所有即使开了rw写权限,客户机也使无法写入的,这个不映射为匿名用户,还保留原来的用户权限就可以读写了,因为一般都是用root用户登录的。 注意:当客机是否有写权限时,还要看该目录对该用户有没有开放写入权限 ##### 四、启动服务 1.启动rpcbind服务 启动nfs服务 (且rpcbind一定要先于nfs启动) service rpcbind start 或者 /etc.init.d/rpcbind start service nfs start 或者 /etc.init.d/nfs start 2. 停止服务 停止NFS服务器前,需要先停止NFS服务再停止portmap服务。如果系统中还有其它服务需要portmap时,则可以不用停止portmap服务。 service rpcbind stop 或者 /etc.init.d/rpcbind stop service nfs stop 或者 /etc.init.d/nfs stop 3.自动启动NFS服务 chkconfig --level 35 rpcbind on chkconfig --level 35 nfs on 4.中portmap查看所有输出的共享目录 showmount -e 10.175.202.119 输出以下结果: Export list for 10.175.202.119: /data/web/webphoto 10.171.239.25 5.显示所有被挂载的所有输出目录 showmount -d 192.168.1.150 说明成功启动(注意:在centos 6.x之后的版本showmount -e 后面一定要指定ip,否则会卡在那,也没输出,5.x的版本可以不指定) #### 四、挂载 下面是挂载nfs到指定机器的目录 1.ssh登陆到另一台机器b: ssh root@10.171.239.25 mount -t nfs 10.175.202.119:/data/web/webphoto /data/web/webphoto -t:指定挂载设备的文件类型(nfs是网络文件系统) 10.175.202.119:nfs服务器ip地址 /data/web/webphoto :nfs服务器的共享目录 /data/web/webphoto:挂载在本地的目录 2..启动时自动连接nfs服务器 要先在启动时自动连接nfs服务器上的共享目录,要编辑/etc/fstab文件。在文件中加入 10.175.202.119:/data/web/webphoto /data/web/webphoto nfs defaults 0 0 10.175.202.119:/data/web/webphoto:nfs服务器的共享目录 /data/web/webphoto:本机挂载目录 在a机器上建立文件test.txt,然后发现b机器有了同样的文件,nfs服务端和客户端正常同步。

全文搜索引擎选ElasticSearch还是Solr?

作者:微信小助手

<section style="box-sizing: border-box;"> <section class="V5" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;box-sizing: border-box;background-color: rgb(239, 239, 239);"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;"> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">最近项目组安排了一个任务,项目中用到了基于&nbsp;<span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 22.5px;background-color: rgb(239, 239, 239);">Solr 的</span>全文搜索,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步。</span></p> </section> <section style="clear: both;box-sizing: border-box

linux 未知的名称或服务

作者:不要哭啦

**产生原因**:hostname 与 /etc/hosts 名称不对应 **hostname** 查看本机名称,例如本机名称(studyjava) **vi /etc/hosts** 修改前: 127.0.0.1 localhost localhost.localdomain **localhost4** localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 修改后: 127.0.0.1 localhost localhost.localdomain **studyjava** localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

sysbench MySQL压力测试工具安装

作者:Happy生龙

# 自定义安装 ## 1. 下载安装包 ` https://github.com/akopytov/sysbench/releases/tag/1.0.10 ` ## 2. 更新依赖 ``` yum install autoconf automake gcc-c++ libtool make pkgconfig ``` ## 3. 开始安装 - 查找MySQL目录的方法,MySQL安装成功后会在/etc下有my.cnf 文件,或者在/etc/mysql/my.cnf,查看basedir找到目录 ``` tar -zxvf 1.0.10.tar.gz cd sysbench-1.0.10/ ./autogen.sh ./configure --with-mysql-includes=/usr/local/mysql/include/ --with-mysql-libs=/usr/local/mysql/lib/ make && make install ``` # 官方推荐 ``` curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash sudo yum -y install sysbench ``` > 官方地址:https://github.com/akopytov/sysbench#linux

Java 20个常用术语讲解

作者:じ☆ve宝贝

1.什么是可变参数? 2.断言的用途? 3.什么时候使用断言? 4.什么是垃圾回收? 5.用一个例子解释垃圾回收? 6.什么时候运行垃圾回收? 7.垃圾回收的最佳做法? 8.什么是初始化数据块? 9.什么是静态初始化器? 10.什么是实例初始化块? 11.什么是正则表达式? 12.什么是令牌化? 13.给出令牌化的例子? 14.如何使用扫描器类(Scanner Class)令牌化? 15.如何添加小时(hour)到一个日期对象(Date Objects)? 16.如何格式化日期对象? 17.Java中日历类(Calendar Class)的用途? 18.如何在Java中获取日历类的实例? 19.解释一些日历类中的重要方法? 20.数字格式化类(Number Format Class)的用途? ##什么是可变参数? 可变参数允许调用参数数量不同的方法。请看下面例子中的求和方法。此方法可以调用1个int参数,或2个int参数,或多个int参数。 ``` //int(type) followed ... (three dot's) is syntax of a variable argument. public int sum(int... numbers) { //inside the method a variable argument is similar to an array. //number can be treated as if it is declared as int[] numbers; int sum = 0; for (int number: numbers) { sum += number; } return sum; } public static void main(String[] args) { VariableArgumentExamples example = new VariableArgumentExamples(); //3 Arguments System.out.println(example.sum(1, 4, 5));//10 //4 Arguments System.out.println(example.sum(1, 4, 5, 20));//30 //0 Arguments System.out.println(example.sum());//0 } ``` ##断言的用途? 断言是在Java 1.4中引入的。它能让你验证假设。如果断言失败(即返回false),就会抛出AssertionError(如果启用断言)。基本断言如下所示。 ``` private int computerSimpleInterest(int principal,float interest,int years){ assert(principal>0); return 100; } ``` ##什么时候使用断言? 断言不应该用于验证输入数据到一个public方法或命令行参数。IllegalArgumentException会是一个更好的选择。在public方法中,只用断言来检查它们根本不应该发生的情况。 ##什么是垃圾回收? 垃圾回收是Java中自动内存管理的另一种叫法。垃圾回收的目的是为程序保持尽可能多的可用堆(heap)。 JVM会删除堆上不再需要从堆引用的对象。 ##用一个例子解释垃圾回收? 比方说,下面这个方法就会从函数调用。 ``` void method(){ Calendar calendar = new GregorianCalendar(2000,10,30); System.out.println(calendar); } ``` 通过函数第一行代码中参考变量calendar,在堆上创建了GregorianCalendar类的一个对象。 函数结束执行后,引用变量calendar不再有效。因此,在方法中没有创建引用到对象。 JVM认识到这一点,会从堆中删除对象。这就是所谓的垃圾回收。 ##什么时候运行垃圾回收? 垃圾回收在JVM突发奇想和心血来潮时运行(没有那么糟糕)。运行垃圾收集的可能情况是: 堆可用内存不足 CPU空闲 ##垃圾回收的最佳做法? 用编程的方式,我们可以要求(记住这只是一个请求——不是一个命令)JVM通过调用System.gc()方法来运行垃圾回收。 当内存已满,且堆上没有对象可用于垃圾回收时,JVM可能会抛出OutOfMemoryException。 对象在被垃圾回收从堆上删除之前,会运行finalize()方法。我们建议不要用finalize()方法写任何代码。 ##什么是初始化数据块? 初始化数据块——当创建对象或加载类时运行的代码。 有两种类型的初始化数据块: 静态初始化器:加载类时运行的的代码 实例初始化器:创建新对象时运行的代码 ##什么是静态初始化器? 请看下面的例子:static{ 和 }之间的代码被称为静态初始化器。它只有在第一次加载类时运行。只有静态变量才可以在静态初始化器中进行访问。虽然创建了三个实例,但静态初始化器只运行一次。 ``` public class InitializerExamples { static int count; int i; static{ //This is a static initializers. Run only when Class is first loaded. //Only static variables can be accessed System.out.println("Static Initializer"); //i = 6;//COMPILER ERROR System.out.println("Count when Static Initializer is run is " + count); } public static void main(String[] args) { InitializerExamples example = new InitializerExamples(); InitializerExamples example2 = new InitializerExamples(); InitializerExamples example3 = new InitializerExamples(); } } ``` 示例输出 ``` Static Initializer Count when Static Initializer is run is 0. ``` ###什么是实例初始化块? 让我们来看一个例子:每次创建类的实例时,实例初始化器中的代码都会运行。 ``` public class InitializerExamples { static int count; int i; { //This is an instance initializers. Run every time an object is created. //static and instance variables can be accessed System.out.println("Instance Initializer"); i = 6; count = count + 1; System.out.println("Count when Instance Initializer is run is " + count); } public static void main(String[] args) { InitializerExamples example = new InitializerExamples(); InitializerExamples example1 = new InitializerExamples(); InitializerExamples example2 = new InitializerExamples(); } } ``` 示例输出 ``` Instance Initializer Count when Instance Initializer is run is 1 Instance Initializer Count when Instance Initializer is run is 2 Instance Initializer Count when Instance Initializer is run is 3 ``` ##什么是正则表达式? 正则表达式能让解析、扫描和分割字符串变得非常容易。Java中常用的正则表达式——Patter,Matcher和Scanner类。 ##什么是令牌化? 令牌化是指在分隔符的基础上将一个字符串分割为若干个子字符串。例如,分隔符;分割字符串ac;bd;def;e为四个子字符串ac,bd,def和e。 分隔符自身也可以是一个常见正则表达式。 String.split(regex)函数将regex作为参数。 ##给出令牌化的例子? ``` private static void tokenize(String string,String regex) { String[] tokens = string.split(regex); System.out.println(Arrays.toString(tokens)); } tokenize("ac;bd;def;e",";");//[ac, bd, def, e] ``` ###如何使用扫描器类(Scanner Class)令牌化? ``` private static void tokenizeUsingScanner(String string,String regex) { Scanner scanner = new Scanner(string); scanner.useDelimiter(regex); List<String> matches = new ArrayList<String>(); while(scanner.hasNext()){ matches.add(scanner.next()); } System.out.println(matches); } tokenizeUsingScanner("ac;bd;def;e",";");//[ac, bd, def, e] ``` ##如何添加小时(hour)到一个日期对象(Date Objects)? 现在,让我们如何看看添加小时到一个date对象。所有在date上的日期操作都需要通过添加毫秒到date才能完成。例如,如果我们想增加6个小时,那么我们需要将6小时换算成毫秒。6小时= 6 * 60 * 60 * 1000毫秒。请看以下的例子。 ``` Date date = new Date(); //Increase time by 6 hrs date.setTime(date.getTime() + 6 * 60 * 60 * 1000); System.out.println(date); //Decrease time by 6 hrs date = new Date(); date.setTime(date.getTime() - 6 * 60 * 60 * 1000); System.out.println(date); ``` ##如何格式化日期对象? 格式化日期需要使用DateFormat类完成。让我们看几个例子。 ``` //Formatting Dates System.out.println(DateFormat.getInstance().format( date));//10/16/12 5:18 AM ``` 带有区域设置的格式化日期如下所示: ``` System.out.println(DateFormat.getDateInstance( DateFormat.FULL, new Locale("it", "IT")) .format(date));//marted“ 16 ottobre 2012 System.out.println(DateFormat.getDateInstance( DateFormat.FULL, Locale.ITALIAN) .format(date));//marted“ 16 ottobre 2012 //This uses default locale US System.out.println(DateFormat.getDateInstance( DateFormat.FULL).format(date));//Tuesday, October 16, 2012 System.out.println(DateFormat.getDateInstance() .format(date));//Oct 16, 2012 System.out.println(DateFormat.getDateInstance( DateFormat.SHORT).format(date));//10/16/12 System.out.println(DateFormat.getDateInstance( DateFormat.MEDIUM).format(date));//Oct 16, 2012 System.out.println(DateFormat.getDateInstance( DateFormat.LONG).format(date));//October 16, 2012 ``` ##Java中日历类(Calendar Class)的用途? Calendar类(Youtube视频链接 - https://www.youtube.com/watch?v=hvnlYbt1ve0)在Java中用于处理日期。Calendar类提供了增加和减少天数、月数和年数的简便方法。它还提供了很多与日期有关的细节(这一年的哪一天?哪一周?等等) ##如何在Java中获取日历类(Calendar Class)的实例? Calendar类不能通过使用new Calendar创建。得到Calendar类实例的最好办法是在Calendar中使用getInstance() static方法。 ``` //Calendar calendar = new Calendar(); //COMPILER ERROR Calendar calendar = Calendar.getInstance(); ``` ##解释一些日历类(Calendar Class)中的重要方法? 在Calendar对象上设置日(day),月(month)或年(year)不难。对Day,Month或Year调用恰当Constant的set方法。下一个参数就是值。 ``` calendar.set(Calendar.DATE, 24); calendar.set(Calendar.MONTH, 8);//8 - September calendar.set(Calendar.YEAR, 2010); ``` calendar get方法 要获取一个特定日期的信息——2010年9月24日。我们可以使用calendar get方法。已被传递的参数表示我们希望从calendar中获得的值—— 天或月或年或……你可以从calendar获取的值举例如下: ``` System.out.println(calendar.get(Calendar.YEAR));//2010 System.out.println(calendar.get(Calendar.MONTH));//8 System.out.println(calendar.get(Calendar.DATE));//24 System.out.println(calendar.get(Calendar.WEEK_OF_MONTH));//4 System.out.println(calendar.get(Calendar.WEEK_OF_YEAR));//39 System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//267 System.out.println(calendar.getFirstDayOfWeek());//1 -> Calendar.SUNDAY ``` ##数字格式化类(Number Format Class)的用途? 数字格式用于格式化数字到不同的区域和不同格式中。 使用默认语言环境的数字格式 ``` System.out.println(NumberFormat.getInstance().format(321.24f));//321.24 ``` 使用区域设置的数字格式 使用荷兰语言环境格式化数字: ``` System.out.println(NumberFormat.getInstance(new Locale("nl")).format(4032.3f));//4.032,3 ``` 使用德国语言环境格式化数字: ``` System.out.println(NumberFormat.getInstance(Locale.GERMANY).format(4032.3f));//4.032,3 ``` 使用默认语言环境格式化货币 ``` System.out.println(NumberFormat.getCurrencyInstance().format(40324.31f));//$40,324.31 ``` 使用区域设置格式化货币 使用荷兰语言环境格式化货币: ``` System.out.println(NumberFormat.getCurrencyInstance(new Locale("nl")).format(40324.31f));//? 40.324,31 ``` 译文链接:http://www.codeceo.com/article/20-java-advanced-interview-questions.html 英文原文:Advanced Java Interview Questions 翻译作者:码农网 – 小峰 [ 转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]