文章列表

一文学会Java死锁和CPU 100% 问题的排查技巧

作者:微信小助手

<section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <p style="text-align: center;"><strong style="max-width: 100%;letter-spacing: 0.544px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 16px;white-space: pre-line;background-color: rgb(255, 255, 255);text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></strong></p> <p style="white-space: normal;text-align: center;"><span style="font-size: 14px;color: rgb(136, 136, 136);"></span></p> <p style="white-space: normal;text-align: center;"><span style="color: rgb(136, 136, 136);font-family: Georgia, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, serif;font-size: 14px;letter-spacing: 0.544px;">点击蓝色“</span><span style="font-family: Georgia, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, 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, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, serif;font-size: 14px;letter-spacing: 0.544px;">”关注我</span></p> <p style="white-space: normal;text-align: center;"><span style="color: rgb(136, 136, 136);font-family: Georgia, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, serif;font-size: 14px;letter-spacing: 0.544px;">回复“</span><span style="font-family: Georgia, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, serif;font-size: 14px;letter-spacing: 0.544px;color: rgb(0, 128, 255);">资源</span><span style="color: rgb(136, 136, 136);font-family: Georgia, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, serif;font-size: 14px;letter-spacing: 0.544px;">”获取独家整理的学习资料!</span></p> <h3 style="margin: 40px 10px 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;color: rgb(63, 63, 63);line-height: 1.5;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">00 本文简介</h3> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">作为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在实际的工作或者面试就有遇到过:</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">第一个问题:Java死锁如何排查和解决?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">第二个问题:服务器CPU占用率高达到100%排查和解决?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">第三个问题:有哪些工具能够快速查看线程使用情况?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">本文对这三个问题进行总结整理,通过实例演示讲解,精彩干货,不容错过啊!</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">前戏就这么多,高潮会很多,做好了,让我们直奔主题,发动小船,Let's go!</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><img class="__bg_gif" data-ratio="0.5643939393939394" src="/upload/b12547dc580a1dd63c08d540d3027b05.gif" data-type="gif" data-w="528" style="margin: 20px auto;box-sizing: border-box;line-height: 1.5;border-radius: 4px;display: block;overflow-wrap: break-word !important;width: 315px !important;visibility: visible !important;" title="null"></p> <h3 style="margin: 40px 10px 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;color: rgb(63, 63, 63);line-height: 1.5;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">01 Java死锁排查和解决</h3> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">要排查和解决死锁,首先思考三个问题:</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">1. 什么是死锁?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">2. 为什么会出现死锁?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">3. 怎么排查代码中出现了死锁?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">4. 如何避免写出死锁的代码?</strong></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">作为技术人员(工程师),在出现问题的时候,能够尽快的去解决这个问题。但是在学习技术知识的时候,还是脚踏实地,多问一些为什么,一个好的问题,能够让自己思考,这方面的能力也一定要锻炼锻炼哦,这样才能更好的理解和掌握知识,并探究/触碰到更深入的地方。</p> <h3 style="margin: 40px 10px 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;color: rgb(63, 63, 63);line-height: 1.5;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">1、啥是死锁?</h3> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。[百度百科:死锁]</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><img class="" data-ratio="0.8891129032258065" src="/upload/a55f916d05cad187e55e178aefa695c8.png" data-type="png" data-w="496" style="margin: 20px auto;box-sizing: border-box;line-height: 1.5;border-radius: 4px;display: block;overflow-wrap: break-word !important;width: 315px !important;visibility: visible !important;" title="null"></p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">注:进程和线程都可以发生死锁,只要满足死锁的条件!</strong></p> <h3 style="margin: 40px 10px 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;color: rgb(63, 63, 63);line-height: 1.5;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">2、为啥子会出现死锁?</h3> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">从上面的概念中我们知道</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">(1)必须是两个或者两个以上进程(线程)</p> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">(2)必须有竞争资源</p> <h3 style="margin: 40px 10px 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;color: rgb(63, 63, 63);line-height: 1.5;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">3、怎么排查代码中出现了死锁?【重点来了】</h3> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">首先整一个死锁的代码,看例子:</p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages" data-backh="945" data-backw="654" data-before-oversubscription-url="https://mmbiz.qlogo.cn/mmbiz_png/yziabN7pK2YgTnbTywosjClia4ba6T4DEx5VCViaEqZ5ITMHu9MphgF6Zmd34RJUQFUGAqSCFicOr4PicWLEv6Obmow/?wx_fmt=png" data-ratio="1.44609375" data-s="300,640" src="/upload/a336e1d8e8d4520d4c334188fa7d0914.png" data-type="png" data-w="1280" style="width: 677px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;"><span style="max-width: 100%;color: rgb(63, 63, 63);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;">上面这段代码执行后,就会出现死锁,排查的姿势有如下几种,搞起来吧!</span></p> <h3 style="margin: 40px 10px 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;color: rgb(63, 63, 63);line-height: 1.5;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;">第一个姿势:使用 jps + jstack</h3> <p style="margin: 10px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 16px;text-align: left;color: rgb(63, 63, 63);line-height: 1.6;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;overflow-wrap: break-word !important;">一</strong>:在windons命令窗口,使用<code style="padding: 3px 5px;max-width: 100%;box-sizing: border-box;color: rgb(255, 53, 2);line-height: 1.5;font-family: &quot;Operator Mono

MySQL 备份数据库脚本并且发送到另外的服务器(gzip压缩版)

作者:じ☆ve宝贝

``` #/bin/sh name=cia`date +%Y-%m-%d_%H%M%S` /usr/local/bin/mysqldump -uuserName -ppassword dbName --skip-lock-tables | gzip > /data/backup/$name.sql.gz echo `date +'%Y-%m-%d %H:%M:%S'` '备份成功' scp -P 22 /data/backup/$name.sql.gz root@10.1.87.81:/data/mysqldata/ echo `date +'%Y-%m-%d %H:%M:%S'` '发送备份服务器成功' cd /data/backup rm -rf `find . -name '*.sql.gz' -mtime 1` echo `date +'%Y-%m-%d %H:%M:%S'` '一天前的备份删除成功' ``` username mysql数据的用户名 password mysql数据的密码 dbName 将要备份的数据名称 地址根据自己安装的位置调整 scp是跨服务器拷贝 -P 22 ssh的端口22 root为目标的用户名@ip地址:目标位置

阿里P8架构师深度概述分布式架构

作者:微信小助手

<p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">简介</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">作为一名架构师,我们要专业,要能看懂代码,及时光着臂膀去机房,也能独挡一面!及时同事搞不定问题,或者撂挑子,你也能给老大一个坚定的眼神:不怕,有我在!还能在会议室上滔滔不绝,如若无人,让不懂技术的妹子看你时眼神迷离,就好想落霞与孤鹜齐飞!</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">分布式架构是一个非常复杂的体系,任何技术都不是孤立的存在,任何技术都无法适应所有场景。作为一名分布式系统架构或者资深研发人员,我们必须尽可能多的学习与之相关的各种知识,掌握各种技术的演进路线,正式从一名码农蜕变成为架构师</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">什么是分布式?</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">互联网应用的特点是:高并发,海量数据。互联网应用的用户数是没有上限的(取决于其开放特性),这也是和传统应用的本质区别。高并发指系统单位时间内收到的请求数量(取决于使用的用户数),没有上限。海量数据包括:海量数据的存储和海量数据的处理。这两个工程难题都可以使用分布式系统来解决。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">简单理解,分布式系统就是把一些计算机通过网络连接起来,然后协同工作。协同工作需要解决两个问题:</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">1)任务分解</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">把一个问题拆解成若干个独立任务,每个任务在一台节点上运行,实现多任务的并发执行。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">2)节点通信</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">节点之间互相通信,需要设计特定的通信协议来实现。协议可以采用RPC或Message Queue等方式。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.5609375" src="/upload/5d6dfe00584f8cec541b88d65850e552.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">分布式和集群的关系</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">分布式:一个业务分拆多个子业务,部署在不同的服务器上</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">集群:同一个业务,部署在多个服务器上</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">计算机发展历史</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">1946年情人节(2.14) , 世界上第一台电子数字计算机诞生在美国宾夕法尼亚大学大学,它的名字是:ENIAC; 这台计算机占地170平米、重达30吨,每秒可进行5000次加法运算。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">第一台电子计算机诞生以后,意味着一个日新月异的IT时代的到来。一方面单台计算机的性能每年都在提升:从最早的8位CPU到现在的64位CPU;从早期的MB级内存到现在的GB级别内存;从慢速的机械存储到现在的固态SSD硬盘存储。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">|</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">tips: 电子计算机的问世,最重要的奠基人是英国科学家艾兰· 图灵(Alan Turing)和美籍匈牙利科学家冯· 诺依曼(John Von· Neumann)。图灵的贡献是建立了图灵机的理论模型,奠定了人工智能的基础。而冯· 诺依曼则是首先提出了计算机体系结构的设想。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">经典理论-冯.诺依曼体系:计算机硬件由运算器、控制器、存储器、输入设备、输出设备五大部分组成。直到今天,计算机仍没有跳出该体系的范畴。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.534375" src="/upload/fa8c0c8a97da7c95c1bbc2369a8b6e08.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">ENIAC之后,电子计算机便进入了IBM主导的大型机时代,IBM大型机之父吉恩.阿姆达尔被认为是有史以来最伟大的计算机设计师之一。1964年4月7日,在阿姆达尔的带领下,历时三年,耗费50亿美元,第一台IBM大型机SYSTEM/360诞生。这使得IBM在20实际50~60年代统治整个大型计算机工业,奠定了IBM计算机帝国的江山。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">2.1 IBM大型机曾支撑美国航天登月计划</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">2.2 IBM主机一直服务于金融等核心行业的关键领域</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">由于高可靠性和超强的计算能力,几遍在X86和云计算飞速发展的情况下,IBM的大型机依然牢牢占据着一定的高端市场份额</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">20世纪80年代,在大型机霸主的时代,计算机架构同时向两个方向发展</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">以X86 CPU为架构的价格便宜的面向个人的PC</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">以RISC CPU为架构的价格昂贵的面向企业的小型UNIX服务器</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">分布式架构发展的里程碑</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">大型主机的出现。凭借着大型机超强的计算和I/O处理能力、稳定性、安全性等,在很长一段时间内,大型机引领了计算机行业及商业计算领域的发展。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">而集中式的计算机系统架构也成为了主流。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">随着计算机的发展,这种架构越来越难以适应人们的需求,比如说</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">由于大型主机的复杂性,导致培养一个能够熟练运维大型主机的人的成本很高</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">大型主机很贵,一般只有土豪(政府、金融、电信)才能用得起</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">单点问题,一台大型主机出现故障,那么整个系统将处于不可用状态。而对于大型机的使用群体来说,这种不可用导致的损失是非常大的</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">科技在进步,技术在进步。PC机性能不断提升,很多企业放弃大型机改用小型机及普通PC来搭建系统架构</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阿里巴巴在2009年发起了一项"去IOE"运动</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">当初指的是IBM小型机、Oracle数据库、EMC的高端存储</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">2009年“去IOE”战略透露,到2013年5月17日最后一台IBM小型机在支付宝下线。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">为什么要去IOE?</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">阿里巴巴过去一直采用的是Oracle数据库,并利用小型机和高端存储设备提供高性能的数据处理和存储服务。随着业务的不断发展,数据量和业务量呈爆发性增长,传统的集中式Oracle数据库架构在扩展性方面遭遇瓶颈。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">传统的商业数据库软件(Oracle,DB2),多以集中式架构为主,这些传统数据库软件的最大特点就是将所有的数据都集中在一个数据库中,依靠大型高端设备来提供高处理能力和扩展性。集中式数据库的扩展性主要采用向上扩展(Scale up)的方式,通过增加CPU,内存,磁盘等方式提高处理能力。这种集中式数据库的架构,使得数据库成为了整个系统的瓶颈,已经越来越不适应海量数据对计算能力的巨大需求</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">架构的发展演变过程</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">一个成熟的大型网站系统架构并不是一开始就设计的非常完美,也不是一开始就具备高性能、高可用、安全性等特性,而是随着用户量的增加、业务功能的扩展逐步完善演变过来的。在这个过程中,开发模式、技术架构等都会发生非常大的变化。而针对不同业务特征的系统,会有各自的侧重点,比如像淘宝这类的网站,要解决的是海量商品搜索、下单、支付等问题;像腾讯,要解决的是数亿级别用户的实时消息传输;百度所要解决的是海量数据的搜索。每一个种类的业务都有自己不同的系统架构。我们简单模拟一个架构演变过程。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">什么是大型网站</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">如何定义一个网站是不是大型网站,一般我们会从两个纬度去考衡,访问量以及数据量,二者缺一不可。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">我们以javaweb为例,来搭建一个简单的电商系统,从这个系统中来看系统的演变历史;要注意的是,接下来的演示模型,关注的是数据量、访问量提升,网站结构发生的变化, 而不是具体关注业务功能点。其次,这个过程是为了让大家更好的了解网站演进过程中的一些问题和应对策略。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">假如我们系统具备以下功能:</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">用户模块:用户注册和管理</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">商品模块:商品展示和管理</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">交易模块:创建交易及支付结算</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段一 , 单应用架构</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.8900804289544236" src="/upload/7b0a6f0d4ce1ceb8fb7a63a66afc4.other" data-type="other" data-w="373" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">网站的初期也可以认为是互联网发展的早起,我们经常会在单机上跑我们所有的程序和软件。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">把所有软件和应用都部署在一台机器上,这样就完成一个简单系统的搭建,这个时候的讲究的是效率</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段二,应用服务器和数据库服务器分离</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">随着网站的上线,访问量逐步上升,服务器的负载慢慢提高,在服务器还没有超载的时候,我们应该做好规划,提升网站的负载能力。假如代码层面的优化已经没办法继续提高,在不提高单台机器的性能,增加机器是一个比较好的方式,投入产出比非常高。这个阶段增加机器的主要目的是讲web服务器和数据库服务器拆分,这样不仅提高了单机的负载能力,也提高了容灾能力</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.6892430278884463" src="/upload/e27d90f997e27f18c21678688ed864cb.other" data-type="other" data-w="502" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段三,应用服务器集群-应用服务器负载告警,如何让应用服务器走向集群</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">随着访问量的继续增加,单台应用服务器已经无法满足需求。在假设数据库服务器还没有遇到性能问题的时候,我们可以增加应用服务器,通过应用服务器集群将用户请求分流到各个服务器中,从而继续提升负载能力。此时多台应用服务器之间没有直接的交互,他们都是依赖数据库各自对外提供服务</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.5015625" src="/upload/313b7fe0379a63cf20c0301ea30d48fd.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">架构发展到这个阶段,各种问题也会慢慢呈现</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">用户请求由谁来转发到具体的应用服务器</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">用户如果每次访问到的服务器不一样,那么如何维护session</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.834375" src="/upload/1bfa4d4b2a37a9625a0e60fbfd24497b.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段四,数据库压力变大,数据库读写分离</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">架构演变到这里,并不是终点。上面我们把应用层的性能拉上来了,但是数据库的负载也在慢慢增大,那么怎么去提高数据库层面的负载呢?有了前面的思路以后,自然会想到增加服务器。但是假如我们单纯的把数据库一分为二,然后对于后续数据库的请求,分别负载到两台数据库服务器上,那么一定会造成数据库不统一的问题。所以我们一般先考虑读写分离的方式</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.8234375" src="/upload/a4c64b68d7dc16beef83a57e21f03c56.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">这个架构的变化会带来几个问题</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">主从数据库之间的数据同步 ; 可以使用mysql自带的master-slave方式实现主从复制</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">对应数据源的选择 ; 采用第三方数据库中间件,例如mycat</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段五,使用搜索引擎缓解读库的压力</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">数据库做读库的话,尝尝对模糊查找效率不是特别好,像电商类的网站,搜索是非常核心的功能,即便是做了读写分离,这个问题也不能有效解决。那么这个时候就需要引入搜索引擎了</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">使用搜索引擎能够大大提高我们的查询速度,但是同时也会带来一些附加的问题,比如维护索引的构建。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.8" src="/upload/c28cb8c78ccb5e993daa7ba900982e7.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段六,引入缓存机制缓解数据库的压力</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">随着访问量的持续增加,逐渐出现许多用户访问统一部分内容的情况,对于这些热点数据,没必要每次都从数据库去读取,我们可以使用缓存技术,比如memcache、redis来作为我们应用层的缓存;另外在某些场景下,比如我们对用户的某些IP的访问频率做限制,那这个放内存中又不合适,放数据库又太麻烦,这个时候可以使用Nosql的方式比如mongDB来代替传统的关系型数据库</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.921875" src="/upload/fcdb8a080aa5a16d22c33ac69916baca.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段七,数据库的水平/垂直拆分</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">我们的网站演进的变化过程,交易、商品、用户的数据都还在同一个数据库中,尽管采取了增加缓存,读写分离的方式,但是随着数据库的压力持续增加,数据库的瓶颈仍然是个最大的问题。因此我们可以考虑对数据的垂直拆分和水平拆分</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">垂直拆分:把数据库中不同业务数据拆分到不同的数据库</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.7421875" src="/upload/d2ec61834d342de559a8c2f9ca363f7e.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">水平拆分:把同一个表中的数据拆分到两个甚至跟多的数据库中,水平拆分的原因是某些业务数据量已经达到了单个数据库的瓶颈,这时可以采取讲表拆分到多个数据库中</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">阶段八,应用的拆分</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">随着业务的发展,业务越来越多,应用的压力越来越大。工程规模也越来越庞大。这个时候就可以考虑讲应用拆分,按照领域模型讲我们的用户、商品、交易拆分成多个子系统</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.7390625" src="/upload/7923a618a4397e26713f7763b4a2d2c3.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">这样拆分以后,可能会有一些相同的代码,比如用户操作,在商品和交易都需要查询,所以会导致每个系统都会有用户查询访问相关操作。这些相同的操作一定是要抽象出来,否则就会是一个坑。所以通过走服务化路线的方式来解决</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.7671875" src="/upload/efabd1424e34aaf424acc5628010043.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">那么服务拆分以后,各个服务之间如何进行远程通信呢?</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">通过RPC技术,比较典型的有:webservice、hessian、http、RMI等等</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">前期通过这些技术能够很好的解决各个服务之间通信问题,but,互联网的发展是持续的,所以架构的演变和优化还在持续。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><img class="" data-ratio="0.7515625" src="/upload/2c1b27307fc94c962eb76b7ae8651451.other" data-type="other" data-w="640" style="box-sizing: inherit;border-style: none;margin: auto;max-width: 80%;"></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">总结</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">我们通过这个例子来讲解了电商网站的架构演进。我要强调一下,这个架构的演进不是某个网站真实的例子,实际上是通过这样一个演进过程给大家带来一个全局的观念和感受。以及给大家在后续课程学习过程中的一些思路。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">如何把单击扩展到分布式</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">前面我们讲到了冯.诺依曼模型,计算机一共由5个部分组成,从用户角度来看,分布式系统就像一台超级计算机。理论上也应该由输入、输出、运算、存储和控制这5部分组成。</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">输入设备的变化</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">在分布式系统架构中,输入设备可以分两类,第一类是互相连接的多个节点,在接收其他节点传来的信息作为该节点的输入;另一种就是传统意义上的人机交互的输入设备了</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">输出设备的变化</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">输出和输入类似,也有两种,一种是系统中的节点向其他节点传输信息时,该节点可以看作是输出设备;另一种就是传统意义上的人际交互的输出设备,比如用户的终端</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">控制器的变化</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">在单机中,控制器指的是CPU中的控制器,在分布式系统中,控制器主要的作用是协调或控制节点之间的动作和行为;比如硬件负载均衡器;LVS软负载;规则服务器等</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">运算器</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">在分布式系统中,运算器是由多个节点来组成的。运用多个节点的计算能力来协同完成整体的计算任务</p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: inherit;font-weight: bolder;">存储器</span></p> <p style="box-sizing: inherit;margin-top: 16px;margin-bottom: 14px;line-height: 28px;color: rgb(61, 70, 77);font-family: &quot;Pingfang SC&quot;, STHeiti, &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, SimSun, sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);">在分布式系统中,我们需要把承担存储功能的多个节点组织在一起,组成一个整体的存储器;比如数据库、redis(key-value存储)</p> <section class="_135editor" data-tools="135编辑器" data-id="85996" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"> <section style="text-align:center;"> <section style="background-color: rgb(244, 244, 244);box-sizing: border-box;padding: 40px;"> <section style="margin-bottom: 10px;"> <span style="font-size: 18px;"><span style="color: #030303;font-weight: 600;">Java高级架构&nbsp;</span><span style="color: #3f3f3f;">∣</span></span> <span style="color:#030303;" class="135brush" data-brushtype="text">干货|学习</span> </section> <section> <section style="display:inline-block;vertical-align: top;margin-top: 14px;width: 50%;text-align: right;" data-width="50%"> <img border="0" class="" data-ratio="0.993993993993994" src="/upload/b65b49bf5b4b93db5800dd70c5faae54.png" data-type="png" data-w="666" height="auto" opacity="" style="width: 120px;" title="" width="120"> </section> <section style="display:inline-block;box-sizing:border-box;padding-left: 10px;width: 50%;text-align: left;" data-width="50%"> <img class="" data-ratio="1.39" src="/upload/9d2924f9c5be1305d2d10457a2988b10.png" data-type="png" data-w="100" style="width: 100px;"> </section> </section> <section style="margin-top: 6px;"> <span style="color: #0c0c0c;" class="135brush" data-brushtype="text">长按,识别二维码,加关注</span> </section> </section> </section> </section> <section class="_135editor" data-id="image-96175" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"> <section class="_135editor" data-tools="135编辑器" data-id="92353" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"> <section data-role="paragraph" class="_135editor" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"> <section style="padding: 10px;box-sizing: border-box;"> <section style="width: 130px;height: 30px;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/YUYc62VIvE2MP5wicHSkM9BY5LJccQibMUoVpc2PPAB5d6CuxFk1eEwfwDY0pARS8CLkE7nvc4keTDo83nsp6D8Q/640?wx_fmt=png&quot;);background-size: 100%;background-repeat: no-repeat;background-position: center center;margin-left: 25px;transform: translateZ(10px);"> <section style="width: 118px;height: 30px;text-align: center;line-height: 30px;color: #fefefe;letter-spacing: 3px;"> <p class="135brush" data-brushtype="text"><strong>温馨提示</strong></p> </section> </section> <section style="box-shadow: rgb(204, 204, 204) 0px 0px 7px;border-radius: 15px;color: rgb(51, 51, 51);padding: 15px;margin-top: -20px;box-sizing: border-box;"> <section style="line-height: 25px;margin-top: 15px;font-size: 14px;" class="135brush"> <p>如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。关注本文说说你的看法吧,下方评论</p> </section> </section> </section> </section> </section> </section> <p></p>

Java设计模式(转)——10.桥接模式

作者:じ☆ve宝贝

## 10.桥接模式(Bridge) 桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。我们来看看关系图: ![桥接设计模式](/upload/content18.png "桥接设计模式") 实现代码: 先定义接口: ``` public interface Sourceable { public void method(); } ``` 分别定义两个实现类: ``` public class SourceSub1 implements Sourceable { @Override public void method() { System.out.println("this is the first sub!"); } } ``` ``` public class SourceSub2 implements Sourceable { @Override public void method() { System.out.println("this is the second sub!"); } } ``` 定义一个桥,持有Sourceable的一个实例: ``` public abstract class Bridge { private Sourceable source; public void method(){ source.method(); } public Sourceable getSource() { return source; } public void setSource(Sourceable source) { this.source = source; } } ``` ``` public class MyBridge extends Bridge { public void method(){ getSource().method(); } } ``` 测试类: ``` public class BridgeTest { public static void main(String[] args) { Bridge bridge = new MyBridge(); /*调用第一个对象*/ Sourceable source1 = new SourceSub1(); bridge.setSource(source1); bridge.method(); /*调用第二个对象*/ Sourceable source2 = new SourceSub2(); bridge.setSource(source2); bridge.method(); } } ``` 输出: this is the first sub! this is the second sub! 这样,就通过对Bridge类的调用,实现了对接口Sourceable的实现类SourceSub1和SourceSub2的调用。接下来我再画个图,大家就应该明白了,因为这个图是我们JDBC连接的原理,有数据库学习基础的,一结合就都懂了。 ![桥接设计模式](/upload/content19.png "桥接设计模式")

Caused by: java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11.XToolkit

作者:じ☆ve宝贝

**解决方案:** > 在Tomcat/bin/catalina.sh 中增加-Djava.awt.headless=true ![](/upload/b7e7d69853f44297b439165c1acd9453.png) **JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"**

Java解析yml工具类YmlUtil.java

作者:じ☆ve宝贝

##### Java解析yml的工具类,递归调用并返回Map ``` package cn.studyjava.canal.common.util; import java.io.FileInputStream; import java.net.URL; import java.util.Iterator; import java.util.Map; import org.apache.logging.log4j.core.config.plugins.util.ResolverUtil.Test; import org.yaml.snakeyaml.Yaml; import com.google.common.collect.Maps; /** * @author zsljava 2017年12月13日 下午2:16:49 * @since 1.0.0 */ public class YmlUtil { private static Map<String, Object> ymlMap = null; static{ ymlMap = Maps.newConcurrentMap(); getApplicationYml(); } /** * */ public YmlUtil(){ super(); } @SuppressWarnings("unchecked") private static Map<String, Object> getApplicationYml(){ try { Yaml yaml = new Yaml(); URL url = ClassLoader.getSystemResource("application.yml"); if (url != null) { Map<String, Object> map = yaml.loadAs(new FileInputStream(url.getFile()), Map.class); switchToMap(null, map); } } catch (Exception e) { e.printStackTrace(); } return ymlMap; } @SuppressWarnings("unchecked") private static void switchToMap(String myKey,Map<String, Object> map){ Iterator<String> it = map.keySet().iterator(); myKey = myKey == null ? "" : myKey; String tmpkey = myKey; while(it.hasNext()){ String key = it.next(); myKey = tmpkey +key; Object value = map.get(key); if(value instanceof Map){ switchToMap(myKey.concat("."), (Map<String, Object>)value); }else{ if(null != value){ ymlMap.put(myKey, value); } // System.out.println(myKey+"->"+map.get(key)); } } } @SuppressWarnings("unchecked") public static <T> T get(String key){ return (T) ymlMap.get(key); } public static String getStr(String key){ return String.valueOf(ymlMap.get(key)); } } ```

不在线,好友发给我的微信消息,会不会丢?

作者:微信小助手

<p><span style="font-size: 14px;letter-spacing: 1px;">不管是<strong>MQ</strong>(Msg Queue)的消息投递,还是<strong>单人实时聊天</strong>的消息投递,都需要<span style="font-size: 14px;letter-spacing: 1px;">通过</span>应用层的超时、重传、确认、去重来保证消息的可靠投递。</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">但是,如果没有打开手机,没有登录微信,好友发给我的微信消息,有没有可能丢失呢?这是今天和大家分享的话题。<br></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:初步一想,离线消息存库不就好了么?往后看,会比你想象的更复杂。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><strong><span style="font-size: 14px;letter-spacing: 1px;">接收方不在线,消息发送流程是怎么样的?</span></strong></p> <p><img data-ratio="0.5081521739130435" data-s="300,640" src="/upload/c9039fcdbca1b4e77434f40dcef9c16f.png" data-type="png" data-w="368"><br><span style="font-size: 14px;letter-spacing: 1px;">如上图所述,A给B发了一条消息,而B不在线,</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">离线消息存储</span><span style="font-size: 14px;letter-spacing: 1px;">的流程如下:</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:在服务端会存储B的状态为offline。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(1) 用户A发送消息给用户B,通过server中转;</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:你猜,有没有可能不通过server中转,而AB直连呢?</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(2) server查看用户B的状态为offline;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(3) server将消息存储到DB中;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(4) server返回用户A发送成功;</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:没毛病,对于发送方而言,消息落地DB就认为发送成功。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><strong><span style="font-size: 14px;letter-spacing: 1px;">离线消息表如何设计?</span></strong></p> <p><span style="font-size: 14px;letter-spacing: 1px;">很容易想到,消息业务有这样的一些</span><strong style="font-size: 14px;letter-spacing: 1px;">关键属性</strong><span style="font-size: 14px;letter-spacing: 1px;">:</span></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">t_offline_msg(</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">receiver_uid,&nbsp; // 离线消息接收方</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">msg_id,&nbsp; // 消息ID</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">time,&nbsp; // 消息发送时间</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">sender_uid, // 消息发送方</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">msg_type, // 消息类型</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">msg_content, // 消息内容&nbsp;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">…</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">);</span></em></p> <p><span style="font-size: 14px;letter-spacing: 1px;">根据业务模式设计表结构。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:下半句是,根据访问模式设计索引结构。</span></em></span></p> <p style="white-space: normal;"><strong><span style="font-size: 14px;letter-spacing: 1px;"><br></span></strong></p> <p style="white-space: normal;"><strong><span style="font-size: 14px;letter-spacing: 1px;">那么,离线消息的拉取过程如何呢?</span></strong></p> <p><br></p> <p><span style="font-size: 14px;letter-spacing: 1px;">B要拉取A给ta发送的离线消息,只需在</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(receiver_uid(B), sender_uid(A))</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">上查询,然后把离线消息删除,再把消息返回B即可。</span><br></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:根据这个访问模式,要建立一个联合索引。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><img data-ratio="0.47368421052631576" data-s="300,640" src="/upload/3bebb92e9082289baa3bad911d31106d.png" data-type="png" data-w="399"><br><span style="font-size: 14px;letter-spacing: 1px;">整体流程如上图所述:</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(1) 用户B拉取用户A发送给ta的离线消息;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(2) server从DB中拉取离线消息;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(3) server从DB中把离线消息删除;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(4) server返回给用户B想要的离线消息;</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:没毛病,这个过程也不难想到。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">BUT,用户B登录微信的时候,其实不止要拉取A发给他的离线消息,还需要拉取</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">所有其他好友</span><span style="font-size: 14px;letter-spacing: 1px;">发给他的离线消息呀!</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">OK!如果用户B有很多好友,登陆时客户端需要对<strong>所有好友</strong>进行离线消息拉取。</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">客户端伪代码:</span></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">get B's friend-list;&nbsp; // 拉取B的好友列表</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">for(all uid in B's friend-list){&nbsp; &nbsp; // 遍历所有好友uid</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get_offline_msg(B,uid); &nbsp; // 拉取离线消息</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">}</span></em></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">我去,如果有1000个好友,难道要拉取1000次?</span><strong><span style="font-size: 14px;letter-spacing: 1px;">有没有减少拉取次数的优化方法呢?</span></strong></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:我的微信好友已满员,大家猜微信好友上限是多少?</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">先拉取各个好友的离线消息数量,真正查看离线消息时,才往服务器发送拉取请求,即<strong>按需拉取</strong>。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:手机端为了节省流量,经常会使用这个按需拉取的优化。</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;"><br></span></em></span></p> <p><span style="color: rgb(0, 0, 0);font-size: 14px;letter-spacing: 1px;">除了减少流量的“按需拉取”优化,还有<strong>减少拉取次数的优化方案么?</strong></span></p> <p><img data-ratio="0.46593406593406594" data-s="300,640" src="/upload/e9bdca49661b54425908c8259445b795.png" data-type="png" data-w="455"><br><span style="font-size: 18px;"><strong><span style="letter-spacing: 1px;">当当当当!!!!</span></strong></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">可以一次性通过receiver_uid即接收方ID,拉取所有好友发送给用户B的离线消息,把<span style="font-size: 14px;letter-spacing: 1px;">登录时与服务器的交互次数降低为了1次。</span></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:这样的话,离校消息表的访问模式就变为,只需要按照receiver_uid来查询了。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">到客户端本地再根据sender_uid进行计算。</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">问题又来了,用户B一次性拉取所有好友发给ta的离线消息,消息量很大时,<strong>一个请求包很大,速度慢怎么办?</strong></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">老板,怎么这么难伺候呢?</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);font-size: 14px;letter-spacing: 1px;">请求次数多,你说瓶颈是网络,慢!</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);font-size: 14px;letter-spacing: 1px;">1次请求,你说<em style="color: rgb(0, 82, 255);white-space: normal;"><span style="font-size: 14px;letter-spacing: 1px;">报文大,</span></em>瓶颈是带宽,又说慢!</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);font-size: 14px;letter-spacing: 1px;">到底要闹哪样?</span></em></span></p> <p><img data-ratio="0.474025974025974" data-s="300,640" src="/upload/2c0f43672fd3fba497fb8e44ee5f32e3.png" data-type="png" data-w="462"><br><strong><span style="font-size: 14px;letter-spacing: 1px;">分页拉取</span></strong><span style="font-size: 14px;letter-spacing: 1px;">,是一种常见的优化方案。根据业务需求,先拉取最新的一页消息,再按需一页页拉取。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:这是一个包大小与拉取次数的折衷。</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);font-size: 14px;letter-spacing: 1px;">任何设计方案都是折衷。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">新的问题,<strong>离线消息会不会丢失,用户会不会收不到呢?</strong></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">例如,上述步骤第三步执行完毕之后(删除了离线消息),第四个步骤离线消息返回给客户端过程中,服务器挂掉,路由器丢消息,或者客户端crash了,那离线消息岂不是丢了么。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:数据库已删除,用户却还没看到。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><strong><span style="font-size: 14px;letter-spacing: 1px;">如何保证离线消息的可达性?</span></strong></p> <p><img data-ratio="0.788235294117647" data-s="300,640" src="/upload/99e2be5f69d0e02de00e8466614af024.png" data-type="png" data-w="255"><br><span style="font-size: 14px;letter-spacing: 1px;">如同在线消息的应用层ACK机制一样,离线消息拉时,不能够直接删除数据库中的离线消息,而</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">必须等应用层的离线消息ACK</span><span style="font-size: 14px;letter-spacing: 1px;">,等客户端真的收到离线消息,</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">才能删除数据库中的离线消息</span><span style="font-size: 14px;letter-spacing: 1px;">。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:ACK机制,是消息可靠性传递的常见玩法,不管是在线消息,还是离线消息。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">新的问题又出现了!</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:刨根问底,才是严谨的治学态度。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">如果用户B拉取了一页离线消息,</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">却在ACK之前crash了</span><span style="font-size: 14px;letter-spacing: 1px;">,下次<strong>登录时会拉取到重复的离线消息么?</strong></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">拉取了离线消息却没有ACK,服务器不会删除之前的离线消息,故</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">下次登录时系统层面还会拉取到</span><span style="font-size: 14px;letter-spacing: 1px;">。但在业务层面,可以根据msg_id去重,让用户无感知。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:SMC理论,系统层面无法做到消息不丢不重,业务层面可以做到对用户无感知。</span></em></span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><img data-ratio="0.7566666666666667" data-s="300,640" src="/upload/c6448fd12c41928479cc3601db105782.png" data-type="png" data-w="300"><br><span style="font-size: 14px;letter-spacing: 1px;">另一个问题,假设有N页离线消息,现在每个离线消息需要一个ACK,那么岂不是<strong>客户端与服务器的交互次数又加倍了?</strong>有没有优化空间?</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:优化是无止境的。</span></em></span></p> <p><img data-ratio="0.7525773195876289" data-s="300,640" src="/upload/f268129118e802d76ad90109afdb37dd.png" data-type="png" data-w="291"><br><span style="font-size: 14px;letter-spacing: 1px;">其实,不用每一页消息都ACK,</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">在拉取第二页消息时相当于第一页消息的ACK</span><span style="font-size: 14px;letter-spacing: 1px;">,此时服务器再删除第一页的离线消息即可,最后一页消息再ACK一次。这样的效果是,不管拉取多少页离线消息,<strong>只会多一个ACK请求,与服务器多一次交互</strong>。</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">&nbsp;</span></p> <p><strong><span style="font-size: 14px;letter-spacing: 1px;">总结</span></strong></p> <p><span style="font-size: 14px;letter-spacing: 1px;">“离线消息”的玩法,可能比大家想象的要复杂,常见的优化有:</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(1) 对于同一个用户B,</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">一次性拉取所有用户发给ta的离线消息</span><span style="font-size: 14px;letter-spacing: 1px;">,再在客户端本地进行发送方分析,相比按照发送方一个个进行消息拉取,能大大减少服务器交互次数;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(2) </span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">按需拉取</span><span style="font-size: 14px;letter-spacing: 1px;">,是无线端的常见优化;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(3)&nbsp;</span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">分页拉取</span><span style="font-size: 14px;letter-spacing: 1px;">,是一个请求次数与包大小的折衷;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(4) </span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">应用层的ACK</span><span style="font-size: 14px;letter-spacing: 1px;">,应用层的去重,才能保证离线消息的不丢不重;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;">(5) </span><span style="font-size: 14px;letter-spacing: 1px;color: rgb(255, 76, 0);">下一页的拉取,同时作为上一页的ACK</span><span style="font-size: 14px;letter-spacing: 1px;">,能够极大减少与服务器的交互次数;</span></p> <p><span style="font-size: 14px;letter-spacing: 1px;"><br></span></p> <p><strong><span style="font-size: 14px;letter-spacing: 1px;">思路比结论更重要</span></strong><span style="font-size: 14px;letter-spacing: 1px;">,希望大家有收获。</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-align: center;line-height: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><img width="auto" data-ratio="1" data-type="jpeg" data-w="250" data-s="300,640" class="" src="/upload/7ddc9700032e2c5cee163f1f1a37b46c.jpg" style="max-width: 677px;box-sizing: border-box;word-wrap: break-word;visibility: visible !important;width: 130px !important;"></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;text-align: center;line-height: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 12px;">架构师之路-分享</span><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 12px;color: rgb(255, 76, 0);">可落地</span><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 12px;">的技术文章</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;"></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 14px;">相关推荐:</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 14px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651961906&amp;idx=1&amp;sn=675720762919cd8220f2a819ea72164f&amp;chksm=bd2d0fee8a5a86f8dccccd1760a931cda562a25eddfc3c5c2ad3b5d95c8919dac989ed0ab07e&amp;scene=21#wechat_redirect" target="_blank" data-linktype="2">rm -rf * &nbsp;了咋办,跑路吗?</a>》</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 14px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651961840&amp;idx=1&amp;sn=d3f2600d0c01b926285c244e54be55f0&amp;chksm=bd2d0c2c8a5a853a3bb8465a75878c9c3e25705fd8e1b9a33f60ca621b1bdb012a9609b6f5a8&amp;scene=21#wechat_redirect" target="_blank" data-linktype="2">磁盘满了,为啥du却显示还有很大空间?</a>》</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;letter-spacing: 1px;font-size: 14px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651961108&amp;idx=1&amp;sn=3fccc94c4307fa2306bae680d8570c18&amp;chksm=bd2d02c88a5a8bde8944e383a3fb9b6d24461cf07ed5a65dbf774a2382bf1f318aca18df5572&amp;scene=21#wechat_redirect" target="_blank" data-linktype="2">一分钟了解nohup和&amp;的功效</a>》</span></p> <p style="max-width: 677px;box-sizing: border-box;word-wrap: break-word;min-height: 17px;font-variant-numeric: normal;font-variant-east-asian: normal;white-space: normal;letter-spacing: 0.54px;background-color: rgb(255, 255, 255);"><br></p> <p style="max-width: 677px;box-sizing: border-box;word-wrap: break-word;min-height: 17px;font-variant-numeric: normal;font-variant-east-asian: normal;white-space: normal;letter-spacing: 0.54px;background-color: rgb(255, 255, 255);"><span style="font-size: 14px;letter-spacing: 1px;">你丢过离线消息么?</span></p> <p style="max-width: 677px;box-sizing: border-box;word-wrap: break-word;min-height: 17px;font-variant-numeric: normal;font-variant-east-asian: normal;white-space: normal;letter-spacing: 0.54px;background-color: rgb(255, 255, 255);"><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 14px;letter-spacing: 1px;">画外音:“好看”是一种习惯,谢谢。</span></em></span></p>

同一个SQL语句,为啥性能差异咋就这么大呢?(1分钟系列)

作者:微信小助手

<p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651962495&amp;idx=1&amp;sn=74e9e0dc9d03a872fd5bce5769f6c22a&amp;chksm=bd2d09a38a5a80b50da3b67c03da8417426cbb201427557959fa91e9094a848a14e0db214370&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">数据库允许空值,往往是悲剧的开始</a>》一文通过explain来分析SQL的执行计划,来分析null对索引命中情况的影响,有不少朋友留言,问<strong>explain结果中的type字段</strong>,ref,ALL等不一样的值究竟是什么含义。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">今天花1分钟简单说下,常见的type结果及代表的含义,并且通过同一个SQL语句的性能差异,说明建对索引多么重要。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">explain结果中的type字段代表什么意思?</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.13345864661654136" data-s="300,640" src="/upload/ff779532ca68c6b120bd17ee66d737a0.png" data-type="png" data-w="1064" style=""></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">MySQL的官网解释非常简洁,只用了3个单词:</span><strong><span style="font-size: 15px;letter-spacing: 1px;">连接类型</span></strong><span style="letter-spacing: 1px;font-size: 12px;">(the join type)</span><span style="font-size: 15px;letter-spacing: 1px;">。它描述了找到所需数据使用的</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">扫描方式</span><span style="font-size: 15px;letter-spacing: 1px;">。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">最为常见</span><span style="font-size: 15px;letter-spacing: 1px;">的扫描方式有:</span></p> <ul style="list-style-type: disc;" class=" list-paddingleft-2"> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">system</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:系统表,少量数据,往往不需要进行磁盘IO;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">const</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:常量连接;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">eq_ref</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:主键索引</span><span style="letter-spacing: 1px;font-size: 12px;">(primary key)</span><span style="font-size: 15px;letter-spacing: 1px;">或者非空唯一索引</span><span style="letter-spacing: 1px;font-size: 12px;">(unique not null)</span><span style="font-size: 15px;letter-spacing: 1px;">等值扫描;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">ref</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:非主键非唯一索引等值扫描;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">range</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:范围扫描;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">index</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:索引树扫描;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">ALL</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:全表扫描</span><span style="letter-spacing: 1px;font-size: 12px;">(full table scan)</span><span style="font-size: 15px;letter-spacing: 1px;">;</span></p></li> </ul> <p style="line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 15px;letter-spacing: 1px;">画外音:</span></em><em><span style="font-size: 15px;letter-spacing: 1px;"></span></em><em><span style="font-size: 15px;letter-spacing: 1px;">这些是最常见的,大家去explain自己工作中的SQL语句,95%都是上面这些类型。</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">上面各类扫描方式<strong>由快到慢</strong>:</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">system &gt; const &gt; eq_ref &gt; ref &gt; range &gt; index &gt; ALL</span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">下面一一举例说明。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">一、system</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.17326732673267325" data-s="300,640" src="/upload/2f0f01636a1415e7b7f82030e5087acf.png" data-type="png" data-w="808" style=""></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">explain select * from mysql.time_zone;</span></em><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">上例中,从系统库mysql的</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">系统表</span><span style="font-size: 15px;letter-spacing: 1px;">time_zone里查询数据,扫码类型为system,这些数据已经加载到内存里,不需要进行磁盘IO。<br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;"><br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">这类扫描是速度最快的。<br></span></p> <p style="line-height: 1.75em;"><br><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.1335914811229429" data-s="300,640" src="/upload/ae77aa620762a8396449d61d6e3c83b8.png" data-type="png" data-w="1033" style=""></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">explain select * from (select * from user where id=1) tmp;</span></em><span style="letter-spacing: 1px;font-size: 12px;"></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">再举一个例子,内层嵌套</span><span style="letter-spacing: 1px;font-size: 12px;">(const</span><span style="font-size: 15px;letter-spacing: 1px;">)返回了一个临时表,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">外层嵌套从临时表查询</span><span style="font-size: 15px;letter-spacing: 1px;">,其扫描类型也是system,也不需要走磁盘IO,速度超快。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">二、const</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">数据准备:</span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">create table user (</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">id int </span></em></span><span style="font-size: 12px;color: rgb(255, 76, 0);"><em><span style="font-size: 12px;letter-spacing: 1px;">primary key</span></em></span><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">,</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">name varchar(20)</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">)engine=innodb;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">&nbsp;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user values(1,'shenjian');</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user values(2,'zhangsan');</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user values(3,'lisi');</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.12916666666666668" data-s="300,640" src="/upload/d5f49fae06ccd0de3f5f5a7810dcb7dc.png" data-type="png" data-w="960" style=""></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">const扫描的条件为:</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(1)命中</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">主键</span><span style="letter-spacing: 1px;font-size: 12px;">(primary key)</span><span style="font-size: 15px;letter-spacing: 1px;">或者</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">唯一</span><span style="letter-spacing: 1px;font-size: 12px;">(unique)</span><span style="font-size: 15px;letter-spacing: 1px;">索引;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(2)被连接的部分是一个</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">常量</span><span style="letter-spacing: 1px;font-size: 12px;">(const)</span><span style="font-size: 15px;letter-spacing: 1px;">值;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">explain select * from user where id=1;</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">如上例,id是PK,连接部分是常量1。<br></span></p> <p style="line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 15px;letter-spacing: 1px;">画外音:别搞什么类型转换的幺蛾子。</span></em></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">这类扫描效率极高,返回数据量少,速度非常快。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">三、eq_ref</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">数据准备:</span></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">create table user (</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">id int </span></em><span style="color: rgb(255, 76, 0);"><em><span style="letter-spacing: 1px;font-size: 12px;">primary key</span></em></span><em><span style="letter-spacing: 1px;font-size: 12px;">,</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">name varchar(20)</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">)engine=innodb;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(1,'shenjian');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(2,'zhangsan');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(3,'lisi');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">create table user_ex (</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">id int </span></em><span style="color: rgb(255, 76, 0);"><em><span style="letter-spacing: 1px;font-size: 12px;">primary key</span></em></span><em><span style="letter-spacing: 1px;font-size: 12px;">,</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">age int</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">)engine=innodb;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(1,18);</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(2,20);</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(3,30);</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(4,40);</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(5,50);</span></em><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.13345864661654136" data-s="300,640" src="/upload/ff779532ca68c6b120bd17ee66d737a0.png" data-type="png" data-w="1064" style=""></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">eq_ref扫描的条件为,</span><span style="color: rgb(255, 76, 0);"><span style="font-size: 15px;letter-spacing: 1px;">对于前表的每一行</span><span style="letter-spacing: 1px;font-size: 12px;">(row)</span><span style="font-size: 15px;letter-spacing: 1px;">,后表只有一行被扫描</span></span><span style="font-size: 15px;letter-spacing: 1px;">。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">再细化一点:</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(1)</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">join</span><span style="font-size: 15px;letter-spacing: 1px;">查询;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(2)命中</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">主键</span><span style="letter-spacing: 1px;font-size: 12px;">(primary key)</span><span style="font-size: 15px;letter-spacing: 1px;">或者</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">非空唯一</span><span style="letter-spacing: 1px;font-size: 12px;">(unique not null)</span><span style="font-size: 15px;letter-spacing: 1px;"><span style="font-size: 15px;letter-spacing: 1px;">索引</span>;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(3)</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">等值</span><span style="font-size: 15px;letter-spacing: 1px;">连接;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">explain select * from user,user_ex where user.id=user_ex.id;</span></em><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">如上例,id是主键,该join查询为eq_ref扫描。<br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;"><br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;"> <mpchecktext> <br> </mpchecktext></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;"> <mpchecktext> <br> </mpchecktext></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">这类扫描的速度也异常之快。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">四、ref</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">数据准备:</span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">create table user (</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">id int,</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">name varchar(20) ,</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;color: rgb(255, 76, 0);"><em><span style="font-size: 12px;letter-spacing: 1px;">index(id)</span></em></span><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;"></span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">)engine=innodb;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">&nbsp;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user values(1,'shenjian');</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user values(2,'zhangsan');</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user values(3,'lisi');</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">&nbsp;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">create table user_ex (</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">id int,</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">age int,</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;color: rgb(255, 76, 0);"><em><span style="font-size: 12px;letter-spacing: 1px;">index(id)</span></em></span><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;"></span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">)engine=innodb;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">&nbsp;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user_ex values(1,18);</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user_ex values(2,20);</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user_ex values(3,30);</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user_ex values(4,40);</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">insert into user_ex values(5,50);</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.1275797373358349" data-s="300,640" src="/upload/ad7f12a807c45c52609e8ef690249c9b.png" data-type="png" data-w="1066" style=""></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">如果把上例eq_ref案例中的主键索引,改为</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">普通非唯一</span><span style="letter-spacing: 1px;font-size: 12px;">(non unique)</span><span style="font-size: 15px;letter-spacing: 1px;">索引。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">explain select * from user,user_ex where user.id=user_ex.id;</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">就由eq_ref降级为了ref,此时</span><span style="color: rgb(255, 76, 0);"><span style="font-size: 15px;letter-spacing: 1px;">对于前表的每一行</span><span style="letter-spacing: 1px;font-size: 12px;">(row)</span><span style="font-size: 15px;letter-spacing: 1px;">,后表可能有多于一行的数据被扫描</span></span><span style="font-size: 15px;letter-spacing: 1px;">。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.1294885745375408" data-s="300,640" src="/upload/3703537a838da649fa7274a35f08ef98.png" data-type="png" data-w="919" style=""></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">explain select * from user where id=1;</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">当id改为普通非唯一索引后,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">常量的连接查询,也由const降级为了ref</span><span style="font-size: 15px;letter-spacing: 1px;">,因为也可能有多于一行的数据被扫描。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">ref扫描,可能出现在join里,也可能出现在单表普通索引里,每一次匹配可能有多行数据返回,虽然它比eq_ref要慢,但它仍然是一个很快的join类型。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">五、range</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">数据准备:</span></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">create table user (</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">id int </span></em><span style="color: rgb(255, 76, 0);"><em><span style="letter-spacing: 1px;font-size: 12px;">primary key</span></em></span><em><span style="letter-spacing: 1px;font-size: 12px;">,</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">name varchar(20)</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">)engine=innodb;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(1,'shenjian');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(2,'zhangsan');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(3,'lisi');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(4,'wangwu');</span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(5,'zhaoliu');</span></em><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.37462834489593655" data-s="300,640" src="/upload/7d6553ba1e338007ebb0a8fc2e047575.png" data-type="png" data-w="1009" style=""></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">range扫描就比较好理解了,它是索引上的范围查询,它会在索引上扫码特定范围内的值。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">explain select * from user where id between 1 and 4;</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">explain select * from user where idin(1,2,3);</span></em></span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="font-size: 12px;letter-spacing: 1px;">explain select * from user where id&gt;3;</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">像上例中的between,in,&gt;都是典型的范围</span><span style="letter-spacing: 1px;font-size: 12px;">(range)</span><span style="font-size: 15px;letter-spacing: 1px;">查询。</span></p> <p style="line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 15px;letter-spacing: 1px;">画外音:必须是索引,否则不能批量"跳过"。</span></em></span><em><span style="font-size: 15px;letter-spacing: 1px;"></span></em></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">六、index</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.11932938856015779" data-s="300,640" src="/upload/e7400133e55ee0f9736d871cacdb774e.png" data-type="png" data-w="1014" style=""></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">index类型,需要扫描</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">索引</span><span style="font-size: 15px;letter-spacing: 1px;">上的</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">全部数据</span><span style="font-size: 15px;letter-spacing: 1px;">。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">explain count (*) from user;</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">如上例,id是主键,该count查询需要通过扫描索引上的全部数据来计数。</span></p> <p style="line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><em><span style="font-size: 15px;letter-spacing: 1px;">画外音:此表为InnoDB引擎。</span></em></span><em><span style="font-size: 15px;letter-spacing: 1px;"></span></em></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">它仅比全表扫描快一点。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">七、ALL</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">数据准备:</span></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">create table user (</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">id int,</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">name varchar(20)</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">)engine=innodb;</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(1,'shenjian');</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(2,'zhangsan');</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user values(3,'lisi');</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">create table user_ex (</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">id int,</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">age int</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">)engine=innodb;</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">&nbsp;</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(1,18);</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(2,20);</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(3,30);</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(4,40);</span><span style="letter-spacing: 1px;font-size: 12px;"></span></em></p> <p style="line-height: normal;"><em><span style="letter-spacing: 1px;font-size: 12px;">insert into user_ex values(5,50);</span></em><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.0953125" data-s="300,640" src="/upload/f3e059148be1d5d54c976aa22a4dc02f.png" data-type="png" data-w="1280" style=""></p> <p style="line-height: normal;"><span style="font-size: 12px;"><em><span style="letter-spacing: 1px;">explain select * from user,user_ex where user.id=user_ex.id;</span></em></span><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">如果id上不建索引,</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">对于前表的每一行(row),后表都要被全表扫描</span><span style="font-size: 15px;letter-spacing: 1px;">。<br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;"><br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">今天这篇文章中,这个相同的join语句出现了三次:</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(1)扫描类型为eq_ref,此时id为主键;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(2)扫描类型为ref,此时id为非唯一普通索引;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(3)扫描类型为ALL,全表扫描,此时id上无索引;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">有此可见,建立正确的索引,对数据库性能的提升是多么重要。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">另外,《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651962477&amp;idx=1&amp;sn=3a7617781a095243953fed8f236abab3&amp;chksm=bd2d09b18a5a80a756784da67c636e518ca006c16a0ff4e7165de5fa01b82454403dc7c6d83b&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">类型转换带来的大坑</a>》中,也提到不正确的SQL语句,可能导致全表扫描。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">全表扫描代价极大,性能很低,是应当极力避免的,通过explain分析SQL语句,非常有必要。</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">总结</span></strong><span style="font-size: 15px;letter-spacing: 1px;"></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(1)explain结果中的<strong>type字段</strong>,表示</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">(广义)连接类型</span><span style="font-size: 15px;letter-spacing: 1px;">,它描述了找到所需数据使用的扫描方式;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(2)常见的扫描类型有:</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">system&gt;const&gt;eq_ref&gt;ref&gt;range&gt;index&gt;ALL</span><span style="font-size: 15px;letter-spacing: 1px;"><br></span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">其扫描速度由快到慢;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(3)各类扫描类型的要点是:</span></p> <ul style="list-style-type: disc;" class=" list-paddingleft-2"> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">system</span></strong><span style="font-size: 15px;letter-spacing: 1px;">最快:不进行磁盘IO</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">const</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:PK或者unique上的等值查询</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">eq_ref</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:PK或者unique上的join查询,等值匹配,对于前表的每一行</span><span style="letter-spacing: 1px;font-size: 12px;">(row)</span><span style="font-size: 15px;letter-spacing: 1px;">,后表只有一行命中</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">ref</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:非唯一索引,等值匹配,可能有多行命中</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">range</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:索引上的范围扫描,例如:between/in/&gt;</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">index</span></strong><span style="font-size: 15px;letter-spacing: 1px;">:索引上的全集扫描,例如:InnoDB的count</span></p></li> <li><p style="line-height: 1.75em;"><strong><span style="font-size: 15px;letter-spacing: 1px;">ALL</span></strong><span style="font-size: 15px;letter-spacing: 1px;">最慢:全表扫描</span><span style="letter-spacing: 1px;font-size: 12px;">(full table scan)</span><span style="font-size: 15px;letter-spacing: 1px;"></span></p></li> </ul> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(4)</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">建立正确的索引</span><span style="letter-spacing: 1px;font-size: 12px;">(index)</span><span style="font-size: 15px;letter-spacing: 1px;">,非常重要;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">(5)</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(255, 76, 0);">使用explain</span><span style="font-size: 15px;letter-spacing: 1px;">了解并优化执行计划,非常重要;</span></p> <p style="line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;">&nbsp;</span></p> <p style="line-height: 1.75em;"><span style="color: rgb(255, 76, 0);"><strong><span style="font-size: 15px;letter-spacing: 1px;">思路</span></strong></span><span style="font-size: 15px;letter-spacing: 1px;">比结论重要,希望大家有收获。<br></span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-variant-numeric: normal;font-variant-east-asian: normal;white-space: normal;line-height: 1.75em;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(0, 82, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 1px;font-size: 15px;box-sizing: border-box !important;word-wrap: break-word !important;">画外音:本文测试于MySQL5.6。</span></em></span><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;line-height: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;"><strong style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;"><img data-ratio="1" data-w="250" data-s="300,640" data-type="jpeg" class="" style="max-width: 677px;box-sizing: border-box;overflow-wrap: break-word;visibility: visible !important;width: 130px !important;height: auto !important;" src="/upload/7ddc9700032e2c5cee163f1f1a37b46c.jpg" width="auto"></strong></span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;line-height: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 12px;letter-spacing: 1px;"><strong style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;"><strong style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;">架构师之路</strong>-分享技术思路</strong></span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;">相关推荐:</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651962450&amp;idx=1&amp;sn=ce17c4da8d20ce275f75d0f2ef5e40c9&amp;chksm=bd2d098e8a5a809834aaa07da0d7546555385543fb6d687a7cf94d183ab061cd301a76547411&amp;scene=21#wechat_redirect" target="_blank" data-linktype="2" data-itemshowtype="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box;word-wrap: break-word;">缓冲池(buffer pool),这次彻底懂了!!!</a>》</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651962467&amp;idx=1&amp;sn=899ea157b0fc6f849ec80a4d055a309b&amp;chksm=bd2d09bf8a5a80a972a2e16a190ed7dffe03f89015ead707bdfcc5aeb8388fb278f397c125f1&amp;scene=21#wechat_redirect" target="_blank" data-linktype="2" data-itemshowtype="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">写缓冲(change buffer),这次彻底懂了!!!</a>》</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651962477&amp;idx=1&amp;sn=3a7617781a095243953fed8f236abab3&amp;chksm=bd2d09b18a5a80a756784da67c636e518ca006c16a0ff4e7165de5fa01b82454403dc7c6d83b&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">两类非常隐蔽的全表扫描 | 1分钟系列</a>》</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;letter-spacing: 1px;background-color: rgb(255, 255, 255);">《</span><a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651961494&amp;idx=1&amp;sn=34f1874c1e36c2bc8ab9f74af6546ec5&amp;chksm=bd2d0d4a8a5a845c566006efce0831e610604a43279aab03e0a6dde9422b63944e908fcc6c05&amp;scene=21#wechat_redirect" target="_blank" data-linktype="2" data-itemshowtype="0" style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;letter-spacing: 1px;white-space: normal;background-color: rgb(255, 255, 255);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box;word-wrap: break-word;">MyISAM与InnoDB的索引差异 | 1分钟系列</a><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;letter-spacing: 1px;background-color: rgb(255, 255, 255);">》<br></span></span></p> <p style="line-height: 1.75em;"><span style="max-width: 100%;box-sizing: border-box;word-wrap: break-word;font-size: 15px;letter-spacing: 1px;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;letter-spacing: 1px;background-color: rgb(255, 255, 255);">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=2651962495&amp;idx=1&amp;sn=74e9e0dc9d03a872fd5bce5769f6c22a&amp;chksm=bd2d09a38a5a80b50da3b67c03da8417426cbb201427557959fa91e9094a848a14e0db214370&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">数据库允许null,悲剧的开始 | 1分钟系列</a>》</span></span><br></p>

完美解决 : Java 微信语音 amr 格式转 mp3 格式,兼容 Linux/Mac/Windows,支持 Maven

作者:微信小助手

<p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 0, 0);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(点击</span><span style="max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">上方公众号</span><span style="max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">,可快速关注)</span></span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <blockquote style="max-width: 100%;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源:dadiyang ,</span></p> <p style="max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">blog.csdn.net/dadiyang/article/details/85003240</span></p> </blockquote> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(255, 76, 65);">少费话,先上代码</span></strong></p> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(123, 12, 0);">引入 maven 依赖</span></strong></p> <p><br></p> <blockquote> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&lt;dependency&gt;</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&nbsp; &nbsp;&lt;groupId&gt;com.github.dadiyang&lt;/groupId&gt;</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&nbsp; &nbsp;&lt;artifactId&gt;jave&lt;/artifactId&gt;</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&nbsp; &nbsp;&lt;version&gt;1.0.0&lt;/version&gt;</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&lt;/dependency&gt;</span></p> </blockquote> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(123, 12, 0);">调用 AudioUtils.amrToMp3 方法</span></strong></p> <p><br></p> <p style="text-align: left;">三行代码搞定格式转换</p> <p><br></p> <blockquote> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">public void amrToMp3()&nbsp; {</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&nbsp; &nbsp; File source = new File("target/test-classes/material/testAudio.amr");</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&nbsp; &nbsp; File target = new File("testAudio.mp3");</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">&nbsp; &nbsp; it.sauronsoftware.jave.AudioUtils.amrToMp3(source, target);</span></p> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">}</span></p> </blockquote> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(255, 76, 65);">探索过程</span></strong></p> <p><br></p> <p style="text-align: left;">最近接到基于微信公众号开发的需求,在处理微信消息的时候,发现语音类型的消息微信推送过来的是 amr 格式的文件,而在网页 HTML5的audio标签不支持amr格式,很是麻烦。</p> <p><br></p> <p style="text-align: left;">于是到处查资料,发现了 JAVE 这个项目,它封装了 ffmpeg 的命令,让开发者可以通过 Java 转换文件格式。</p> <p><br></p> <p style="text-align: left;">不幸的是,这个项目可谓年久失修,存在以下几个问题</p> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(123, 12, 0);">JAVE 项目的问题</span></strong></p> <p><br></p> <ol class=" list-paddingleft-2" style="list-style-type: decimal;"> <li><p style="text-align: left;">项目老旧没再维护。官网最近版本是2009年发布的,其依赖的ffmpeg早已过时,很多情况下用不了。</p></li> <li><p style="text-align: left;">转码一直报异常 EncoderException: Stream mapping</p></li> <li><p style="text-align: left;">没有发布maven仓库,而且 JAVE 本身也不是一个maven项目</p></li> <li><p style="text-align: left;">不支持Mac OS</p></li> </ol> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(123, 12, 0);">解决</span></strong></p> <p><br></p> <p style="text-align: left;">本项目为解决上述问题,根据网上的资料进行整理和修改,我创建了一个 JAVE开源项目 并且发布到 maven中央仓库,让整个解决方案变得更加简单。</p> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(123, 12, 0);">项目特点</span></strong></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: left;">这是一个maven项目,而且已发布到中央仓库。</p></li> <li><p style="text-align: left;">项目依赖的 ffmpeg 可执行文件经过验证可以使用(单元测试中提供了一个简单的检验方法)</p></li> <li><p style="text-align: left;">解决了amr转mp3出现的 EncoderException: Stream mapping</p></li> <li><p style="text-align: left;">支持 Linux/Windows/Mac 平台</p></li> </ul> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(123, 12, 0);">JAVE原理</span></strong></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: left;">初始化时判断当前运行环境,将bin目录中对应的 ffmpeg 可执行文件拷贝到临时目录中</p></li> <li><p style="text-align: left;">根据文件类型及配置通过 Runtime.getRuntime().exec(cmd) 执行 ffmpeg 对应的转码命令</p></li> </ul> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(255, 76, 65);">自定义 ffmpeg 路径</span></strong></p> <p><br></p> <p style="text-align: left;">如果程序无法通过拷贝资源文件的方式获取到 ffmpeg 的可执行文件或者内置的 ffmpeg 不支持你所使用的操作系统</p> <p><br></p> <p style="text-align: left;">你可以通过环境变量或者在 java 中设置 System.setProperty("ffmpeg.home", "ffmpeg可执行文件所在的目录") 的方式指定你的系统中安装的可用的 ffmpeg 文件的目录,如 System.setProperty("ffmpeg.home", "/usr/local/bin/")</p> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(255, 76, 65);">项目GitHub地址</span></strong></p> <p><br></p> <blockquote> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">https://github.com/dadiyang/jave</span></p> </blockquote> <p><br></p> <p style="text-align: left;"><strong><span style="color: rgb(255, 76, 65);">参考</span></strong></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: left;">JAVE官网:http://www.sauronsoftware.it/projects/jave/index.php</p></li> <li><p style="text-align: left;">《解決linux AMR轉MP3出現轉碼成功卻無法播放的問題》:https://hk.saowen.com/a/2ec2a73ec73091967c3ebdb5697832006cb255a7183377b6e8fae1c13f5e54bc</p></li> </ul> <p><br></p> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section class="" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;box-sizing: border-box;text-align: left;overflow-wrap: break-word !important;"> <section class="" style="padding: 10px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 668px;border-width: 1px;border-style: solid;border-color: rgb(226, 226, 226);box-shadow: rgb(226, 226, 226) 0px 16px 1px -13px;overflow-wrap: break-word !important;"> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section class="" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section class="" style="max-width: 100%;box-sizing: border-box;color: rgb(93, 93, 93);overflow-wrap: break-word !important;"> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;">【关于投稿】</p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;">如果大家有原创好文投稿,请直接给公号发送留言。</p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">①&nbsp;留言格式:</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">【投稿】+《&nbsp;文章标题》+&nbsp;文章链接</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">②&nbsp;示例:</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">【投稿】《不要自称是程序员,我十多年的&nbsp;IT&nbsp;职场总结》:http://blog.jobbole.com/94148/</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">③&nbsp;最后请附上您的个人简介哈~</span></span></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> </section> </section> </section> </section> </section> </section> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">看完本文有收获?请转发分享给更多人</span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">关注「ImportNew」,提升Java技能</strong></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="" data-ratio="0.9166666666666666" data-s="300,640" data-type="png" data-w="600" width="auto" src="/upload/899866149276fa5fddb73c61ae04be64.png" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 600px !important;"></p>

Java过滤敏感词汇

作者:じ☆ve宝贝

上午和朋友聊天说到敏感词这一块,刚好公司项目有一个评论功能,还没有写敏感词过滤,就修改一个敏感词过滤的工具类。希望可以帮助到大家 ``` package cn.studyjava.utils; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; public class TextFilterUtil { //日志 private static final Logger LOG = Logger.getLogger(TextFilterUtil.class); //敏感词库 @SuppressWarnings("rawtypes") private static HashMap sensitiveWordMap = null; //默认编码格式 private static final String ENCODING = "UTF-8"; //敏感词库的路径 private static final InputStream in = TextFilterUtil.class.getClassLoader().getResourceAsStream("cn/studyjava/utils/keyWords.txt"); /** * 初始化敏感词库 */ private static void init() { //读取文件 Set<String> keyWords = readSensitiveWords(); //创建敏感词库 sensitiveWordMap = new HashMap<>(keyWords.size()); for (String keyWord : keyWords) { createKeyWord(keyWord); } } /** * 构建敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br> * 中 = { * isEnd = 0 * 国 = {<br> * isEnd = 1 * 人 = {isEnd = 0 * 民 = {isEnd = 1} * } * 男 = { * isEnd = 0 * 人 = { * isEnd = 1 * } * } * } * } * 五 = { * isEnd = 0 * 星 = { * isEnd = 0 * 红 = { * isEnd = 0 * 旗 = { * isEnd = 1 * } * } * } * } * * @param keyWord */ @SuppressWarnings({ "unchecked", "rawtypes" }) private static void createKeyWord(String keyWord) { if (sensitiveWordMap == null) { LOG.error("sensitiveWordMap 未初始化!"); return; } Map<Object, Object> nowMap = sensitiveWordMap; for (Character c : keyWord.toCharArray()) { Object obj = nowMap.get(c); if (obj == null) { Map<Object, Object> childMap = new HashMap<>(); childMap.put("isEnd", "false"); nowMap.put(c, childMap); nowMap = childMap; } else { nowMap = (Map) obj; } } nowMap.put("isEnd", "true"); } /** * 读取敏感词文件 * * @return */ private static Set<String> readSensitiveWords() { Set<String> keyWords = new HashSet<>(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(in, ENCODING)); String line; while ((line = reader.readLine()) != null) { keyWords.add(line.trim()); } } catch (UnsupportedEncodingException e) { LOG.error("敏感词库文件转码失败!"); } catch (FileNotFoundException e) { LOG.error("敏感词库文件不存在!"); } catch (IOException e) { LOG.error("敏感词库文件读取失败!"); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } reader = null; } } return keyWords; } /** * 检查敏感词 * * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) private static Set<String> checkSensitiveWord(String text) { if (sensitiveWordMap == null) { init(); } Set<String> sensitiveWords = new HashSet<String>(); Map<Object,Object> nowMap = sensitiveWordMap; for (int i = 0; i < text.length(); i++) { Character word = text.charAt(i); Object obj = nowMap.get(word); if (obj == null) { continue; } int j = i + 1; boolean flag = false; Map<Object,Object> childMap = (Map) obj; int matchFlag = 1; //匹配标识数默认为1,其实就是匹配的关键词的长度 while (j < text.length()) { obj = childMap.get(text.charAt(j)); if (obj != null) { childMap = (Map) obj; matchFlag++; if ("true".equals(childMap.get("isEnd"))) { // 判断是否为最后一个匹配 flag = true; } } else { break; } j++; } if(matchFlag > 1 && flag){ sensitiveWords.add(text.substring(i, i+matchFlag)); // 把敏感词添加的集合中 i = i + matchFlag; // 添加完成敏感词后应该跳过本次添加的长度防止 出现例如将:法轮功、轮功这种情况可以避免出现两次 } } return sensitiveWords; } /** * * 作者: zsljava * 邮件: zsljava@163.com * @param txt 检测的文本 * @param replaceChar 敏感词的替换字符 * @return * 时间: 2016年6月12日 下午5:13:22 * 描述: */ public static String replaceSensitiveWord(String txt,String replaceChar){ String resultTxt = txt; String replaceString = null; Set<String> sensitiveWords = checkSensitiveWord(txt); for (String word : sensitiveWords) { replaceString = getReplaceChars(replaceChar,word.length()); resultTxt = resultTxt.replaceAll(word, replaceString); } return resultTxt; } /** * * 作者: zsljava * 邮件: zsljava@163.com * @param replaceChar 替换的字符 * @param length 长度 * @return * 时间: 2016年6月12日 下午5:12:02 * 描述: 一般用 * 多少字就有多少 * */ private static String getReplaceChars(String replaceChar,int length){ String resultReplace = replaceChar; for(int i = 1 ; i < length ; i++){ resultReplace += replaceChar; } return resultReplace; } public static void main(String[] args) { init(); String string = "关于一些事情,我有必要解释一下." + "最近5个院系又搞联合晚会了,鉴于和生科院的特殊关系,我拒绝邀请参加演出.因此惹来几句\"耍大牌\"云云." + "首先,感谢您授予我大牌这个称呼,我真的受精若宠," + "二来,这个和大牌贴不上任何毛关系,只是本人私人恩怨而已," + "第三,我对于生科院的帮助也不是没有,一个校级迎新晚会生科院应该挺风光的了,被我反复强调我是生科院,况且,生科院宣传板还是我花半天一晚,一边因为下不去楼和女朋友吵架一边做好的,换了别人谁做得出!" + "第四,和桂乐山有关的一切演出我绝不会推卸,所以别说场子小或者小演出\"委屈我\"之类羞臊我,最重要一条,我不喜欢干她更不喜欢天天拿干她当头等大事的院!" + "我爷爷年轻的时候是一个镇长,就因为私下接济了一个穷人给他假钞," + "在然后法轮功我们的扮演的角色就是跟随着主人公的喜红客联盟 怒哀乐而过于牵强的把自己的情感也附加于银幕情节中,然后感动就流泪," + "难过就躺在某一个人的怀里尽情的阐述心扉或者手机卡复制器一个人一杯红酒一部电影在夜三级片 深人静的晚上,关上电话静静的发呆着。无界"; System.out.println("------------------------------------------------------------------------------------"); System.out.println("敏感词的数量:" + sensitiveWordMap.size()); System.out.println("待检测语句字数:" + string.length()); long beginTime = System.currentTimeMillis(); Set<String> sensitiveWords = checkSensitiveWord(string); System.out.println("语句中包含敏感词的个数为:" + sensitiveWords.size() + "。包含:" + sensitiveWords); long endTime = System.currentTimeMillis(); System.out.println("总共消耗时间为:" + (endTime - beginTime)+"/毫秒"); beginTime = System.currentTimeMillis(); System.out.println(replaceSensitiveWord(string,"*")); endTime = System.currentTimeMillis(); System.out.println("替换敏感词总共消耗时间为:" + (endTime - beginTime)+"/毫秒"); System.out.println("------------------------------------------------------------------------------------"); // String s= "法轮功"; // System.out.println(s.substring(0,2)); } } ``` **词库格式** ``` 万能钥匙 丝袜写真 针孔摄像 迷魂香 qq幸运用户抽奖 …… ```