作者:微信小助手
<section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-copyright="0" data-ratio="0.6057298772169167" data-s="300,640" src="/upload/2ab63de539c847c0701a7999be391b76.png" data-type="png" data-w="733" style="color: rgb(107, 107, 107);font-size: 14px;background-color: rgb(246, 246, 246);letter-spacing: 0.544px;box-sizing: border-box !important;word-wrap: break-word !important;width: 677px !important;visibility: visible !important;"></p> </section> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;"> <section style="padding: 10px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 677px;vertical-align: top;background-color: rgb(246, 246, 246);word-wrap: break-word !important;"> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 14px;color: rgb(107, 107, 107);line-height: 1.8;word-wrap: break-word !important;"> <h2 class="rich_media_title">上篇文章回顾:<a href="https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484934&idx=1&sn=70d4c8363aeef3f7b67f151a516b63bc&chksm=fd985067caefd971703f7a6b140c17628986572b8d48af203541394635a0c575ad162bad4ae6&token=1245108249&lang=zh_CN&scene=21#wechat_redirect" target="_blank" data-linktype="2">互联网公司面试必问的mysql题目(上)</a></h2> </section> </section> </section> </section> </section> </section> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"> <section style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;"> <span style="color: inherit;font-weight: bold;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 18px;">什么是数据库索引?索引有哪几种类型?什么是最左前缀原则?索引算法有哪些?有什么区别?</span> <br> </section> <section> <span style="color: rgb(255, 0, 0);font-size: 16px;"><strong>关于数据库索引的内容也可以参考这篇文章:</strong></span> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484486&idx=1&sn=215450f11e042bca8a58eac9f4a97686&chksm=fd985227caefdb3117b8375f150676f5824aa20d1ebfdbcfb93ff06e23e26efbafae6cf6b48e&token=1245108249&lang=zh_CN&scene=21#wechat_redirect" target="_blank" style="letter-spacing: 0.544px;font-size: 16px;text-decoration: underline;" data-linktype="2"><span style="letter-spacing: 0.544px;font-size: 16px;">【思维导图-索引篇】搞定数据库索引就是这么简单</span></a> </section> </section> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);">索引是对数据库表中一列或多列的值进行排序的一种结构。一个非常恰当的比喻就是书的目录页与书的正文内容之间的关系,为了方便查找书中的内容,通过对内容建立索引形成目录。索引是一个文件,它是要占据物理空间的。</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 17px;"><strong style="box-sizing: border-box;color: inherit;font-size: inherit;line-height: inherit;">主键索引:</strong></span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">数据列不允许重复,不允许为NULL.一个表只能有一个主键。</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 17px;"><strong style="box-sizing: border-box;color: inherit;font-size: inherit;line-height: inherit;">唯一索引:</strong></span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);">可以通过<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: inherit;color: rgb(233, 105, 0);line-height: inherit;word-wrap: break-word;border-radius: 4px;background: rgb(248, 248, 248);">ALTER TABLE table_name ADD UNIQUE (column);</code> <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">创建唯一索引</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);">可以通过<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: inherit;color: rgb(233, 105, 0);line-height: inherit;word-wrap: break-word;border-radius: 4px;background: rgb(248, 248, 248);">ALTER TABLE table_name ADD UNIQUE (column1,column2);</code><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">创建唯一组合索引</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 17px;"><strong style="box-sizing: border-box;color: inherit;font-size: inherit;line-height: inherit;">普通索引:</strong></span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">基本的索引类型,没有唯一性的限制,允许为NULL值。</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);">可以通过<code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: inherit;color: rgb(233, 105, 0);line-height: inherit;word-wrap: break-word;border-radius: 4px;background: rgb(248, 248, 248);">ALTER TABLE table_name ADD INDEX index_name (column);</code>创建普通索引</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);">可以通过<code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: inherit;color: rgb(233, 105, 0);line-height: inherit;word-wrap: break-word;border-radius: 4px;background: rgb(248, 248, 248);">ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);</code>创建组合索引</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 17px;"><strong style="box-sizing: border-box;color: inherit;font-size: inherit;line-height: inherit;">全文索引:</strong></span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">是目前搜索引擎使用的一种关键技术。</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);">可以通过<code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: inherit;color: rgb(233, 105, 0);line-height: inherit;word-wrap: break-word;border-radius: 4px;background: rgb(248, 248, 248);">ALTER TABLE table_name ADD FULLTEXT (column);</code>创建全文索引</p> <p style="box-sizing: border-box;margin-top: 1.5em;margin-bottom: 1.5em;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><strong style="box-sizing: border-box;color: inherit;font-size: inherit;line-height: inherit;">最左前缀</strong></p> <ul style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">顾名思义,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。</span></p></li> <li><p><span style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">还有一个就是生效原则 比如</span></p></li> </ul> <pre style="box-sizing: border-box;margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs vbnet" style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;word-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;">index(a,b,c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> a=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> 只使用了a<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> a=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">and</span> b=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">5</span> 使用了a,b<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> a=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">and</span> b=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">5</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">and</span> c=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">4</span> 使用了a,b,c<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> b=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">or</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> c=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">4</span> 没有使用索引<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> a=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">and</span> c=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">4</span> 仅使用了a<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> a=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">and</span> b><span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">10</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">and</span> c=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">7</span> 使用了a,b<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">where</span> a=<span class="hljs-number" style="box-sizing: border-box;font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">3</span> <span class="hljs-keyword" style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">a
作者:じ☆ve宝贝
### 1、多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓”知其然知其所以然”,”会用”只是”知其然”,”为什么用”才是”知其所以然”,只有达到”知其然知其所以然”的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法: (1)发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的”多线程”那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程”同时”运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。 (2)防止阻塞 从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。 (3)便于建模 这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务,任务B、任务C、任务D,分别建立程序模型,并通过多线程分别运行这几个任务,那就简单很多了。 ### 2、创建线程的方式 比较常见的一个问题了,一般就是两种: (1)继承Thread类 (2)实现Runnable接口 至于哪个好,不用说肯定是后者好,因为实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度,面向接口编程也是设计模式6大原则的核心。 ### 3、start()方法和run()方法的区别 只有调用了start()方法,才会表现出多线程的特性,不同线程的run()方法里面的代码交替执行。如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其run()方法里面的代码。 ### 4、Runnable接口和Callable接口的区别 有点深的问题了,也看出一个Java程序员学习知识的广度。 Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。 这其实是很有用的一个特性,因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。而Callable+Future/FutureTask却可以获取多线程运行的结果,可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务,真的是非常有用。 ### 5、CyclicBarrier和CountDownLatch的区别 两个看上去有点像的类,都在java.util.concurrent下,都可以用来表示代码运行到某个点上,二者的区别在于: (1)CyclicBarrier的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这个点,所有线程才重新运行;CountDownLatch则不是,某线程运行到某个点上之后,只是给某个数值-1而已,该线程继续运行 (2)CyclicBarrier只能唤起一个任务,CountDownLatch可以唤起多个任务 (3)CyclicBarrier可重用,CountDownLatch不可重用,计数值为0该CountDownLatch就不可再用了 ### 6、Volatile关键字的作用 一个非常重要的问题,是每个学习、应用多线程的Java程序员都必须掌握的。理解volatile关键字的作用的前提是要理解Java内存模型,这里就不讲Java内存模型了,可以参见第31点,volatile关键字的作用主要有两个: (1)多线程主要围绕可见性和原子性两个特性而展开,使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到volatile变量,一定是最新的数据 (2)代码底层执行不像我们看到的高级语言—-Java程序这么简单,它的执行是Java代码–>字节码–>根据字节码执行对应的C/C++代码–>C/C++代码被编译成汇编语言–>和硬件电路交互,现实中,为了获取更好的性能JVM可能会对指令进行重排序,多线程下可能会出现一些意想不到的问题。使用volatile则会对禁止语义重排序,当然这也一定程度上降低了代码执行效率 从实践角度而言,volatile的一个重要作用就是和CAS结合,保证了原子性,详细的可以参见java.util.concurrent.atomic包下的类,比如AtomicInteger。 ### 7、什么是线程安全 又是一个理论的问题,各式各样的答案有很多,我给出一个个人认为解释地最好的:如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么你的代码就是线程安全的。 这个问题有值得一提的地方,就是线程安全也是有几个级别的: (1)不可变 像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用 (2)绝对线程安全 不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet (3)相对线程安全 相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。 (4)线程非安全 这个就没什么好说的了,ArrayList、LinkedList、HashMap等都是线程非安全的类 ### 8、Java中如何获取到线程dump文件 死循环、死锁、阻塞、页面打开慢等问题,打线程dump是最好的解决问题的途径。所谓线程dump也就是线程堆栈,获取到线程堆栈有两步: (1)获取到线程的pid,可以通过使用jps命令,在Linux环境下还可以使用ps -ef | grep java (2)打印线程堆栈,可以通过使用jstack pid命令,在Linux环境下还可以使用kill -3 pid 另外提一点,Thread类提供了一个getStackTrace()方法也可以用于获取线程堆栈。这是一个实例方法,因此此方法是和具体线程实例绑定的,每次获取获取到的是具体某个线程当前运行的堆栈, ### 9、一个线程如果出现了运行时异常会怎么样 如果这个异常没有被捕获的话,这个线程就停止执行了。另外重要的一点是:如果这个线程持有某个某个对象的监视器,那么这个对象监视器会被立即释放 ### 10、如何在两个线程之间共享数据 通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待,比方说阻塞队列BlockingQueue就是为线程之间共享数据而设计的 ### 11、sleep方法和wait方法有什么区别 这个问题常问,sleep方法和wait方法都可以用来放弃CPU一定的时间,不同点在于如果线程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,wait方法会放弃这个对象的监视器 ### 12、生产者消费者模型的作用是什么 这个问题很理论,但是很重要: (1)通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生产者消费者模型最重要的作用 (2)解耦,这是生产者消费者模型附带的作用,解耦意味着生产者和消费者之间的联系少,联系越少越可以独自发展而不需要收到相互的制约 ### 13、ThreadLocal有什么用 简单说ThreadLocal就是一种以空间换时间的做法,在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了 ### 14、为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用 这是JDK强制的,wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁 ### 15、wait()方法和notify()/notifyAll()方法在放弃对象监视器时有什么区别 wait()方法和notify()/notifyAll()方法在放弃对象监视器的时候的区别在于:wait()方法立即释放对象监视器,notify()/notifyAll()方法则会等待线程剩余代码执行完毕才会放弃对象监视器。 ### 16、为什么要使用线程池 避免频繁地创建和销毁线程,达到线程对象的重用。另外,使用线程池还可以根据项目灵活地控制并发的数目。 ### 17、怎么检测一个线程是否持有对象监视器 我也是在网上看到一道多线程面试题才知道有方法可以判断某个线程是否持有对象监视器:Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这是一个static方法,这意味着“某条线程”指的是当前线程。 ### 18、synchronized和ReentrantLock的区别 synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上: (1)ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁 (2)ReentrantLock可以获取各种锁的信息 (3)ReentrantLock可以灵活地实现多路通知 另外,二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word,这点我不能确定。 ### 19、ConcurrentHashMap的并发度是什么 ConcurrentHashMap的并发度就是segment的大小,默认为16,这意味着最多同时可以有16条线程操作ConcurrentHashMap,这也是ConcurrentHashMap对Hashtable的最大优势,任何情况下,Hashtable能同时有两条线程获取Hashtable中的数据吗? ### 20、ReadWriteLock是什么 首先明确一下,不是说ReentrantLock不好,只是ReentrantLock某些时候有局限。如果使用ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。 因为这个,才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口,ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。 ### 21、FutureTask是什么 这个其实前面有提到过,FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。 ### 22、Linux环境下如何查找哪个线程使用CPU最长 这是一个比较偏实践的问题,这种问题我觉得挺有意义的。可以这么做: (1)获取项目的pid,jps或者ps -ef | grep java,这个前面有讲过 (2)top -H -p pid,顺序不能改变 这样就可以打印出当前的项目,每条线程占用CPU时间的百分比。注意这里打出的是LWP,也就是操作系统原生线程的线程号,我笔记本山没有部署Linux环境下的Java工程,因此没有办法截图演示,网友朋友们如果公司是使用Linux环境部署项目的话,可以尝试一下。 使用”top -H -p pid”+”jps pid”可以很容易地找到某条占用CPU高的线程的线程堆栈,从而定位占用CPU高的原因,一般是因为不当的代码操作导致了死循环。 最后提一点,”top -H -p pid”打出来的LWP是十进制的,”jps pid”打出来的本地线程号是十六进制的,转换一下,就能定位到占用CPU高的线程的当前线程堆栈了。 ### 23、Java编程写一个会导致死锁的程序 第一次看到这个题目,觉得这是一个非常好的问题。很多人都知道死锁是怎么一回事儿:线程A和线程B相互等待对方持有的锁导致程序无限死循环下去。当然也仅限于此了,问一下怎么写一个死锁的程序就不知道了,这种情况说白了就是不懂什么是死锁,懂一个理论就完事儿了,实践中碰到死锁的问题基本上是看不出来的。 真正理解什么是死锁,这个问题其实不难,几个步骤: (1)两个线程里面分别持有两个Object对象:lock1和lock2。这两个lock作为同步代码块的锁; (2)线程1的run()方法中同步代码块先获取lock1的对象锁,Thread.sleep(xxx),时间不需要太多,50毫秒差不多了,然后接着获取lock2的对象锁。这么做主要是为了防止线程1启动一下子就连续获得了lock1和lock2两个对象的对象锁 (3)线程2的run)(方法中同步代码块先获取lock2的对象锁,接着获取lock1的对象锁,当然这时lock1的对象锁已经被线程1锁持有,线程2肯定是要等待线程1释放lock1的对象锁的 这样,线程1″睡觉”睡完,线程2已经获取了lock2的对象锁了,线程1此时尝试获取lock2的对象锁,便被阻塞,此时一个死锁就形成了。代码就不写了,占的篇幅有点多,Java多线程7:死锁这篇文章里面有,就是上面步骤的代码实现。 ### 24、怎么唤醒一个阻塞的线程 如果线程是因为调用了wait()、sleep()或者join()方法而导致的阻塞,可以中断线程,并且通过抛出InterruptedException来唤醒它;如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。 ### 25、不可变对象对多线程有什么帮助 前面有提到过的一个问题,不可变对象保证了对象的内存可见性,对不可变对象的读取不需要进行额外的同步手段,提升了代码执行效率。 ### 26、什么是多线程的上下文切换 多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。 ### 27、如果你提交任务时,线程池队列已满,这时会发生什么 如果你使用的LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务;如果你使用的是有界队列比方说ArrayBlockingQueue的话,任务首先会被添加到ArrayBlockingQueue中,ArrayBlockingQueue满了,则会使用拒绝策略RejectedExecutionHandler处理满了的任务,默认是AbortPolicy。 ### 28、Java中用到的线程调度算法是什么 抢占式。一个线程用完CPU之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。 ### 29、Thread.sleep(0)的作用是什么 这个问题和上面那个问题是相关的,我就连在一起了。由于Java采用抢占式的线程调度算法,因此可能会出现某条线程常常获取到CPU控制权的情况,为了让某些优先级比较低的线程也能获取到CPU控制权,可以使用Thread.sleep(0)手动触发一次操作系统分配时间片的操作,这也是平衡CPU控制权的一种操作。 ### 30、什么是自旋 很多synchronized里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,因为线程阻塞涉及到用户态和内核态切换的问题。既然synchronized里面的代码执行地非常快,不妨让等待锁的线程不要被阻塞,而是在synchronized的边界做忙循环,这就是自旋。如果做了多次忙循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。 ### 31、什么是Java内存模型 Java内存模型定义了一种多线程访问Java内存的规范。Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几部分内容: (1)Java内存模型将内存分为了主内存和工作内存。类的状态,也就是类之间共享的变量,是存储在主内存中的,每次Java线程用到这些主内存中的变量的时候,会读一次主内存中的变量,并让这些内存在自己的工作内存中有一份拷贝,运行自己线程代码的时候,用到这些变量,操作的都是自己工作内存中的那一份。在线程代码执行完毕之后,会将最新的值更新到主内存中去 (2)定义了几个原子操作,用于操作主内存和工作内存中的变量 (3)定义了volatile变量的使用规则 (4)happens-before,即先行发生原则,定义了操作A必然先行发生于操作B的一些规则,比如在同一个线程内控制流前面的代码一定先行发生于控制流后面的代码、一个释放锁unlock的动作一定先行发生于后面对于同一个锁进行锁定lock的动作等等,只要符合这些规则,则不需要额外做同步措施,如果某段代码不符合所有的happens-before规则,则这段代码一定是线程非安全的 ### 32、什么是CAS CAS,全称为Compare and Set,即比较-设置。假设有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不做并返回false。当然CAS一定要volatile变量配合,这样才能保证每次拿到的变量是主内存中最新的那个值,否则旧的预期值A对某条线程来说,永远是一个不会变的值A,只要某次CAS操作失败,永远都不可能成功。 ### 33、什么是乐观锁和悲观锁 (1)乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-设置这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。 (2)悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。 ### 34、什么是AQS 简单说一下AQS,AQS全称为AbstractQueuedSychronizer,翻译过来应该是抽象队列同步器。 如果说java.util.concurrent的基础是CAS的话,那么AQS就是整个Java并发包的核心了,ReentrantLock、CountDownLatch、Semaphore等等都用到了它。AQS实际上以双向队列的形式连接所有的Entry,比方说ReentrantLock,所有等待的线程都被放在一个Entry中并连成双向队列,前面一个线程使用ReentrantLock好了,则双向队列实际上的第一个Entry开始运行。 AQS定义了对双向队列所有的操作,而只开放了tryLock和tryRelease方法给开发者使用,开发者可以根据自己的实现重写tryLock和tryRelease方法,以实现自己的并发功能。 ### 35、单例模式的线程安全性 老生常谈的问题了,首先要说的是单例模式的线程安全意味着:某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法,我总结一下: (1)饿汉式单例模式的写法:线程安全 (2)懒汉式单例模式的写法:非线程安全 (3)双检锁单例模式的写法:线程安全 ### 36、Semaphore有什么作用 Semaphore就是一个信号量,它的作用是限制某段代码块的并发数。Semaphore有一个构造函数,可以传入一个int型整数n,表示某段代码最多只有n个线程可以访问,如果超出了n,那么请等待,等到某个线程执行完毕这段代码块,下一个线程再进入。由此可以看出如果Semaphore构造函数中传入的int型整数n=1,相当于变成了一个synchronized了。 ### 37、Hashtable的size()方法中明明只有一条语句”return count”,为什么还要做同步? 这是我之前的一个困惑,不知道大家有没有想过这个问题。某个方法中如果有多条语句,并且都在操作同一个类变量,那么在多线程环境下不加锁,势必会引发线程安全问题,这很好理解,但是size()方法明明只有一条语句,为什么还要加锁? 关于这个问题,在慢慢地工作、学习中,有了理解,主要原因有两点: (1)同一时间只能有一条线程执行固定类的同步方法,但是对于类的非同步方法,可以多条线程同时访问。所以,这样就有问题了,可能线程A在执行Hashtable的put方法添加数据,线程B则可以正常调用size()方法读取Hashtable中当前元素的个数,那读取到的值可能不是最新的,可能线程A添加了完了数据,但是没有对size++,线程B就已经读取size了,那么对于线程B来说读取到的size一定是不准确的。而给size()方法加了同步之后,意味着线程B调用size()方法只有在线程A调用put方法完毕之后才可以调用,这样就保证了线程安全性 (2)CPU执行代码,执行的不是Java代码,这点很关键,一定得记住。Java代码最终是被翻译成汇编代码执行的,汇编代码才是真正可以和硬件电路交互的代码。即使你看到Java代码只有一行,甚至你看到Java代码编译之后生成的字节码也只有一行,也不意味着对于底层来说这句语句的操作只有一个。一句”return count”假设被翻译成了三句汇编语句执行,完全可能执行完第一句,线程就切换了。 ### 38、线程类的构造方法、静态块是被哪个线程调用的 这是一个非常刁钻和狡猾的问题。请记住:线程类的构造方法、静态块是被new这个线程类所在的线程所调用的,而run方法里面的代码才是被线程自身所调用的。 如果说上面的说法让你感到困惑,那么我举个例子,假设Thread2中new了Thread1,main函数中new了Thread2,那么: (1)Thread2的构造方法、静态块是main线程调用的,Thread2的run()方法是Thread2自己调用的 (2)Thread1的构造方法、静态块是Thread2调用的,Thread1的run()方法是Thread1自己调用的 ### 39、同步方法和同步块,哪个是更好的选择 同步块,这意味着同步块之外的代码是异步执行的,这比同步整个方法更提升代码的效率。请知道一条原则:同步的范围越少越好。 借着这一条,我额外提一点,虽说同步的范围越少越好,但是在Java虚拟机中还是存在着一种叫做锁粗化的优化方法,这种方法就是把同步范围变大。这是有用的,比方说StringBuffer,它是一个线程安全的类,自然最常用的append()方法是一个同步方法,我们写代码的时候会反复append字符串,这意味着要进行反复的加锁->解锁,这对性能不利,因为这意味着Java虚拟机在这条线程上要反复地在内核态和用户态之间进行切换,因此Java虚拟机会将多次append方法调用的代码进行一个锁粗化的操作,将多次的append的操作扩展到append方法的头尾,变成一个大的同步块,这样就减少了加锁–>解锁的次数,有效地提升了代码执行的效率。 ### 40、高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池? 这是我在并发编程网上看到的一个问题,把这个问题放在最后一个,希望每个人都能看到并且思考一下,因为这个问题非常好、非常实际、非常专业。关于这个问题,个人看法是: (1)高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换 (2)并发不高、任务执行时间长的业务要区分开看: a)假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以加大线程池中的线程数目,让CPU处理更多的业务 b)假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换 (3)并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦。
作者:微信小助手
<p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.66640625" data-s="300,640" src="/upload/fc7f734c1c3f6f78ce29d6300bf182e5.jpg" data-type="jpeg" data-w="1280" style="width: 100%;height: auto;" data-before-oversubscription-url="/upload/fc7f734c1c3f6f78ce29d6300bf182e5.jpg" data-backw="556" data-backh="371"></p> <section class="" style="margin: 0px;padding: 0px;font-style: normal;font-variant: normal;font-weight: 400;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;letter-spacing: 0.544px;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section label="Copyright Reserved by PLAYHUDONG." style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;letter-spacing: 0.612px;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section label="Copyright Reserved by PLAYHUDONG." style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section class="" style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"> <section label="Copyright Reserved by PLAYHUDONG." style="margin: 0px 0em;padding: 0.5em 1em;max-width: 100%;border-style: none;background-color: rgb(235, 235, 235);box-sizing: border-box !important;word-wrap: break-word !important;"> <p style="margin: 0px;padding: 0px;clear: both;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="margin: 0px;padding: 0px;max-width: 100%;color: rgb(136, 136, 136);font-size: 15px;letter-spacing: 0.612px;box-sizing: border-box !important;word-wrap: break-word !important;">阿里妹导读</span><span style="margin: 0px;padding: 0px;max-width: 100%;color: rgb(136, 136, 136);font-size: 15px;letter-spacing: 0.612px;box-sizing: border-box !important;word-wrap: break-word !important;">:研发效能分为两块,一是用技术的更新来提升效率;二是提高整个技术生态中的协同效率,激发技术活力。阿里巴巴技术团队在此基础上要实现的终极目标是打造7*24小时灵活发布的通道,以及提供更快的业务代码迭代能力。今天,阿里巴巴高级测试开发专家傲野为你带来关于研发效能的一些思考,希望对你有启发。</span></p> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);"> </span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);">7*24小时发布窗口的实现其实并不简单,受限于很多因素。我简单地进行了分解。</span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><br style="margin: 0px;padding: 0px;"></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: center;"><img class="" data-ratio="1.0743494423791822" data-s="300,640" src="/upload/39dcda9b43b4add00596aa4e97510198.png" data-type="png" data-w="269" style="margin: 0px;padding: 0px;max-width: 100%;height: auto !important;"></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);"> </span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><strong style="margin: 0px;padding: 0px;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(255, 129, 36);">一、系统</span></strong></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);"><br style="margin: 0px;padding: 0px;"></span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);">先从最基础的开始说,</span><span style="margin: 0px;padding: 0px;color: rgb(62, 62, 62);font-size: 15px;">当一个创业团队只有几个人,一两个系统的情况下,是可以不考虑研发效率这回事的。因为不存在系统间的依赖,系统内的依赖也完全在一个可控的范围内,本地起一个 Tomcat 或 Apache 就能开发、调试。另外再加上团队成员之间的高频交流,基本上可以实现随时随地,想发就发的要求。</span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);"> </span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: center;"><img class="" data-ratio="0.6998191681735986" data-s="300,640" src="/upload/8e8e25bdb2f9690b33ccb95e3b690285.png" data-type="png" data-w="553" style="margin: 0px;padding: 0px;max-width: 100%;height: auto !important;"></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);"><br style="margin: 0px;padding: 0px;"></span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);">当业务逐渐复杂,开发人数扩展到10几个人时。提效的第一步是理清系统内的依赖关系,并促进角色的专业化。这也是大家所熟知的MVC,通过对视图、模型、控制器的分离,对系统内的逻辑进行分层。把复杂的代码逻辑下沉到Model层,而视图层交由更专业的前端来负责。</span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75em;"><span style="margin: 0px;padding: 0px;font-size: 15px;color: rgb(62, 62, 62);"> </span></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;text-align: center;"><img class="" data-ratio="0.46112115732368897" data-s="300,640" src="/upload/54837fa2d85c84b235f4ed0fc9a297a.png" data-type="png" data-w="553" style="margin: 0px;padding: 0px;max-width: 100%;height: auto !important;"></p> <p style="margin: 0px;padding: 0px;clear: both;color: rgb(0, 0, 0);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Ar
作者:じ☆ve宝贝
#### 需要的jar包velocity-1.5.jar mail.jar #### 配置文件config.properties ``` mail.host=smtp.ym.163.com mail.username=service@studyjava.cn mail.smtp.auth=true mail.smtp.timeout=25000 ``` #### 配置文件Const.java ``` //mail public static final String MAILUSERLIST="system1@studyjava.cn,system2@studyjava.cn,system3@studyjava.cn,system4@studyjava.cn,system5@studyjava.cn,system6@studyjava.cn,system7@studyjava.cn,system8@studyjava.cn,system9@studyjava.cn,system10@studyjava.cn"; public static final String MAILPASSWORD="www.studyjava.cn"; ``` #### register.vm模板 ``` 亲爱的 <b style="color:red;">${username}</b>: 您好!<br/><br/> 你的登录邮箱为:${useremail}<br/> 请点击下面链接,完成您的邮箱验证:<br/> <a href='${sureurl}' >${sureurl}</a><br/> 如果以上链接无法点击请点击这里<a href='${sureurl}' style="color:red;">立即激活</a>,或将上面的地址复制到你的浏览器(如IE)的地址栏。<br/> (该链接在48小时内有效,48小时后需要重新注册) <br/><br/><br/> <br/><br/><br/> <center style="color:red;font-size:10px"> 温馨提示:此邮件由CIA验证平台系统发送,请勿直接回复。 </center> ``` ####applictionContext-mail.xml ``` <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- 邮件发送器 --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="${mail.host}" /> <property name="defaultEncoding" value="UTF-8"></property> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">${mail.smtp.auth}</prop> <prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop> </props> </property> </bean> <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> <property name="resourceLoaderPath" value="classpath:cn/studyjava/util"></property> </bean> <bean id="mailService" class="cn.studyjava.service.MailService"> <property name="javaMailSender" ref="mailSender"></property> <property name="encoding" value="UTF-8"></property> <property name="templateLocation" value="register.vm"></property> <property name="velocityEngine" ref="velocityEngine"></property> <property name="title" value="测试邮件"></property> </bean> </beans> ``` ####s pring.xml ``` <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd" default-lazy-init="true"> <context:property-placeholder location="classpath:/cn/studyjava/config.properties" /> <!-- 导入mail配置文件--> <import resource="classpath:/cn/studyjava/applictionContext-mail.xml" /> </beans> ``` #### MailService.java ``` package cn.studyjava.service; import java.util.Map; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.exception.VelocityException; import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.springframework.ui.velocity.VelocityEngineUtils; import cn.studyjava.util.Const; /** * * 邮件发送器 zsl * * Velocity类中使用init方法里是使用了RuntimeSingleton.init(); * 在RuntimeSingleton类中,使用到的运行实例是静态new出来的。 private static RuntimeInstance ri = * new RuntimeInstance(); * 而在org.apache.velocity.app.VelocityEngine类中,并没有一个单例类来初始化, 每次都会使用private * RuntimeInstance ri = new RuntimeInstance()来创建一个新的运行实例, * 这样就使得每个velocity引擎都会拥有各自的实例,互不干扰。搜索 */ public class MailService { protected final Log log = LogFactory.getLog(getClass()); private JavaMailSenderImpl javaMailSender; // 一个初始化单例的velocity实例的类。 private VelocityEngine velocityEngine; private String title; private String encoding; private String templateLocation; private String[] toEmails; private Map<String, Object> model; public boolean send() { try { MimeMessage msg = javaMailSender.createMimeMessage(); MimeMessageHelper message = new MimeMessageHelper(msg, true, "UTF-8"); //重点在这里,多账号是在这里认证的 String username = Const.MAILUSERLIST.split(",")[(int)(Math.random()*10)]; javaMailSender.setUsername(username); javaMailSender.setPassword(Const.MAILPASSWORD); message.setFrom(username); message.setSubject(title); message.setTo(toEmails); message.setText(getMessage(), true); // 如果发的不是html内容去掉true参数 // message.addInline("myLogo",new // ClassPathResource("img/mylogo.gif")); // message.addAttachment("myDocument.pdf", new // ClassPathResource("doc/myDocument.pdf")); javaMailSender.send(msg); } catch (MessagingException e) { e.printStackTrace(); if (log.isWarnEnabled()) { log.warn("邮件信息导常! 邮件标题为: " + title); } return false; } catch (MailException me) { me.printStackTrace(); if (log.isWarnEnabled()) { log.warn("发送邮件失败! 邮件标题为: " + title); } return false; } return true; } /** * 邮件模板中得到信息 * * @return 返回特发送的内容 */ private String getMessage() { try { return VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templateLocation, encoding, model); } catch (VelocityException e) { e.printStackTrace(); log.error("邮件模板读取失败!邮件标题为: " + title); } return ""; } private String[] createToEmail(String to) { return new String[] { to }; } public void setToEmail(String to) { setToEmails(createToEmail(to)); } public void setJavaMailSender(JavaMailSenderImpl javaMailSender) { this.javaMailSender = javaMailSender; } public void setVelocityEngine(VelocityEngine velocityEngine) { this.velocityEngine = velocityEngine; } public void setEncoding(String encoding) { this.encoding = encoding; } public void setModel(Map<String, Object> model) { this.model = model; } public void setTemplateLocation(String templateLocation) { this.templateLocation = templateLocation; } public void setTitle(String title) { this.title = title; } public void setToEmails(String[] toEmails) { this.toEmails = toEmails; } public String getTemplateLocation() { return templateLocation; } } ``` #### 测试法方法 注入service后直接调用下面内容即可发送邮件 ``` Map<String, Object> data = new HashMap<String, Object>(); data.put("username", ciaDeveloper.getName()); data.put("useremail", ciaDeveloper.getEmail()); data.put("sureurl", "http://www.studyjava.cn"); // java模板引擎(velocity)apache的开源项目velocity做的文件就是.vm后缀 mailService.setTemplateLocation("register.vm"); mailService.setModel(data); mailService.setToEmail(ciaDeveloper.getEmail()); mailService.setTitle("激活CIA验证服务帐号"); mailService.send(); System.out.println("邮件发送成功!!"); ```
作者:じ☆ve宝贝
要访问一个MySQL服务器,你需要使用一个用户帐号登录其中方可进行。每个MySQL用户帐号都有许多与之相关连的属性,例如用户名、密码以及权限和资源限制。"权限"定义了特定用户能够在MySQL服务器中做什么,而"资源限制"为用户设置了一系列服务器资源的使用许可。创建或更新一个用户涉及到了对用户帐号所有属性的管理。  下面展示了如何在Linux中创建和设置一个MySQL用户。 首先以root身份登录到MySQL服务器中。 ``` $ mysql -u root -p ``` 当验证提示出现的时候,输入MySQL的root帐号的密码。  ###创建一个MySQL用户 使用如下命令创建一个用户名和密码分别为"myuser"和"mypassword"的用户。 ``` mysql> CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'mypassword'; ``` 一旦用户被创建后,包括加密的密码、权限和资源限制在内的所有帐号细节都会被存储在一个名为user的表中,这个表则存在于mysql这个特殊的数据库里。 运行下列命令,验证帐号是否创建成功 ``` mysql> SELECT host, user, password FROM mysql.user WHERE user='myuser' ``` ###赋予MySQL用户权限 一个新建的MySQL用户没有任何访问权限,这就意味着你不能在MySQL数据库中进行任何操作。你得赋予用户必要的权限。以下是一些可用的权限: - ALL: 所有可用的权限 - CREATE: 创建库、表和索引 - LOCK_TABLES: 锁定表 - ALTER: 修改表 - DELETE: 删除表 - INSERT: 插入表或列 - SELECT: 检索表或列的数据 - CREATE_VIEW: 创建视图 - SHOW_DATABASES: 列出数据库 - DROP: 删除库、表和视图 运行以下命令赋予"myuser"用户特定权限。 ``` mysql> GRANT <privileges> ON <database>.<table> TO 'myuser'@'localhost'; ``` 以上命令中,<privileges> 代表着用逗号分隔的权限列表。如果你想要将权限赋予任意数据库(或表),那么使用星号(*)来代替数据库(或表)的名字。 例如,为所有数据库/表赋予 CREATE 和 INSERT 权限: ``` mysql> GRANT CREATE, INSERT ON *.* TO 'myuser'@'localhost'; ``` 验证给用户赋予的全权限: ``` mysql> SHOW GRANTS FOR 'myuser'@'localhost'; ``` 将全部的权限赋予所有数据库/表: ``` mysql> GRANT ALL ON *.* TO 'myuser'@'localhost'; ``` 你也可以将用户现有的权限删除。使用以下命令废除"myuser"帐号的现有权限: ``` mysql> REVOKE <privileges> ON <database>.<table> FROM 'myuser'@'localhost'; ``` ###为用户添加资源限制 在MySQL中,你可以为单独的用户设置MySQL的资源使用限制。可用的资源限制如下: - MAX_QUERIES_PER_HOUR: 允许的每小时最大请求数量 - MAX_UPDATES_PER_HOUR: 允许的每小时最大更新数量 - MAX_CONNECTIONS_PER_HOUR: 允许的每小时最大连接(LCTT译注:其与 MySQL全局变量: max_user_connections 共同 决定用户到数据库的同时连接数量)数量 - MAX_USER_CONNECTIONS: 对服务器的同时连接量 使用以下命令为"myuser"帐号增加一个资源限制: ``` mysql> GRANT USAGE ON <database>.<table> TO 'myuser'@'localhost' WITH <resource-limits>; ``` 在 <resource-limits> 中你可以指定多个使用空格分隔开的资源限制。 例如,增加 MAXQUERIESPERHOUR 和 MAXCONNECTIONSPERHOUR 资源限制: ``` mysql> GRANT USAGE ON *.* TO 'myuser'@'localhost' WITH MAX_QUERIES_PER_HOUR 30 MAX_CONNECTIONS_PER_HOUR 6; ``` 验证用户的资源限制: ``` mysql> SHOW GRANTS FOR 'myuser'@'localhost; ````  创建和设置一个MySQL用户最后的一个重要步骤: ``` mysql> FLUSH PRIVILEGES; ``` 如此一来更改便生效了。现在MySQL用户帐号就可以使用了
作者:微信小助手
<p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);text-align: center;"><span style="font-family: 微软雅黑;font-size: 14px;widows: 1;max-width: 100%;color: rgb(178, 178, 178);line-height: 34.1333px;letter-spacing: 0.8px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;">点击上方“</span><span style="font-family: 微软雅黑;font-size: 14px;widows: 1;max-width: 100%;line-height: 34.1333px;letter-spacing: 0.8px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(0, 122, 170);"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">程序员大咖</strong></span><span style="max-width: 100%;color: rgb(178, 178, 178);">”,选择“置顶公众号”</span></span><span style="font-family: 微软雅黑;widows: 1;max-width: 100%;font-size: 14px;color: rgb(178, 178, 178);line-height: 34.1333px;letter-spacing: 0.8px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);text-align: center;"><span style="color: rgb(178, 178, 178);font-family: 微软雅黑;font-size: 18px;">关键时刻,第一时间送达!</span><img class="" data-ratio="0.0625" src="/upload/21f429670ba6010be4e5057a15790a6b.null" data-w="640" width="auto" style="font-family: 微软雅黑;font-size: 18px;color: rgb(178, 178, 178);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;visibility: visible !important;width: 656px !important;"><a href="https://mp.weixin.qq.com/s?__biz=MzI4MDYwMDc3MQ==&mid=2247484909&idx=2&sn=b6319708cc2ed28833109f2434d3d043&scene=21#wechat_redirect" target="_blank"><span class="js_jump_icon h5_image_link" data-positionback="static" style="top: auto;left: auto;right: auto;bottom: auto;"><img class="" data-copyright="0" data-ratio="0.5128205128205128" src="/upload/8f1fa0ea66334dac238224f74f6f0ced.gif" data-type="gif" data-w="390" style="color: rgb(136, 136, 136);font-size: 14px;width: 526.193px;top: auto;left: auto;right: auto;bottom: auto;"></span></a></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);text-align: center;"><br></p> <section class="mpa-template" data-mpa-template-id="328323" data-mpa-color="null" data-mpa-category="fav" style="white-space: normal;"> <section class="mpa-template" data-mpa-template-id="328323" data-mpa-color="null" data-mpa-category="fav"> <blockquote> <p><span style="color: rgb(136, 136, 136);font-size: 10px;">来源:https://www.cnblogs.com/jiahaoJAVA/p/6244278.html</span></p> <p><span style="color: rgb(136, 136, 136);font-size: 10px;">程序员大咖整理发布,转载请联系作者获得授权</span></p> </blockquote> <p><span style="color: rgb(136, 136, 136);font-size: 10px;"><br></span></p> </section> </section> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">1 什么是redis?</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"> </span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">Redis 是一个基于内存的高性能key-value数据库。 (有空再补充,有理解错误或不足欢迎指正)</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">2 Reids的特点</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: center;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-ratio="0.6" src="/upload/1c8771cc0606ee05c225612e21a546cf.jpg" data-type="jpeg" data-w="500"></p> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">3 Redis支持的数据类型</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">Redis通过Key-Value的单值不同类型来区分, 以下是支持的类型:<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">Strings<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">Lists<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">Sets 求交集、并集<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">Sorted Set <br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">hashes<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></span></p> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">4 为什么redis需要把所有数据放到内存中?</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></strong></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">5 Redis是单进程单线程的</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"> </span></p> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">6 虚拟内存</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.<br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h2 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">7 分布式</strong></span></h2> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">这是一个典型的分布式读写分离模型。我们可以利用master来插入数据,slave提供检索服务。这样可以有效减少单个机器的并发访问数量</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h3 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">8 读写分离模型</strong></span></h3> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">通过增加Slave DB的数量,读的性能可以线性增长。为了避免Master DB的单点故障,集群一般都会采用两台Master DB做双机热备,所以整个集群的读和写的可用性都非常高。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">读写分离架构的缺陷在于,不管是Master还是Slave,每个节点都必须保存完整的数据,如果在数据量很大的情况下,集群的扩展能力还是受限于单个节点的存储能力,而且对于Write-intensive类型的应用,读写分离架构并不适合。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"> </span><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h3 style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">9 数据分片模型</strong></span></h3> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">为了解决读写分离模型的缺陷,可以将数据分片模型应用进来。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">可以将每个节点看成都是独立的master,然后通过业务实现数据分片。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">结合上面两种模型,可以将每个master设计成由一个master和多个slave组成的模型。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">10 Redis的回收策略</strong></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"> </span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">no-enviction(驱逐):禁止驱逐数据</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">11. 使用Redis有哪些好处?</strong></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(2) 支持丰富数据类型,支持string,list,set,sorted set,hash</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">12. redis相比memcached有哪些优势?</span></strong></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(2) redis的速度比memcached快很多</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(3) redis可以持久化其数据</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(204, 0, 0);box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">13. redis常见性能问题和解决方案:</span></strong></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">(4) 尽量避免在压力很大的主库上增加从库</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB",
作者:微信小助手
<section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn" data-mpa-powered-by="yiban.io"></section> <p style="text-align: center;"><span style="color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;">点击上方蓝色“</span><span style="font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;color: rgb(0, 128, 255);">程序猿DD</span><span style="color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;">”,选择“设为星标”</span><br></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;text-align: center;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">回复“</span><span style="max-width: 100%;font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;color: rgb(0, 128, 255);overflow-wrap: break-word !important;box-sizing: border-box !important;">资源</span><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">”获取独家整理的学习资料!</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;white-space: normal;text-align: center;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="" data-backh="34" data-backw="540" data-ratio="0.0625" data-s="300,640" data-type="jpeg" data-w="640" width="100%" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.null" style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: 654px !important;"></span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;white-space: normal;text-align: center;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;font-size: 14px;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="" data-ratio="0.6153846153846154" src="/upload/14deb15b46448f80c2e1a0ce94fa2b23.jpg" data-type="jpeg" data-w="650"></span></p> <section style="text-align: right;margin-bottom: 15px;max-width: 100%;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;box-sizing: border-box !important;"> <span style="max-width: 100%;letter-spacing: 0.544px;font-family: Optima-Regular, PingFangTC-light;color: rgb(178, 178, 178);font-size: 13px;overflow-wrap: break-word !important;box-sizing: border-box !important;">来源 |<span style="color: rgb(178, 178, 178);max-width: 100%;letter-spacing: 0.544px;font-family: Optima-Regular, PingFangTC-light;white-space: pre-line;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <span style="color: rgb(178, 178, 178);max-width: 100%;font-family: "Monospaced Number", "Chinese Quote", -apple-system, system-ui, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;letter-spacing: 0.544px;text-align: start;white-space: pre;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;box-sizing: border-box !important;">https://dwz.cn/LuowUpuc</span></span></span> <span style="max-width: 100%;color: rgba(0, 0, 0, 0.65);font-family: "Monospaced Number", "Chinese Quote", -apple-system, system-ui, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;letter-spacing: 0.544px;text-align: start;white-space: pre;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;box-sizing: border-box !important;"></span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">最近,在知乎上看到一个有意思的问题,我个人觉得不错,挺有收获,在这里跟大家分享一下。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;background-color: rgb(255, 215, 213);">题目:《阿里巴巴JAVA开发手册》里面写超过三张表禁止join 这是为什么?这样的话那sql要怎么写?</span> <span style="background-color: rgb(255, 0, 0);font-size: 16px;"></span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;background-color: rgb(255, 215, 213);"><br></span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <img class="" data-ratio="0.13945945945945945" src="/upload/37866a370b3564c82ac9f773ce15af91.jpg" data-type="jpeg" data-w="925"> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;"><br></span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">一般,我对于这种问题,解决方案是查询官方文档,要么查看我的工具书《高性能的MySQL》,在本书的6.3节:重构查询的方式里面提到,<span style="background-color: rgb(255, 218, 169);">需要考虑实际情况,看看是否有必要将一个复杂的查询分解成多个简单的查询,并不一定要把所有的工作全都移交给数据库(转换思路)</span>!!!</span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <img class="rich_pages " data-ratio="0.6343327454438565" data-s="300,640" data-type="png" data-w="1701" src="/upload/ce322c02e8195b13cbd353eefd9b5255.png" style="width: 677px !important;visibility: visible !important;"> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">其实Join拆解的核心就是利用In关键字,这个也是出自该书,你不信,那我还是只能给你拍照(见下图)。</span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <img class="rich_pages " data-ratio="1.612037037037037" data-s="300,640" data-type="jpeg" data-w="1080" src="/upload/39470674acb9486880c467445ff89dab.jpg" style="width: 677px !important;visibility: visible !important;"> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">所有的问题答案都在书中,这也是我经常推荐大家,要多读书,读好书,比如,我经常给你们推荐的书(我又在装叉了,哈哈)。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">计算机解决问题,要么用空间换时间,要么用时间换空间,此二法基本上能解决大多数疑难杂症,你现在看到的各种高大上的玩法,基本上都跟此二法沾亲带故。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">比如,该问题下,阿里大佬李晨曦的回答,通过空间换时间的方案来设计表,虽然数据冗余了,但查询性能显著提升了,挺有意思。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);">------</p> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">该大佬的回答如下:</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <strong><span style="font-size: 16px;">一:</span><span style="font-size: 16px;">为什么做这种限制?</span></strong> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">打个比方,如果我有无限的钱,我想买个豪华别墅,想买个跑车,想买个直升飞机,但现实是我没钱,只能租房住,只能走路上下班。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">如果数据库的性能无限强大,多个表的join肯定是需要的,尤其是复杂的分析型(OLAP)查询,甚至可能涉及10几个表的join,但现实是大部分数据库的性能都太弱了,尤其是涉及到多表join的查询。给@韩飞点个赞,国内懂这个做这个的太少了,以后就靠他们了。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">规范一看就是在使用MySQL时的限制(这种规范实际上迫不得已的限制),做这个限制有两个原因:一是优化器很弱,涉及多个表的查询,往往得不到很好的查询计划,这块比较复杂,感兴趣的朋友可以关注我,我以后会写文章专门介绍;二是执行器很弱,只有nested loop join,block nested loop join和index nested loop join。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">1、nested loop join就是分别从两个表读一行数据进行两两对比,复杂度是n^2。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">2、block nested loop join是分别从两个表读很多行数据,然后进行两两对比,复杂度也是n^2,只是少了些函数调用等overhead。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">3、index nested loop join是从第一个表读一行,然后在第二个表的索引中查找这个数据,索引是B+树索引,复杂度可以近似认为是nlogn,比上面两个好很多,这就是要保证关联字段有索引的原因。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">4、 如果有hash join,就不用做这种限制了,用第一个表(小表)建hash table,第二个表在hash table中查找匹配的项,复杂度是n。缺点是hash table占的内存可能会比较大,不过也有基于磁盘的hash join,实现起来比较复杂。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <strong><span style="font-size: 16px;">二:</span><span style="font-size: 16px;">在这种限制下SQL怎么写?</span></strong> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">可是我确实需要两个表里的数据链接在一起啊,我们可以做个冗余,建表的时候,就把这些列放在一个表里,比如一开始有student(id, name),class(id, description),student_class(student_id, class_id)三张表,这样是符合数据库范式的(第一范式,第二范式,第三范式,BC范式等),没有任何冗余,但是马上就不符合“编程规范“了,那我们可以用一张大表代替它,student_class_full(student_id, class_id, name, description),这样name和description可能要被存储多份,但是由于不需要join了,查询的性能就可以提高很多了。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;background-color: rgb(255, 218, 169);">任何的规范都是在特定情况下的某种妥协,脱离了这个环境,就不一定成立了。</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">----------</span> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">其实,很多同学问我,我是如何解决编程的问题?</span> <span style="font-size: 16px;background-color: rgb(255, 218, 169);">其实我就是按照以前做数学应用题的方法来解决编程问题,大问题拆分成小问题,小问题在书中就会有相应的例题,照猫画虎,所有小问题都击破了,那么,大问题就迎刃而解了,这便是所谓的不攻自破。</span> <br> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">其实,你遇到的问题,90%都能通过搜索引擎解决,而你非得要做伸手党,哎...</span> <br> </section> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="1" data-type="jpeg" data-w="225" src="/upload/f936859aaa2c8959fe7fb7e22afa4e6b.jpg" style="width: 225px !important;visibility: visible !important;"></p> <p style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">最后,还是推荐一下《高性能MySQL》这本给各位同学(这是我第3次推荐了~~~),没事多读读,网上也有电子版,但我建议大家还是去买一本实体书,当做工具书用。</span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;"><br></span> </section> <section> <mpcps frameborder="0" class="js_editor_cps" data-datakey="1574253258200_0.28435708618244737" style="width:100% !important;border:0;" data-uid="1574253258206" data-type="1" data-product="" data-templateid="list" data-pid="23214590" data-packid="" data-smartnum="" data-color="#fa7834" data-categoryid="3" data-appid="wx831660fe3ded4389" data-report="s0%3D0%26s1%3D0%26s2%3D0%26s3%3D%25E9%25AB%2598%25E6%2580%25A7%25E8%2583%25BDMySQL%26s4%3D0%26s5%3D10%26s6%3Did_1574255323662_161154%26s7%3D%26s8%3D%26s9%3D%26s10%3D%26pid%3Dwx831660fe3ded4389_23214590%26uuid%3D30187261351335814345%26title%3D%25E9%25AB%2598%25E6%2580%25A7%25E8%2583%25BDMySQL%25EF%25BC%2588%25E7%25AC%25AC3%25E7%2589%2588%25EF%25BC%2589%26sid%3D3%26cid%3D3%26ratio%3D17.00%2525%26price%3D88.30%26"></mpcps> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <br> <span style="font-size: 16px;"></span> </section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"></section> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: Optima-Regular, PingFangTC-light;"> <span style="font-size: 16px;">多读书,读好书。</span> </section> <p style="text-align: left;margin-top: 10px;"><br></p> <section class="" style="max-width: 100%;white-space: normal;letter-spacing: 0.544px;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <p style="line-height: 27.2px;max-width: 100%;letter-spacing: normal;color: rgb(62, 62, 62);font-weight: 400;overflow-wrap: break-word;box-sizing: border-box;margin: 0px;padding: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;white-space: normal;min-height: 17px;font-size: 17px;background-image: none;background-clip: border-box;background-position: 0% 0%;background-repeat: repeat;background-size: auto;border-width: 0px;border-style: none;border-color: rgb(62, 62, 62);bottom: auto;display: block;float: none;height: auto;left: auto;max-height: none;min-width: 0px;text-align: justify;text-decoration: none solid rgb(62, 62, 62);top: auto;z-index: auto;visibility: visible;clear: both;"><img class="" data-ratio="0.037096774193548385" data-type="png" data-w="620" width="536px" src="/upload/51d6fabc9de3c2c58426d89f435a5d12.png" style="margin-right: auto;margin-left: auto;letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);text-align: center;line-height: 25.6px;font-family: monospace;font-size: 15px;display: block;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: auto !important;"></p> </section> </section> <section class="" style="max-width: 100%;white-space: normal;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;caret-color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-size-adjust: auto;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" style="max-width: 100%;line-height: 1.6;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" data-style-type="6" data-tools="新媒体排版" data-id="8751" style="max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section class="" data-mpa-template-id="90" data-mpa-color="#ffffff" data-mpa-category="quote" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section style="margin: 30px auto;padding: 25px 20px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;background-color: rgb(247, 247, 247);"> <section data-preserve-color="t" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <section style="margin-top: 5px;max-width: 100%;text-align: center;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <span style="max-width: 100%;color: rgb(136, 136, 136);font-size: 12px;overflow-wrap: break-word !important;box-sizing: border-box !important;">本文通过OpenWrite的Markdown转换工具发布</span> </section> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;text-align: center;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;font-size: 12px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="background-color: rgb(255, 255, 255);max-width: 100%;color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">关注我,回复“</span><span style="background-color: rgb(255, 255, 255);max-width: 100%;font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;letter-spacing: 0.544px;color: rgb(0, 128, 255);overflow-wrap: break-word !important;box-sizing: border-box !important;">加群</span><span style="background-color: rgb(255, 255, 255);max-width: 100%;color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">”<span style="background-color: rgb(255, 255, 255);max-width: 100%;color: rgba(0, 0, 0, 0.498);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">加入各种主题讨论群</span></span></span></p> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;white-space: normal;text-align: center;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="rich_pages" data-ratio="0.18524332810047095" src="/upload/d2a38b8f8a4c599687e2292f14dfd57b.gif" data-type="gif" data-w="637" style="height: 41px;width: 220px;overflow-wrap: break-word !important;box-sizing: border-box !important;"></p> <ul class=" list-paddingleft-2" style="list-style-type: circle;"> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247488919&idx=2&sn=fca0d6fcf2ed70bbbd194a020aadf5ae&chksm=9bd0b80faca731199354dbf669257b53d08694a97c9efce93d0896d4c059d02cefa90e980f2e&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="text-decoration: underline;" data-linktype="2"><span style="text-decoration: underline;font-size: 14px;">RESTful 架构基础</span></a></p></li> <li><p><span style="text-decoration: underline;font-size: 14px;"><a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247488902&idx=1&sn=f99e953f8dcad7425268d0188fd81462&chksm=9bd0b81eaca73108f44f924de5b74c0319ba21ac56463846477de0129dce1168ac6b01b8d03b&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">17 个方面,综合对比四大消息中间件</a></span></p></li> <li><p><a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247488895&idx=2&sn=0b1c2d9b27463cc9b8f3d55316bddcc5&chksm=9bd0b8e7aca731f1bb53a1fc030eb0e54f283ed2ed044d556a6199587003fea2800e8018545a&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-decoration: underline;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-decoration: underline;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 14px;">9 个爱不释手的 JSON 工具</span></a></p></li> <li><p><a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247488890&idx=1&sn=b6fb5b2e67629ee348dd901eb7076e8e&chksm=9bd0b8e2aca731f4bab79c636fabed11b9a22a25fc90bd3808409a3a614189c5ab13d9c067d6&scene=21#wechat_redirect" target="_blank" data-itemshowtype="11" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;text-decoration: underline;"><span style="text-decoration: underline;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 14px;">手把手教你定制标准 Spring Boot starter</span></a></p></li> <li><p><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;text-decoration: underline;font-size: 14px;"><a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247488890&idx=2&sn=48ec821f5056110a2e4994c8d12afe8e&chksm=9bd0b8e2aca731f4aeae2dc29929ef1ed632b461ded2a100a38a2c0aedbffd329c43be7301e0&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">程序员接私活的10个平台和一些建议</a></span></p></li> </ul> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-variant-numeric: normal;font-variant-east-asian: normal;font-weight: 700;letter-spacing: 0.544px;text-align: right;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);widows: 1;font-family: Optima-Regular, PingFangTC-light;font-size: 14px;overflow-wrap: break-word !important;box-sizing: border-box !important;">朕已阅 </span><img class="__bg_gif" data-ratio="1" data-type="gif" data-w="19" src="/upload/6d654f7f0528a43fa6e93c1b3334f39e.null" width="19px" style="font-weight: 700;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;font-variant-numeric: normal;line-height: 25.6px;text-align: center;widows: 1;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: 19px !important;"></p>
作者:向往美好明天
### js监听click时间ajax回调html后事件监听无效: **原因:** ` 因为ajax回调后,在本页面的click监听事件也随之注销。所以再次点击的时候就没有效果了 ` **解决:** ` 把事件的click监听函数包含在ajax回掉的返回之中,包含到jsp页面就可以解决问题 `
作者:じ☆ve宝贝
## <classPathEntry> 驱动文件指定配置项 ``` <classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" /> <columnOverride> ``` ## 将数据库中的字段重命名为实体类的属性 column 数据库中字段名 property POJO属性名 javaType POJO类型 jdbcType 数据库字段类型 ``` <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" > <property name="useActualColumnNames" value="true"/> <generatedKey column="ID" sqlStatement="DB2" identity="true" /> <columnOverride column="DATE_FIELD" property="startDate" /> <ignoreColumn column="FRED" /> <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> </table> ``` ## <columnRenamingRule> 按规则将数据库中的字段重命名为实体类的属性 ``` <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" > <columnRenamingRule searchString="^CUST_" replaceString="" /> .. </table> ``` ## <commentGenerator> 代码上面的注释规则 子属性:property porperties: suppressAllComments false时打开注释,true时关闭注释 suppressDate false时打开时间标志,true时关闭...真是反人类啊 ``` <commentGenerator> <property name="suppressDate" value="true" /> </commentGenerator> ``` ## <context> 这个实在不知道怎么解释,反正就是大环境 targetRuntime 可选项,可填值为MyBatis3,MyBatis3Simple(默认的),Ibatis2Java2,Ibatis2Java5 ``` <context id="DB2Tables" targetRuntime="MyBatis3"> ... </context> ``` ## <generatedKey> 指定自增加以及Id column 字段 sqlStatement 数据库语句,可以为MySql,DB2,SqlServer,SyBase等http://mybatis.github.io/generator/configreference/generatedKey.html identity true为id,false不为id ``` <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" > <property name="useActualColumnNames" value="true"/> <generatedKey column="ID" sqlStatement="DB2" identity="true" /> <columnOverride column="DATE_FIELD" property="startDate" /> <ignoreColumn column="FRED" /> <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> </table> ``` ## <ignoreColumn> 忽略字段 column 字段名 ``` <table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" > <ignoreColumn column="FRED" /> .. </table> ``` ## <javaClientGenerator> Mapper生成配置 type XMLMAPPER配置文件方式,ANNOTATEDMAPPER注解方式 http://mybatis.github.io/generator/configreference/javaClientGenerator.html ``` <javaClientGenerator type="XMLMAPPER" targetPackage="dao.mapper" targetProject="app"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <javaModelGenerator> ``` 实体类生成配置 http://mybatis.github.io/generator/configreference/javaModelGenerator.html ``` <javaModelGenerator targetPackage="domain" targetProject="app"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="false" /> </javaModelGenerator> <javaTypeResolver> ``` mybatis里专门用来处理NUMERIC和DECIMAL类型的策略 ``` <javaTypeResolver> <property name="forceBigDecimals" value="true" /> </javaTypeResolver> ``` ## <jdbcConnection> jdbc配置,不解释了哈 ``` <jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver" connectionURL="jdbc:db2:MBGTEST" userId="db2admin" password="db2admin"> </jdbcConnection> ``` ## <sqlMapGenerator> 生成sql语句的xml文件 在mybatis2里是必须的,在mybatis3中,只有用XML方式的时候才是需要的。 ``` <sqlMapGenerator targetPackage="test.model" targetProject="\MyProject\src"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> ```
作者:微信小助手
<section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <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;" title="" opera-tn-ra-cell="_$.pages:0.layers:0.comps:0.txt1"> <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;">周末无聊刷着手机,某宝网 App 突然蹦出来一条消息“为了回馈老客户,女朋友买一送一,活动仅限今天!”。</span></p> </section> <section style="clear: both;box-sizing: border-box;"></section> </section> </section> </section> <p style="line-height: 1.75em;"><br></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.5602322206095791" data-s="300,640" src="/upload/712eb438f5e20559a905ec7bb1b07aef.png" data-type="png" data-w="689" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">买一送一还有这种好事,那我可不能错过!忍不住立马点了去。于是选了两个最新款,下单、支付一气呵成!满足的躺在床上,想着马上有女朋友了,竟然幸福的失眠了……</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">第二天正常上着班,突然接到快递小哥的电话:</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">小哥:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">“你是 xx 吗?你的女朋友到了,我现在在你楼下,你来拿一下吧!”。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">“这……我在上班呢,可以晚上送过来吗?“。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">小哥:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">“晚上可不行哦,晚上我也下班了呢!”。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">于是两个人僵持了很久……</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">最后小哥说,要不我帮你放到楼下小芳便利店吧,你晚上下班了过来拿,尴尬的局面这才得以缓解!</span></p> <p style="line-height: normal;"><br></p> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="menu-title" style="box-sizing: border-box;">为什么需要消息队列</p> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">回到正题,如果没有小芳便利店,那快递小哥和我的交互图就应:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><img class="" data-ratio="0.37397034596375617" src="/upload/7aabe0c29e1d0a2009b06677027cee3a.png" data-type="png" data-w="607" style="line-height: 1.75em;box-sizing: content-box;border: 0px none;vertical-align: middle;"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">会出现什么情况呢?</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">为了这个女朋友,我请假回去拿(老板不批)。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">小哥一直在你楼下等(小哥还有其他的快递要送)。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">周末再送(显然等不及)。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这个女朋友我不要了(绝对不可能)!</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">小芳便利店出现后,交互图如下:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="" data-ratio="0.3684210526315789" src="/upload/75fa203b114dfae53cecd7a5376da477.png" data-type="png" data-w="608" style="line-height: 1.75em;box-sizing: content-box;border: 0px none;vertical-align: middle;"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在上面例子中,“快递小哥”和“买女朋友的我”就是需要交互的两个系统,小芳便利店就是我们本文要讲的消息中间件。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">总结下来小芳便利店(消息中间件)出现后有如下好处:</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>解耦</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">快递小哥手上有很多快递需要送,他每次都需要先电话一一确认收货人是否有空、哪个时间段有空,然后再确定好送货的方案。这样完全依赖收货人了!如果快递一多,快递小哥估计得忙疯了……</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果有了便利店,快递小哥只需要将同一个小区的快递放在同一个便利店,然后通知收货人来取货就可以了,这时候快递小哥和收货人就实现了解耦!</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>异步</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">快递小哥打电话给我后需要一直在你楼下等着,直到我拿走你的快递他才能去送其他人的。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">快递小哥将快递放在小芳便利店后,又可以干其他的活儿去了,不需要等待你到来而一直处于等待状态,提高了工作的效率。</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>削峰</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">假设双十一我买了不同店里的各种商品,而恰巧这些店发货的快递都不一样,有中通、圆通、申通、各种通等……更巧的是他们都同时到货了!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">中通的小哥打来电话叫我去北门取快递、圆通小哥叫我去南门、申通小哥叫我去东门。我一时手忙脚乱……</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们能看到在系统需要交互的场景中,使用消息队列中间件真的是好处多多,基于这种思路,就有了丰巢、菜鸟驿站等比小芳便利店更专业的“中间件”了。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">最后,上面的故事纯属虚构……</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">消息队列通信的模式</p> </section> </section> </section> </section> <p style="line-height: normal;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <h1></h1> <h1 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">通过上面的例子我们引出了消息中间件,并且介绍了消息队列出现后的好处,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">这里就需要介绍消息队列通信的两种模式了:</span></h1> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="menu-title" style="box-sizing: border-box;"><strong>点对点模式</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.47079439252336447" data-s="300,640" src="/upload/dff0634939d901edc482dbeb056f8d3f.png" data-type="png" data-w="856"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如上图所示,点对点模式通常是基于拉取或者轮询的消息传送模型,这个模型的特点是发送到队列的消息被一个且只有一个消费者进行处理。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">生产者将消息放入消息队列后,由消费者主动的去拉取消息进行消费。点对点模型的优点是消费者拉取消息的频率可以由自己控制。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但是消息队列是否有消息需要消费,在消费者端无法感知,所以在消费者端需要额外的线程去监控。</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="menu-title" style="box-sizing: border-box;"><strong>发布订阅模式</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.4712778429073857" data-s="300,640" src="/upload/d8b582f3402de8f713ce788fdcbc6e18.png" data-type="png" data-w="853"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如上图所示,发布订阅模式是一个基于消息送的消息传送模型,该模型可以有多种不同的订阅者。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">生产者将消息放入消息队列后,队列会将消息推送给订阅过该类消息的消费者(类似微信公众号)。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">由于是消费者被动接收推送,所以无需感知消息队列是否有待消费的消息!但是 Consumer1、Consumer2、Consumer3 由于机器性能不一样,所以处理消息的能力也会不一样,但消息队列却无法感知消费者消费的速度!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以推送的速度成了发布订阅模式的一个问题!假设三个消费者处理速度分别是 8M/s、5M/s、2M/s,如果队列推送的速度为 5M/s,则 Consumer3 无法承受!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果队列推送的速度为 2M/s,则 Consumer1、Consumer2 会出现资源的极大浪费!</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">Kafka</p> </section> </section> </section> </section> <p style="line-height: normal;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <h1></h1> <h1 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面简单的介绍了为什么需要消息队列以及消息队列通信的两种模式,接下来就到了我们本文的主角 Kafka 闪亮登场的时候了!</span></h1> <p style="line-height: normal;"><br></p> <h1></h1> <h1 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据,具有高性能、持久化、多副本备份、横向扩展能力……… </span></h1> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="menu-title" style="box-sizing: border-box;"><strong>基础架构及术语</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <h2 class="menu-title"></h2> <h2 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">话不多说,先看图,通过这张图我们来捋一捋相关的概念及之间的关系:</span></h2> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.6811881188118812" data-s="300,640" src="/upload/ee57256660da62d5de4c0b8c3fb1f9a8.png" data-type="png" data-w="1010"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果看到这张图你很懵逼,木有关系!我们先来分析相关概念:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Producer:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Producer 即生产者,消息的产生者,是消息的入口。<br style="box-sizing: border-box;"></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Kafka Cluster:</span></strong></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Broker:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Broker 是 Kafka 实例,每个服务器上有一个或多个 Kafka 的实例,我们姑且认为每个 Broker 对应一台服务器。</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">每个 Kafka 集群内的 Broker 都有一个不重复的编号,如图中的 Broker-0、Broker-1 等……</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Topic:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消息的主题,可以理解为消息的分类,Kafka 的数据就保存在 Topic。在每个 Broker 上都可以创建多个 Topic。</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Partition:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Topic 的分区,每个 Topic 可以有多个分区,分区的作用是做负载,提高 Kafka 的吞吐量。</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">同一个 Topic 在不同的分区的数据是不重复的,Partition 的表现形式就是一个一个的文件夹!</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Replication:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">每一个分区都有多个副本,副本的作用是做备胎。当主分区(Leader)故障的时候会选择一个备胎(Follower)上位,成为 Leader。</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在 Kafka 中默认副本的最大数量是 10 个,且副本的数量不能大于 Broker 的数量,Follower 和 Leader 绝对是在不同的机器,同一机器对同一个分区也只可能存放一个副本(包括自己)。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Message:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">每一条发送的消息主体。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Consumer:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消费者,即消息的消费方,是消息的出口。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Consumer Group:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们可以将多个消费组组成一个消费者组,在 Kafka 的设计中同一个分区的数据只能被消费者组中的某一个消费者消费。</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">同一个消费者组的消费者可以消费同一个 Topic 的不同分区的数据,这也是为了提高 Kafka 的吞吐量!</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Zookeeper:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Kafka 集群依赖 Zookeeper 来保存集群的的元信息,来保证系统的可用性。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section class="ui-sortable-handle" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span></strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="menu-title" style="box-sizing: border-box;"><strong>工作流程分析</strong></p> </section> </section> </section> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面介绍了 Kafka 的基础架构及基本概念,不知道大家看完有没有对 Kafka 有个大致印象,如果还比较懵也没关系!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们接下来再结合上面的结构图分析 Kafka 的工作流程,最后再回来整个梳理一遍我相信你会更有收获!</span></p> <p style="line-height: normal;"><br></p> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;"><strong><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">发送数据</span></strong></span></h3> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们看上面的架构图中,Producer 就是生产者,是数据的入口。注意看图中的红色箭头,Producer 在写入数据的时候永远在找 Leader,不会直接将数据写入 Follower!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">那 Leader 怎么找呢?写入的流程又是什么样的呢?我们看下图:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.47399411187438667" data-s="300,640" src="/upload/11a94a2d688f9384a8fcd1f5e19f88a9.png" data-type="png" data-w="1019"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">发送的流程就在图中已经说明了,就不单独在文字列出来了!需要注意的一点是,消息写入 Leader 后,Follower 是主动的去 Leader 进行同步的!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Producer 采用 Push 模式将数据发布到 Broker,每条消息追加到分区中,顺序写入磁盘,所以保证同一分区内的数据是有序的!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">写入示意图如下:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.4966292134831461" data-s="300,640" src="/upload/d24171b8aa69a23129b65e68ad55e23b.png" data-type="png" data-w="890"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面说到数据会写入到不同的分区,那 Kafka 为什么要做分区呢?相信大家应该也能猜到,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">分区的主要目的是:</span></p> <ul class=" list-paddingleft-2" style="margin-left: 8px;margin-right: 8px;"> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">方便扩展。</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">因为一个 Topic 可以有多个 Partition,所以我们可以通过扩展机器去轻松的应对日益增长的数据量。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">提高并发。</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">以 Partition 为读写单位,可以多个消费者同时消费数据,提高了消息的处理效率。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">熟悉负载均衡的朋友应该知道,当我们向某个服务器发送请求的时候,服务端可能会对请求做一个负载,将流量分发到不同的服务器。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">那在 Kafka 中,如果某个 Topic 有多个 Partition,Producer 又怎么知道该将数据发往哪个 Partition 呢?</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">Kafka 中有几个原则:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Partition 在写入的时候可以指定需要写入的 Partition,如果有指定,则写入对应的 Partition。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果没有指定 Partition,但是设置了数据的 Key,则会根据 Key 的值 Hash 出一个 Partition。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果既没指定 Partition,又没有设置 Key,则会轮询选出一个 Partition。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">保证消息不丢失是一个消息队列中间件的基本保证,那 Producer 在向 Kafka 写入消息的时候,怎么保证消息不丢失呢?</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">其实上面的写入流程图中有描述出来,那就是通过 ACK 应答机制!在生产者向队列写入数据的时候可以设置参数来确定是否确认 Kafka 接收到数据,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">这个参数可设置的值为 0、1、all:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">0 代表 Producer 往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">1 代表 Producer 往集群发送数据只要 Leader 应答就可以发送下一条,只确保 Leader 发送成功。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">all 代表 Producer 往集群发送数据需要所有的 Follower 都完成从 Leader 的同步才会发送下一条,确保 Leader 发送成功和所有的副本都完成备份。安全性最高,但是效率最低。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">最后要注意的是,如果往不存在的 Topic 写数据,能不能写入成功呢?Kafka 会自动创建 Topic,分区和副本的数量根据默认配置都是 1。</span></p> <p style="line-height: normal;"><br></p> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;"><strong><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">保存数据</span></strong></span></h3> <p style="line-height: normal;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <h3 class="menu-title"></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Producer 将数据写入 Kafka 后,集群就需要对数据进行保存了!Kafka 将数据保存在磁盘,可能在我们的一般的认知里,写入磁盘是比较耗时的操作,不适合这种高并发的组件。</span></h3> <p style="line-height: normal;"><br></p> <h3 class="menu-title"></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Kafka 初始会单独开辟一块磁盘空间,顺序写入数据(效率比随机写入高)。</span></h3> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①Partition 结构</span></strong></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">前面说过了每个 Topic 都可以分为一个或多个 Partition,如果你觉得 Topic 比较抽象,那 Partition 就是比较具体的东西了!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Partition 在服务器上的表现形式就是一个一个的文件夹,每个 Partition 的文件夹下面会有多组 Segment 文件。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">每组 Segment 文件又包含 .index 文件、.log 文件、.timeindex 文件(早期版本中没有)三个文件。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Log 文件就是实际存储 Message 的地方,而 Index 和 Timeindex 文件为索引文件,用于检索消息。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.8819444444444444" data-s="300,640" src="/upload/69a73ab49a465dc53866b6e6d55e2210.png" data-type="png" data-w="432"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如上图,这个 Partition 有三组 Segment 文件,每个 Log 文件的大小是一样的,但是存储的 Message 数量是不一定相等的(每条的 Message 大小不一致)。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">文件的命名是以该 Segment 最小 Offset 来命名的,如 000.index 存储 Offset 为 0~368795 的消息,Kafka 就是利用分段+索引的方式来解决查找效率的问题。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②Message 结构</span></strong></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面说到 Log 文件就实际是存储 Message 的地方,我们在 Producer 往 Kafka 写入的也是一条一条的 Message。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">那存储在 Log 中的 Message 是什么样子的呢?</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">消息主要包含消息体、消息大小、Offset、压缩类型……等等!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">我们重点需要知道的是下面三个:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Offset:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Offset 是一个占 8byte 的有序 id 号,它可以唯一确定每条消息在 Parition 内的位置!</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消息大小:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消息大小占用 4byte,用于描述消息的大小。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消息体:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消息体存放的是实际的消息数据(被压缩过),占用的空间根据具体的消息而不一样。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">③存储策略</span></strong></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">无论消息是否被消费,Kafka 都会保存所有的消息。</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">那对于旧数据有什么删除策略呢?</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">基于时间,</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">默认配置是 168 小时(7 天)。</span></p></li> <li><p style="text-align: justify;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">基于大小,</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">默认配置是 1073741824。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">需要注意的是,Kafka 读取特定消息的时间复杂度是 O(1),所以这里删除过期的文件并不会提高 Kafka 的性能!</span></p> <p style="line-height: normal;"><br></p> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;"><strong><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">消费数据</span></strong></span></h3> <p style="line-height: normal;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <h3 class="menu-title"></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">消息存储在 Log 文件后,消费者就可以进行消费了。在讲消息队列通信的两种模式的时候讲到过点对点模式和发布订阅模式。</span></h3> <p style="line-height: normal;"><br></p> <h3 class="menu-title"></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Kafka 采用的是点对点的模式,消费者主动的去 Kafka 集群拉取消息,与 Producer 相同的是,消费者在拉取消息的时候也是找 Leader 去拉取。</span></h3> <p style="line-height: normal;"><br></p> <h3 class="menu-title"></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">多个消费者可以组成一个消费者组(Consumer Group),每个消费者组都有一个组 id!</span></h3> <p style="line-height: normal;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <h3 class="menu-title"></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">同一个消费组者的消费者可以消费同一 Topic 下不同分区的数据,但是不会组内多个消费者消费同一分区的数据!</span></h3> <h3 class="menu-title" style="line-height: normal;"><br></h3> <h3 class="menu-title" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="color: rgb(71, 193, 168);"><span style="font-size: 15px;letter-spacing: 1px;">是不是有点绕?</span><span style="font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">我们看下图:</span></span></h3> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.40836012861736337" data-s="300,640" src="/upload/4fcbe01b6cba90afa5948f0bc29d38ea.png" data-type="png" data-w="933"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">图示是消费者组内的消费者小于 Partition 数量的情况,所以会出现某个消费者消费多个 Partition 数据的情况,消费的速度也就不及只处理一个 Partition 的消费者的处理速度!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果是消费者组的消费者多于 Partition 的数量,那会不会出现多个消费者消费同一个 Partition 的数据呢?</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面已经提到过不会出现这种情况!多出来的消费者不消费任何 Partition 的数据。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以在实际的应用中,建议消费者组的 Consumer 的数量与 Partition 的数量一致!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在保存数据的小节里面,我们聊到了 Partition 划分为多组 Segment,每个 Segment 又包含 .log、.index、.timeindex 文件,存放的每条 Message 包含 Offset、消息大小、消息体……</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们多次提到 Segment 和 Offset,查找消息的时候是怎么利用 Segment+Offset 配合查找的呢?</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">假如现在需要查找一个 Offset 为 368801 的 Message 是什么样的过程呢?</span><span style="line-height: 29.75px;font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">我们先看看下面的图:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.3535958904109589" data-s="300,640" src="/upload/270814fefc20645b7ce03acde2292800.png" data-type="png" data-w="1168"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①先找到 Offset 的 368801message 所在的 Segment 文件(利用二分法查找),这里找到的就是在第二个 Segment 文件。<br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②打开找到的 Segment 中的 .index 文件(也就是 368796.index 文件,该文件起始偏移量为 368796+1。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们要查找的 Offset 为 368801 的 Message 在该 Index 内的偏移量为 368796+5=368801,所以这里要查找的相对 Offset 为 5)。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">由于该文件采用的是稀疏索引的方式存储着相对 Offset 及对应 Message 物理偏移量的关系,所以直接找相对 Offset 为 5 的索引找不到。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这里同样利用二分法查找相对 Offset 小于或者等于指定的相对 Offset 的索引条目中最大的那个相对 Offset,所以找到的是相对 Offset 为 4 的这个索引。<br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">③根据找到的相对 Offset 为 4 的索引确定 Message 存储的物理偏移位置为 256。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">打开数据文件,从位置为 256 的那个地方开始顺序扫描直到找到 Offset 为 368801 的那条 Message。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这套机制是建立在 Offset 为有序的基础上,利用 Segment+有序 Offset+稀疏索引+二分查找+顺序查找等多种手段来高效的查找数据!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">至此,消费者就能拿到需要处理的数据进行处理了。那每个消费者又是怎么记录自己消费的位置呢?</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在早期的版本中,消费者将消费到的 Offset 维护在 Zookeeper 中,Consumer 每间隔一段时间上报一次,这里容易导致重复消费,且性能不好!</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在新的版本中消费者消费到的 Offset 已经直接维护在 Kafka 集群的 __consumer_offsets 这个 Topic 中!</span></p> <p style="line-height: normal;"><br></p> <p style="white-space: normal;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;"><em><span style="font-size: 14px;">作者:苏静</span></em></span></p> <p style="white-space: normal;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;"><em><span style="font-size: 14px;">简介:有过多年大型互联网项目的开发经验,对高并发、分布式、以及微服务技术有深入的研究及相关实践经验。经历过自学,热衷于技术研究与分享!格言:始终保持虚心学习的态度! </span></em></span></p> <p style="white-space: normal;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;"><em><span style="font-size: 14px;">编辑:陶家龙、孙淑娟</span></em></span><br></p> <p style="white-space: normal;line-height: 1.75em;"><span style="font-size: 14px;letter-spacing: 1px;color: rgb(89, 89, 89);"><em>出处:17coding 技术博客:http://www.17coding.info/</em></span></p> <p style="text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="0.3939393939393939" src="/upload/58a14061a632a0fe87d40beb73c1aa.gif" data-type="gif" data-w="660" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="font-size: 15px;border-style: solid;border-width: 0px 0px 1px;color: rgb(89, 89, 89);border-bottom-color: rgba(215, 215, 215, 0.960784);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><strong>精彩文章推荐:</strong></span></p> </section> </section> </section> <p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655824554&idx=3&sn=aeccfc4f704474f513688c706a71ec94&chksm=bd74e77d8a036e6bae85c18675ab9163d61176634cbd85b6bdda281359a9e625d13781a9ac33&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;text-decoration: none;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">谷歌全球大规模宕机4小时,苹果iCloud也遭殃!</span></a><br></p> <p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655824527&idx=1&sn=cecf1587164d836a82ec6b3a7b13cdd7&chksm=bd74e7588a036e4e75ca783dae0f60e56b001b49b99f6da4dff9a369b6a3544fa04cb616d6bb&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;text-decoration: none;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">让美国颤抖的5G,到底牛在哪?</span></a><br></p> <p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655824452&idx=1&sn=ac4d469f248f5a689ef83525138ad356&chksm=bd74e7938a036e85ed8398815097df89748eaa1b856dd749e69b7b7a822d0080777d00c1a3a2&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;text-decoration: none;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">看完这篇文章,我奶奶都懂了HTTPS原理</span></a><br></p>