作者:じ☆ve宝贝
> 现在很多框架使用log4j2作为日志框架,近期在jfinal项目使用es的jar包时,发现没有办法打印日志,故将jfinal日志框架改为log4j2 ## pom.xml 中引入相关jar包 ``` <properties> <!-- log4j日志文件管理包版本 --> <slf4j.version>1.7.21</slf4j.version> <log4j2.version>2.8.2</log4j2.version> </properties> <dependencies> <!--添加SLF4J-JCL依赖,将对JCL的日志API调用转换为对SLF4J接口的调用 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j2.version}</version> </dependency> <!-- 桥接:告诉commons logging使用Log4j2 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jcl</artifactId> <version>${log4j2.version}</version> </dependency> <!-- 桥接:告诉Java Util Logging使用Log4j2 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j2.version}</version> </dependency> </dependencies> ``` ## 实现jfinal的 ILogFactory ``` import com.jfinal.log.ILogFactory; import com.jfinal.log.Log; public class Slf4jLogFactory implements ILogFactory { @Override public Log getLog(Class<?> clazz) { return new Slf4jLogger(clazz); } @Override public Log getLog(String name) { return new Slf4jLogger(name); } } ``` ## 集成jfinal的 Log ``` import org.slf4j.LoggerFactory; import com.jfinal.log.Log; public class Slf4jLogger extends Log { private org.slf4j.Logger log; Slf4jLogger(Class<?> clazz) { log = LoggerFactory.getLogger(clazz); } Slf4jLogger(String name) { log = LoggerFactory.getLogger(name); } public void info(String message) { log.info(message); } public void info(String message, Throwable t) { log.info(message, t); } public void debug(String message) { log.debug(message); } public void debug(String message, Throwable t) { log.debug(message, t); } public void warn(String message) { log.warn(message); } public void warn(String message, Throwable t) { log.warn(message, t); } public void error(String message) { log.error(message); } public void error(String message, Throwable t) { log.error(message, t); } public void fatal(String message) { log.error(message); } public void fatal(String message, Throwable t) { log.error(message, t); } public boolean isDebugEnabled() { return log.isDebugEnabled(); } public boolean isInfoEnabled() { return log.isInfoEnabled(); } public boolean isWarnEnabled() { return log.isWarnEnabled(); } public boolean isErrorEnabled() { return log.isErrorEnabled(); } public boolean isFatalEnabled() { return log.isErrorEnabled(); } } ``` ## 指定Jfinal默认加载的log框架 在继承JFinalConfig的类中找到 configConstant方法 ``` /** * 配置常量 */ public void configConstant(Constants me) { me.setLogFactory(new Slf4jLogFactory()); // 加载少量必要配置,随后可用PropKit.get(...)获取值 PropKit.use("config.properties"); me.setDevMode(PropKit.getBoolean("devMode", false)); } ``` ## log4j2.xml ``` <?xml version="1.0" encoding="UTF-8"?> <!-- Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时, 你会看到log4j2内部各种详细输出。可以设置成OFF(关闭) 或 Error(只输出错误信息)。 600s 刷新此配置 --> <Configuration status="WARN" monitorInterval="600"> <Appenders> <Console name="Console" target="SYSTEM_OUT" ignoreExceptions="false"> <PatternLayout pattern="%n%-d{yyyy-MM-dd HH:mm:ss}%n[%p]-[Thread: %t]-[%C.%M()]: %m%n" /> </Console> </Appenders> <Loggers> <logger name="org.mybatis" level="debug" additivity="true" /> <Root level="info"> <AppenderRef ref="Console" /> </Root> </Loggers> </Configuration> ``` **这样配置完成后你的日志框架已经成功切换为log4j2了**
作者:MyLove
站长呢?咋没联系方式
作者:じ☆ve宝贝
### 1、创建一个HtmlHandler ``` package cn.studyjava.handler; import com.jfinal.handler.Handler; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HtmlHandler extends Handler { @Override public void handle(String s, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, boolean[] booleans) { if(s.lastIndexOf(".html") != -1) { s = s.substring(0, s.indexOf(".html")); } nextHandler.handle(s, httpServletRequest, httpServletResponse, booleans); } } ``` ### 2、在你的config里加载一下就ok了 ``` public class StudyJavaConfig extends JFinalConfig { ...... /** * 配置处理器 */ public void configHandler(Handlers me) { me.add(new HtmlHandler()); } } ```
作者:不要哭啦
有时网络不稳定,ssh容易断开,如果这个时候你正在执行安装等操作,操作也会终止。有时到了下班点,可一个下载或安装程序还没有完成,如果断开连接下班,那么程序也会终止,难道就不下班了吗?NO,班是要下的,程序也是要继续执行的。 步骤: 1、安装screen命令 ``` yum install screen #安装 ``` 2、screen -S spider#创建screen会话,自定义screen虚拟终端的名称,spider可以改为你想要的名称 3、在screen下执行程序就可以了。断开SSH后,再连上,通过screen -r spider回到spider这个screen,发现程序依然再执行 4、常用screen参数 ``` screen -S yourname -> 新建一个叫yourname的session screen -ls -> 列出当前所有的session screen -r yourname -> 回到yourname这个session screen -d yourname -> 远程detach某个session screen -d -r yourname -> 结束当前session并回到yourname这个session ``` 按键盘上面的Ctrl+a,然后再按d #保存当前的screen会话 ``` exit #退出scree ```
作者:微信小助手
<blockquote style="box-sizing: border-box;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">分布式架构:原理,设计与实战,目前公司每个月都要出账,出账就是每个月有要把之前的一个月的账目盘算清楚,做到错误的0容忍,一笔都不能错,错一笔客户都会找你,偏准确性。4个9,5个9并不是说后面设计的,而是在开发之初就要考虑的。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5283333333333333" src="/upload/cf1f5a15d7b9452d9dfeb8515a4d458f.png" data-type="png" data-w="600" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <h4 style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 18px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">分布式服务的发展历程</h4> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">J2EE架构</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">俗称JEE。对于大概有5年以上工作经验的老铁,应该都听过这个名词。基本分为3层。</p> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;">web容器</span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;">EJB容器</span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;">数据库和数据存取的ORM</span></p></li> </ol> <p style="box-sizing: border-box;margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">那时候的容器之间都没有进行物理的隔离,都是部署在同一个jvm上的。所以久而久之,它们之间互相的耦合互相的依赖,业务之前有千丝万缕的,添加和修改增加新的业务的时候,他们变的很复杂,经常导致服务不可用。这个时代就是有了层次,但是层次之前没有进行物理的隔离。带来了一些问题。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.703601108033241" src="/upload/3c9be7d3886c8adc7213b94a7725bcce.png" data-type="png" data-w="722" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">SSH架构</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">开源框架SSH = struts + spring + hibernate,实际上它跟JEE的架构是基本相似的,也把组件分成了三层。</p> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;">struts MVC UI组件</span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;">spring 业务组件,实现业务的逻辑</span></p></li> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;">ORM 对象管理映射层,连接数据库的</span></p></li> </ol> <p style="box-sizing: border-box;margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">那时候的SSH非常流行,因为那个时期都是给传统的行业和制造行业来做的系统,在互联网行业里面ssh架构就不灵了。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.6450381679389313" src="/upload/4a014a08d4ac11ad680db52a041c3074.png" data-type="png" data-w="786" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">Web Service 架构</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">互联网行业偏向于服务化,最流行的微服务起源于服务化,服务化最早体现在web service,web service 以IBM为首的各大公司制定的标准,webservice特点服务开发完毕后,不在部署在同一台机器,同一个JVM上面,拆分成不同的服务,例如图中的web service1 ,web service2,web service3 它们3个各自有各自的角色,各自有各自的功能,服务和服务之前都是通过远程调用的方式来实现互相实现和交流的,远程调用是遵循已定的标准,当时标准是SOAP协议,这个协议是在http协议之上的,来传输xml来完成的。有了这些的服务。需要服务的发现机制,通过webservice的目录来实现的。所有的服务对外提供服务的功能,需要在webservice注册。发现服务UDDI,找到服务WSDL找到服务。这个时代服务主要的特点是:职责拆分,服务部署隔离,服务调用遵守协议。webservice定义的协议是非常重的,首先xml序列化,xml有冗余的标签,服务性能上不来的。webservice注册通信化的服务,通信化的注册服务一定要保证高可用。在互联网里面如果不是高可用的,服务也不是最优化的。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.560488346281909" src="/upload/bfea06031dbcfaa573307ccf2faade1f.png" data-type="png" data-w="901" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">ESB架构</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">企业服务总线,侧重于企业服务总线。 上边是提供的服务,下面是数据库数据源,消息队列,大数据,ERP。所有的服务和资源只要都进入ESB中,就会进行编排,完成特定的功能。这个时期,ESB功能进行了拆分,也有各自的职责,都进行了拆分,在不同的物理机,在不同JVM中。主要体现在可插拔,快速的添加删除服务,快速的加入资源。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.4885654885654886" src="/upload/a305b985aaf0b3eefb87474552e4dbe2.png" data-type="png" data-w="962" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">微服务架构</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">最流行的架构,跟传统架构是一脉相承的,并不是矛盾的。采用的是分层的概念,上层的服务依赖下层的服务,基本两层,第一层:业务服务一;第二层:业务服务2,3,4。上一层跟下一层是依赖的,但是不是循环依赖的。每个服务之间自己是用数据库的,实际上数据库缓存和消息队列都是自治的,这就使微服务有自我管理的权限,微服务内可以快速的消化需求,敏捷上线,提高开发和运维的效率,微服务之前是通过远程的服务调用来先实现的。远程服务调用,并没有特定的要求是通过使用restful还是rpc,要求服务之间一定要有契约,契约可以服务生产者提出,也可以服务消费者提出的服务生产者契约,也可以是多个服务消费者一起找服务的生产者提要求,服务生产者提供一个公共的契约,保证通信没有问题的。例如:来了个需求,先进行服务的拆分,拆分到不同的微服务里面,微服务有了良好的通信契约,不在管对外的功能,就在服务内把需求消化掉了。上线和响应市场也是非常敏捷的。微服务每个节点他们的拆分都是比较单一的,都是比较细的,职责单一后,专业的人干专业的事情,这样很难犯错误,这样系统的可用性就提高起来了。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5316062176165803" src="/upload/8cc89e15ba1c9f1ef1dcb3a36eda017c.png" data-type="png" data-w="965" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">微服务的团队管理</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">团队其实也是自治的。微服务团队里面可能是有产品,运营,测试,开发。如果系统分配到某个团队内,在团队内的开发可以非常敏捷的沟通,很快的开发上线,并不需要跨团队的沟通,跨团队的协调,回顾下当初的SSH,公司分为UI组,开发组,测试组,DB人团队沟通,都不是微服务的团队导致沟通效率很低。所以这就是微服务倡导的敏捷,专业的人干专业的事。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5966785290628707" src="/upload/642bfdb854d09228809a9ea6b47a8666.png" data-type="png" data-w="843" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">分布式服务架构的精髓</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">敏捷上线,微服务下的自治,有效的减少不可用的因素。服务化和微服务都使用了分而治之的思想,分布式服务和分布式系统架构里面,无论是提高性能,提高吞吐量,提高敏捷性。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5413612565445026" src="/upload/d43063fcc38696f501ba7e21c2a8ea96.png" data-type="png" data-w="955" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">微服务架构的痛点</span></span></p></li> </ul> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">一致性</span></span></p></li> </ol> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">强一致性和弱一致性</p> </blockquote> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">高性能</span></span></p></li> </ol> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">容量评估和性能测试</p> </blockquote> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">高可用</span></span></p></li> </ol> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">4个9和5个9</p> </blockquote> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">可扩展</span></span></p></li> </ol> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">可修改,迭代新功能,可插拔</p> </blockquote> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">可伸缩</span></span></p></li> </ol> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">应用层和资源层,随着硬件投入的增加性能和能力相应的增长</p> </blockquote> <ol style="" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">安全性</span></span></p></li> </ol> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">防偷窥,防泄漏,防抵赖,防篡改,防中间人攻击</p> </blockquote> <h4 style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 18px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">保证分布式一致性的最佳方案</h4> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">周朝的时候,分而治之,后来都不听周王的话,导致不一致。不一致导致的痛点是很大的。如何去解决不一致的问题。线上趟过的坑和总结的经验分享。</p> </blockquote> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">一致性原理</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">本质上需要理解下面的3种,本身是什么,应用的场景。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5046923879040668" src="/upload/7fdaebfbc73f0f6e6370dfd53f4d6683.png" data-type="png" data-w="959" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">ACID,数据库理论的时候,我们都学过ACID就是强一致性。四个名词代表的是一个事务是不可以在进行拆分的,要么都成功,要么都失败。在传统的数据库里面都是单体的应用,单体的应用必须保持强一致性的,尤其是我们的关系型数据库。犹豫在互联网高并发的线上。用户量非常大,上千,上万,上亿的,单体的服务架构和单体数据库很难撑起来这么大的量,所以就需要它们之前进行分而治之,在网上进行分开,进行分开,分片。带来的问题,当网络出现问题的时候,这些应用是否可以正常的工作。这就引入了CAP原则。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">CAP,之间肯定是网络通信,一定要有分区容错性,也就是某个节点网络不能正常的通信时。网络断了,或者闪断的话,各自之间还要继续的工作。P肯定是要有的。这个原则是如果三者只能选择其中的二个,P已经必须要了,那就需要在C和A之间选择一个。例如:网络上有一份数据,数据是通过复制来完成的。一份是主数据,一份是从数据,当你存一份数据的时候到主数据的时候,同时也需要往从数据中存一份,如果从出现问题,是继续还是返回给主,这就是一致性和可用性的解读。如果主从必须保持一致,主从都存起来后才可以返回的话,那就保证一致性,可用性就不好,如果网络出问题,就一致等待都一致才返回。不会在有限的时间内返回给客户端的请求,可用性就很差,所以一致性和可用性就是互斥的。如果是很快的返回客户端,那就可能牺牲了一致性保持了可用性。总结就是在容错性的基础之上,可用性和一致性是互斥的。不可兼得。</p> <p style="box-sizing: border-box;margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">BASE,基本可用,中间有软状态,最终保持了一致。基本可用是条件,最终保持一致是目标。软状态就是事先的BASE的方法,就是我们要做一个事,达到目的中间的过程需要2,3个阶段,做完一个阶段记录状态信息,然后做第二个阶段,我们可以从出问题的那个位置恢复到出问题的地方。互联网上很多的高并发项目,都使用了分布式事务都进行打折了,完成了最终一致性。使用了BASE原理,CAP限制了它不可能三者同时存在。</p> </blockquote> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">一致性协议</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">两个阶段的协调者</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.6837837837837838" src="/upload/ea3259f5856cdbe8cba1a28fde99ed99.png" data-type="png" data-w="740" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">三阶段的协调者</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.9795620437956204" src="/upload/4f8bdfa4fbe4589dce80eb042e27eae0.png" data-type="png" data-w="685" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">TCC(Try)</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5553691275167785" src="/upload/1af733b6a9f199a79152248512225172.png" data-type="png" data-w="1192" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">最终一致性</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">查询模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.4540023894862604" src="/upload/ceb7c13ed4b65cb7897bf8799238139b.png" data-type="png" data-w="837" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">补偿模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.4508301404853129" src="/upload/6365d21be6223294d7e6edad2ec335d7.png" data-type="png" data-w="783" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">异步确保模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.4908896034297964" src="/upload/fd376d196680a9d5612c07939d307a53.png" data-type="png" data-w="933" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">定期校对模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.6631736526946108" src="/upload/bad8f6c9367f47be2f0cc10a562f32d5.png" data-type="png" data-w="668" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">可靠消息模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.7413294797687862" src="/upload/7feef4f74b060a8bbc3281fcc8a2f91d.png" data-type="png" data-w="692" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.8933566433566433" src="/upload/b1518ffae14bf261b9b89b9ad379fe94.png" data-type="png" data-w="572" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">服务交互的模式</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">同步模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.23860911270983212" src="/upload/f9a6d46379b7e1965ac6afd138748af2.png" data-type="png" data-w="834" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">异步模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.38545953360768176" src="/upload/43586c58bc7937b545bbfd5f8684a5c3.png" data-type="png" data-w="729" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">消息模式</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.20064724919093851" src="/upload/6cd0ee13b6c21d550bbbcdde857651.png" data-type="png" data-w="927" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">同步与异步的抉择</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">尽量使用异步来替换同步操作</p> <p style="box-sizing: border-box;margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">能用同步解决的问题,不要引入异步</p> </blockquote> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">超时模式</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">同步两个状态的接口超时</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.41847826086956524" src="/upload/1db5cae012d166d7db334d98560157d6.png" data-type="png" data-w="920" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">同步两个状态的内部超时</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.4426919032597266" src="/upload/205b687581888f682f676ec7a14e528.png" data-type="png" data-w="951" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">同步三状态的内部超时</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.38324022346368714" src="/upload/40aafce36a2c16a3aec14f263e218c81.png" data-type="png" data-w="895" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">异步受理超时</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5022075055187638" src="/upload/1ca040124f4a29161ec6f7c55caaa25d.png" data-type="png" data-w="906" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">消息队列发送超时</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.4226254002134472" src="/upload/51399df00ce0abf1c6e0875f0ee95d62.png" data-type="png" data-w="937" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">消息对垒接收超时</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.3084522502744237" src="/upload/b5d05558128e49d4e5061e6f774ec2a6.png" data-type="png" data-w="911" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">补偿的博弈</span></span></p></li> </ul> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.33127317676143386" src="/upload/6d7b172c6f7cc13d77ccccce27993ff0.png" data-type="png" data-w="809" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">服务1调用服务2,如果服务2响应服务1,并且告诉服务1消息我接收了,那么服务1的任务就结束了,如果服务2处理失败,服务2应该负责重试或者补偿。在这种情况下,服务2通常先持久化消息后再告诉服务1接收成功,随后服务2才开始处理持久的消息,避免服务进程被傻吊丢失消息的情况。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.38929695697796435" src="/upload/c1beca95894329245c7fafef023fd136.png" data-type="png" data-w="953" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">服务1调用服务2,如果服务2没有给出明确的接收响应,那么服务1应该持久尝试重试,知道服务2明确表达已经接收消息,这种情况下,容易出现消息重复,因此在服务2中通常要保证滤重或者幂等性。</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.35526315789473684" src="/upload/c8d06c574d18bab4d82142b9d52dae14.png" data-type="png" data-w="912" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">缓存使用的一致性模式</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">缓存是用来加速的,牺牲了一致性,获得高性能,只适合特殊场景。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">保持数据库和缓存的强一致性是个伪命题</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">如果性能要求不是非常的高,尽量使用分布式缓存,而不是使用本地缓存,本地缓存可能你现在读的时候本地是开,其实另一个时间其他人读的是关,你想想多可怕。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">种缓存的时候一定种完全,如果缓存数据的一部分有效,一部分无效,宁可放弃种缓存,也不要把部分数据中入缓存</p> <p style="box-sizing: border-box;margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">通常情况下读的顺序要先缓存,后数据库,写的顺序要先数据库,后缓存</p> </blockquote> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p><span style="box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="box-sizing: border-box;line-height: 22px;">迁移开关的设计模式</span></span></p></li> </ul> <blockquote style="box-sizing: border-box;margin-top: 1em;margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="box-sizing: border-box;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">新旧系统的迁移。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">不要用统一配置开关,开关是定义在某个业务上。在一个系统做滤重,比在多个系统做滤重简单。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">不要用节点独立的开关</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">迁移开关必须使用订单开关</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">开关要用权限控制。开关的重要,特定经验的人来操作。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">开关要能开能关</p> <p style="box-sizing: border-box;margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">迁移开关要大小力度都有</p> </blockquote> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;">PS:了解分布式架构,是对自己从心智上的一种提升,敲代码只是往下看,建议多往前方看看。架构这条路不好走,需要多接触,多趟多走,才能前方一路小平破。</p> <p style="box-sizing: border-box;margin-top: 15px;margin-bottom: 15px;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;"><img class="" data-ratio="0.5009259259259259" src="/upload/c264bae9964f688e105ec6a87b003eb8.png" data-type="png" data-w="1080" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;"></p> <p><br></p>
作者:微信小助手
<section class="mpa-template" data-mpa-template-id="1292523" data-mpa-color="null" data-mpa-category="fav" data-mpa-powered-by="yiban.io"> <section class="" data-mpa-template-id="549497" data-mpa-color="null" data-mpa-category="fav"> <section class="" data-tools="135编辑器" data-id="23"> <section class=""> <p class=""><br></p> </section> </section> </section> </section> <blockquote> <p><span style="font-size: 15px;color: rgb(136, 136, 136);">转自公众号:不只Java</span></p> </blockquote> <p><br></p> <p>今天想和大家分享有关 Redis 主从同步(也称「复制」)的内容。</p> <p><br></p> <p>我们知道,当有多台 Redis 服务器时,肯定就有一台主服务器和多台从服务器。一般来说,主服务器进行写操作,从服务器进行读操作。</p> <p><br></p> <p>那么这里有存在一个问题:从服务器如何和主服务器进行数据同步的呢?</p> <p><br></p> <p>这个问题,就是通过今天的内容:主从同步来解决的。</p> <p><br></p> <p>文章内容依旧比较干,一共 3k+ 字,建议大家静下心来专心看,文末会给大家做个简单总结归纳。</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1449767" data-mpa-color="null" data-mpa-category="收藏"> <section data-mpa-template-id="1292524" data-mpa-color="null" data-mpa-category="fav"> <section data-mpa-template-id="612780" data-mpa-color="null" data-mpa-category="fav"> <p><strong>一、如何进行主从同步</strong></p> </section> </section> </section> <p><br></p> <p>假如,现在有 2 台 Redis 服务器,地址分别是 127.0.0.1:6379 和 127.0.0.1:12345<br></p> <p><br></p> <p>我们在 127.0.0.1:12345 的客户端输入命令:</p> <p><br></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t"> <pre>127.0.0.1:12345> SLAVEOF 127.0.0.6379</pre> </section> <p><br></p> <p>如此 127.0.0.1:12345 服务器就会去复制 127.0.0.1:6379 的数据。即前者是从服务器,后者为主服务器。</p> <p><br></p> <p>除了以上方式进行复制之外,还可以通过配置文件中的 slaveof 选项进行设置。</p> <p><br></p> <p>可能,求知欲爆棚的你会想知道,Redis 是怎么进行主从同步的?</p> <p><br></p> <p>ok,下面我们继续了解一下。</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1449767" data-mpa-color="null" data-mpa-category="收藏"> <section data-mpa-template-id="1292524" data-mpa-color="null" data-mpa-category="fav"> <section data-mpa-template-id="612780" data-mpa-color="null" data-mpa-category="fav"> <p><strong>二、主从同步的实现过程</strong></p> </section> </section> </section> <p><br></p> <p>主从同步分为 2 个步骤:同步和命令传播</p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;margin-left: 1em;margin-right: 1em;"> <li><p>同步:将从服务器的数据库状态更新成主服务器当前的数据库状态。</p></li> <li><p>命令传播:当主服务器数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致的过程。</p></li> </ul> <p><br></p> <p>上面就是主从同步 2 个步骤的作用,下面我打算稍微细说这两个步骤的实现过程。</p> <p><br></p> <p>这里需要提前说明一下:在 Redis 2.8 版本之前,进行主从复制时一定会顺序执行上述两个步骤,而从 2.8 开始则可能只需要执行命令传播即可。在下文也会解释为什么会这样?</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1554743" data-mpa-color="null" data-mpa-category="收藏"> <strong>1、同步</strong> </section> <p><br></p> <p>从服务器对主服务的同步操作,需要通过 sync 命令来实现,以下是 sync 命令的执行步骤:<br></p> <p><br></p> <p>1. 从服务器向主服务器发送 sync 命令</p> <p>2. 收到 sync 命令后,主服务器执行 bgsave 命令,用来生成 rdb 文件,并在一个缓冲区中记录从现在开始执行的写命令。</p> <p>3. bgsave 执行完成后,将生成的 rdb 文件发送给从服务器,用来给从服务器更新数据</p> <p>4. 主服务器再将缓冲区记录的写命令发送给从服务器,从服务器执行完这些写命令后,此时的数据库状态便和主服务器一致了。</p> <p><br></p> <p>用图表示就是这样的:</p> <p><br></p> <p><img class="" data-copyright="0" data-ratio="0.4502487562189055" data-s="300,640" data-type="png" data-w="402" src="/upload/793a5bd4968742f165b44506fce5b666.png" style=""></p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1554743" data-mpa-color="null" data-mpa-category="收藏"> <strong>2、命令传播</strong> </section> <p><br></p> <p>经过同步操作,此时主从的数据库状态其实已经一致了,但这种一致的状态的并不是一成不变的。<br></p> <p><br></p> <p>在完成同步之后,也许主服务器马上就接受到了新的写命令,执行完该命令后,主从的数据库状态又不一致。</p> <p><br></p> <p>为了再次让主从数据库状态一致,主服务器就需要向从服务器执行命令传播操作 ,即把刚才造成不一致的写命令,发送给从服务器去执行。从服务器执行完成之后,主从数据库状态就又恢复一致了。</p> <p><br></p> <p>这里插播一个疑问: </p> <p><br></p> <p>不知道有没有的读者觉得,当发生上述不一致的情况后,Redis 再执行同步操作不就 ok 了吗?</p> <p><br></p> <p>从效果上来说,的确是可以恢复同步,但其实没有必要。原因是实现同步的 sync 命令是一个非常消耗资源的操作,看完下图的说明,相信你肯定理解的。</p> <p><br></p> <p><img class="" data-copyright="0" data-ratio="0.4211123723041998" data-s="300,640" data-type="png" data-w="881" src="/upload/1264da19086d6c0edb8d601c0d0be4a8.png" style=""></p> <p><br></p> <p>既然同步是一个非常消耗资源的操作,那 Redis 有没有什么优化方法呢?答案当然是有的。</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1554743" data-mpa-color="null" data-mpa-category="收藏"> <strong>3、优化版同步操作</strong> </section> <p><br></p> <p>还记得上面说的内容吗 —— 2.8 版本开始,进行主从同步可能只需要执行命令传播即可。这个也是因为 sync 比较耗资源,从而采取的优化。<br></p> <p><br></p> <p>那什么时候可以这么做呢?我们先看下前提条件:</p> <p><br></p> <p>主从同步实际分 2 种情况:</p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;margin-left: 1em;margin-right: 1em;"> <li><p>初次复制:从服务器第一次复制当前主服务器(PS:主服务器是有可能更换的)</p></li> <li><p>断线后重复制:处于命令传播阶段的主从服务器,因为网络问题而中断复制,从服务器通过自动重连,重新连接上主服务器并继续复制。</p></li> </ul> <p><br></p> <p>在断线后重复制的情况下,在 2.8 版本之前,会再次执行同步(sync 命令)和命令传播。</p> <p><br></p> <p>如果说,在断线期间,主服务器(已有上万键值对)只执行了几个写命令,为了让从服务器弥补这几个命令,却要重新执行 sync 来生成新的 rdb 文件,这也是非常低效的。</p> <p><br></p> <p>为了解决这个问题,2.8 开始就使用 psync 命令来代替 sync 命令去执行同步操作。</p> <p><br></p> <p>psync 具有完整重同步和部分重同步两种模式:</p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;margin-left: 1em;margin-right: 1em;"> <li><p>完整重同步:用于初次复制情况,执行过程同 sync,在这不赘述了。</p></li> <li><p>部分重同步:用于断线后重复制情况,如果满足一定条件,主服务器只需要将断线期间执行的写命令发送给从服务器即可。</p></li> </ul> <p><br></p> <p>因此很明显,当主从同步出现断线后重复制的情况,psync 的部分重同步模式可以解决 sync 的低效情况。</p> <p><br></p> <p>上面的介绍中,出现了「满足一定条件」,那又是鬼什么条件呢?—— 其实就是一个偏移量的比较,具体可以继续往下看。</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1554743" data-mpa-color="null" data-mpa-category="收藏"> <strong>4、 部分重同步的实现 </strong> </section> <p><br></p> <p>部分重同步功能由以下 3 部分组成:<br></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;margin-left: 1em;margin-right: 1em;"> <li><p>主从服务器的复制偏移量</p></li> <li><p>主服务器的复制积压缓冲区</p></li> <li><p>服务器的运行 id(run id)</p></li> </ul> <p><br></p> <section class="mpa-template" data-mpa-template-id="1554743" data-mpa-color="null" data-mpa-category="收藏"> <span style="text-decoration: underline;">1) 复制偏移量 </span> </section> <p><br></p> <p>执行复制的主从服务器都会分别维护各自的复制偏移量:<br></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;margin-left: 1em;margin-right: 1em;"> <li><p>主服务器每次向从服务器传播 n 个字节数据时,都会将自己的复制偏移量加 n。</p></li> <li><p>从服务器接受主服务器传来的数据时,也会将自己的复制偏移量加 n</p></li> </ul> <p><br></p> <p>举个例子:</p> <p><br></p> <p>若当前主服务器的复制偏移量为 10000,此时向从服务器传播 30 个字节数据,结束后复制偏移量为 10030。</p> <p><br></p> <p>这时,从服务器还没接收这 30 个字节数据就断线了,然后重新连接上之后,该从服务器的复制偏移量依旧为 10000,说明主从数据不一致,此时会向主服务器发送 psync 命令。</p> <p><br></p> <p>那么主服务器应该对从服务器执行完整重同步还是部分重同步呢?如果执行部分重同步的话,主服务器又如何知道同步哪些数据给从服务器呢?</p> <p><br></p> <p>以下答案都和复制积压缓冲区有关</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1565621" data-mpa-color="null" data-mpa-category="收藏"> <span style="text-decoration: underline;">2) 复制积压缓冲区</span> </section> <p><br></p> <p>首先,复制积压缓冲区是一个固定长度,先进先出的队列,默认 1MB。<br></p> <p><br></p> <p>当主服务器进行命令传播时,不仅会将命令发送给从服务器,还会发送给这个缓冲区。</p> <p><br></p> <p>因此复制积压缓冲区的构造是这样的:</p> <p><br></p> <p><img class="" data-copyright="0" data-ratio="0.25472747497219134" data-s="300,640" data-type="png" data-w="899" src="/upload/61c122128290701ab7e0194f24da0eda.png" style=""></p> <p><br></p> <p>当从服务器向主服务器发送 psync 命令时,还需要将自己的复制偏移量带上,主服务器就可以通过这个复制偏移量和复制积压缓冲区的偏移量进行对比。</p> <p><br></p> <p>若复制积压缓冲区存在从服务器的复制偏移量 + 1 后的数据,则进行部分重同步,否则进行完整重同步。</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1565621" data-mpa-color="null" data-mpa-category="收藏"> <span style="text-decoration: underline;">3) run id</span> </section> <p><br></p> <p>运行 id 是在进行初次复制时,主服务器将会将自己的运行 id 发送给从服务器,让其保存起来。<br></p> <p><br></p> <p>当从服务器断线重连后,从服务器会将这个运行 id 发送给刚连接上的主服务器。</p> <p><br></p> <p>若当前服务器的运行 id 与之相同,说明从服务器断线前复制的服务器就是当前服务器,主服务器可以尝试执行部分同步;</p> <p><br></p> <p>若不同则说明从服务器断线前复制的服务器不是当前服务器,主服务器直接执行完整重同步。</p> <p><br></p> <p>花了很多笔墨,终于把部分重同步的实现写完了,最后补充一个辅助功能</p> <p><br></p> <section class="mpa-template" data-mpa-template-id="1554743" data-mpa-color="null" data-mpa-category="收藏"> <strong>5、心跳检测 </strong> </section> <p><br></p> <p>刚才提到,主从同步有同步和命令传播 2 个步骤。<br></p> <p><br></p> <p>当完成了同步之后,主从服务器就会进入命令传播阶段,此时从服务器会以每秒 1 次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset> ,其中 replication_offset 是从服务器当前的复制偏移量</p> <p><br></p> <p>发送这个命令主要有三个作用:</p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p>检测主从服务器的网络状态</p></li> <li><p>辅助实现 min-slaves 选项</p></li> <li><p>检测命令丢失(若丢失,主服务器会将丢失的写命令重新发给从服务器)</p></li> </ul> <p><br></p> <section class="mpa-template" data-mpa-template-id="1449767" data-mpa-color="null" data-mpa-category="收藏"> <section data-mpa-template-id="1292524" data-mpa-color="null" data-mpa-category="fav"> <section data-mpa-template-id="612780" data-mpa-color="null" data-mpa-category="fav"> <p><strong>三、总结</strong></p> <p><br></p> </section> </section> </section> <p>终于到总结了,我们来总结一下,纪念下我这一个下午的时间。<img data-ratio="1" data-w="20" src="/upload/d8165e442679dd6eaa7a46937ef6b946.null" style="display:inline-block;width:20px;vertical-align:text-bottom;"><br></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p>发送 SLAVEOF 命令可以进行主从同步,比如:SLAVEOF 127.0.0.6379</p></li> <li><p>主从同步有同步和命令传播 2 个步骤。</p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p>同步:将从服务器的数据库状态更新成主服务器当前的数据库状态(一个消耗资源的操作)</p></li> <li><p>命令传播:当主服务器数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致的过程</p></li> </ul> <li><p>主从同步分初次复制和断线后重复制两种情况</p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p>从 2.8 版本开始,在出现断线后重复制情况时,主服务器会根据复制偏移量、复制积压缓冲区和 run id,来确定执行完整重同步还是部分重同步</p></li> </ul> <li><p>2.8 版本使用 psync 命令来代替 sync 命令去执行同步操作。目的是为了解决同步(sync 命令)的低效操作</p></li> </ul> <p><br></p> <section class="" data-style-type="5" data-tools="新媒体排版" data-id="1584460" style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"> <p class="" style="letter-spacing: 0.544px;text-align: center;"><span style="color: rgb(136, 136, 136);"><strong>---END---</strong></span></p> <p class="" style="letter-spacing: 0.544px;"><br></p> <p class="" style="letter-spacing: 0.544px;"><span style="background-color: rgb(136, 136, 136);font-size: 16px;"> <span style="color: rgb(255, 255, 255);">近期热文:</span></span></p> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p style="margin-top: 5px;"><a href="http://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247486716&idx=1&sn=a301ee4feec7cf5cb37c2656d109456d&chksm=e8fe90f5df8919e387bb7f4771f9b52bbc768a74c877efbcf35ef6003a05abedee162f0f377a&scene=21#wechat_redirect" target="_blank" style="text-decoration: underline;font-size: 15px;color: rgb(136, 136, 136);" data-linktype="2"><span style="font-size: 15px;color: rgb(136, 136, 136);">咱们来一起抱团取暖,好吗?</span></a></p></li> <li><p style="margin-top: 5px;"><a href="http://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247486582&idx=1&sn=ae181c7e01684259f52ce6c1d847ebf9&chksm=e8fe907fdf891969ef3041fee79c5d696f9db0bb5a3a6f55f39964e4b529ae466d0df959a439&scene=21#wechat_redirect" target="_blank" data-linktype="2" style="color: rgb(136, 136, 136);text-decoration: underline;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);letter-spacing: 0.544px;font-size: 15px;">漫画:老板扣了我1000,因为我没记住阿里巴巴开发手册的这条规则。</a><br></p></li> <li><p style="margin-top: 5px;"><span style="color: rgb(136, 136, 136);text-decoration: underline;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);font-size: 15px;"><a href="http://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247486509&idx=1&sn=1ff0904ce0d02544ec185ee7651af481&chksm=e8fe9024df891932ee56171a0c6143faa8d68e0b173b01f115861bcfb0e955c1517222962323&scene=21#wechat_redirect" target="_blank" data-linktype="2" style="color: rgb(136, 136, 136);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">漫画:奇怪,为什么在Java中2*(i*i)比2*i*i快?</a></span></p></li> <li><p style="margin-top: 5px;"><a href="http://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247486046&idx=1&sn=a1cb6838d6d1a33271e11acf38231384&chksm=e8fe9657df891f4116b54bfaf47bcc78f797231d6012c57aec987d13ae0c191cb4839006959e&scene=21#wechat_redirect" target="_blank" style="text-decoration: underline;font-size: 15px;color: rgb(136, 136, 136);" data-linktype="2"><span style="font-size: 15px;color: rgb(136, 136, 136);">别再问我要免费资料了,都在这里。</span></a><br></p></li> </ul> </section> <section class="" data-style-type="5" data-tools="新媒体排版" data-id="1661036" style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"> <p class="" style="margin-right: 1em;margin-left: 1em;letter-spacing: 2px;line-height: 1.75em;"><br></p> <p class="" style="margin-right: 1em;margin-left: 1em;text-align: center;"><img class="" data-copyright="0" data-cropselx1="0" data-cropselx2="600" data-cropsely1="0" data-cropsely2="251" data-ratio="0.34475806451612906" data-s="300,640" data-type="png" data-w="2480" src="/upload/9dfa97dc5da8448184d607b9e1a921a8.png" style="box-shadow: rgb(170, 170, 170) 0em 0em 1em 0px;visibility: visible !important;width: 634px !important;"></p> </section>
作者:じ☆ve宝贝
File-->Setting-->Live Templates-->other  不要忘记下面的:define, 选择你要应用的地方,如勾选java
作者:微信小助手
<p data-mpa-powered-by="yiban.io"><br></p> <section class="" style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB, Microsoft YaHei UI, Microsoft YaHei, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);"> <section style="margin: 10px auto;display: flex;justify-content: center;align-items: flex-end;"> <p style="color: rgb(88, 16, 13);line-height: 1.5;text-align: center;"><strong style="color: rgb(57, 137, 31);"><img class="rich_pages" data-copyright="0" data-ratio="0.6666666666666666" data-s="300,640" data-type="jpeg" data-w="1280" src="/upload/398d99ea818be829b0277e1b59a977c8.jpg" style="letter-spacing: 0.544px;box-shadow: rgb(170, 170, 170) 0em 0em 1em 0px;visibility: visible !important;width:auto !important;max-width:100% !important;height:auto !important;"></strong><br></p> </section> </section> <p style="margin-top: 25px;margin-bottom: 15px;white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB, Microsoft YaHei UI, Microsoft YaHei, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);line-height: 2em;text-align: center;"><span style="font-size: 16px;">扫描下方二维码<span style="color: rgb(201, 56, 28);"><strong>试读</strong></span></span></p> <p style="margin-bottom: 15px;white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB, Microsoft YaHei UI, Microsoft YaHei, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><span style="color: rgb(57, 137, 31);"><strong><img class="" data-ratio="0.6666666666666666" data-type="png" data-w="600" src="/upload/3f6bb75371fa02356c9a40f699003d25.png" style="border-radius: 0em;width: 23%;visibility: visible !important;height: auto;"></strong></span></p> <hr style="white-space: normal;border-style: solid;border-right-width: 0px;border-bottom-width: 0px;border-left-width: 0px;border-color: rgba(0, 0, 0, 0.0980392);transform-origin: 0px 0px 0px;transform: scale(1, 0.5);"> <p style="white-space: normal;"><br></p> <h3 style="line-height: 2em;"><strong>一、概念</strong></h3> <p style="line-height: 2em;">幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次,比如:</p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">订单接口, 不能多次创建订单</p></li> </ul> <p style="line-height: 2em;"><br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">支付接口, 重复支付同一笔订单只能扣一次钱</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">支付宝回调接口, 可能会多次回调, 必须处理重复回调</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">普通表单提交接口, 因为网络超时等原因多次点击提交, 只能成功一次<br>等等</p></li> </ul> <p style="line-height: 2em;"><br></p> <h3 style="line-height: 2em;"><strong>二、常见解决方案</strong></h3> <ol class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">唯一索引 -- 防止新增脏数据</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">token机制 -- 防止页面重复提交</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">悲观锁 -- 获取数据的时候加锁(锁表或锁行)</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">乐观锁 -- 基于版本号version实现, 在更新数据那一刻校验数据</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">分布式锁 -- redis(jedis、redisson)或zookeeper实现</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">状态机 -- 状态变更, 更新数据时判断状态</p></li> </ol> <p style="line-height: 2em;"><br></p> <h3 style="line-height: 2em;"><strong>三、本文实现</strong></h3> <p style="line-height: 2em;">本文采用第2种方式实现, 即通过redis + token机制实现接口幂等性校验</p> <p style="line-height: 2em;"><br></p> <h3 style="line-height: 2em;"><strong>四、实现思路</strong></h3> <p style="line-height: 2em;">为需要保证幂等性的每一次请求创建一个唯一标识<code>token</code>, 先获取<code>token</code>, 并将此<code>token</code>存入redis</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">请求接口时, 将此<code>token</code>放到header或者作为请求参数请求接口, 后端接口判断redis中是否存在此<code>token</code>:</p> <p style="line-height: 2em;"><br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">如果存在, 正常处理业务逻辑, 并从redis中删除此<code>token</code>, 那么, 如果是重复请求, 由于<code>token</code>已被删除, 则不能通过校验, 返回<code>请勿重复操作</code>提示</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">如果不存在, 说明参数不合法或者是重复请求, 返回提示即可</p></li> </ul> <h3 style="line-height: 2em;"><br></h3> <h3 style="line-height: 2em;"><strong>五、项目简介</strong></h3> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">springboot</p></li> <li><p style="line-height: 2em;">redis</p></li> <li><p style="line-height: 2em;"><code>@ApiIdempotent</code>注解 + 拦截器对请求进行拦截</p></li> <li><p style="line-height: 2em;">@ControllerAdvice全局异常处理</p></li> <li><p style="line-height: 2em;">压测工具: jmeter</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><span style="color: rgb(57, 137, 31);">说明:</span></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">本文重点介绍幂等性核心实现, 关于<strong>springboot如何集成redis</strong>、<strong>ServerResponse</strong>、<strong>ResponseCode</strong>等细枝末节不在本文讨论范围之内,</p></li> </ul> <p><br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">有兴趣的小伙伴可以查看我的Github项目:</p><p style="line-height: 2em;"><span style="font-size: 12px;">https://github.com/wangzaiplus/springboot/tree/wxw</span></p></li> </ul> <h3 style="line-height: 2em;"><strong><br></strong></h3> <h3 style="line-height: 2em;"><strong>六、代码实现</strong></h3> <ol class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">pom</p></li> </ol> <pre class="hljs xml"><p style="line-height: 2em;"><code class="xml"> <br></code></p><p style="text-align: center;"><img class="rich_pages" data-ratio="0.4431818181818182" data-s="300,640" src="/upload/a9bb7a1ade99b47bf52a879c8bc925a8.png" data-type="png" data-w="616" style=""></p></pre> <p><br></p> <ol start="2" class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><code>JedisUtil</code></p></li> </ol> <pre class="hljs java"> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;" class="hljs-default"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none;font-weight: 400;font-style: normal;">package</span> com.wangzaiplus.test.util;<br mpa-from-tpl="t"><br mpa-from-tpl="t"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">import</span> lombok.extern.slf4j.Slf4j;<br mpa-from-tpl="t"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">import</span> org.springframework.beans.factory.annotation.Autowired;<br mpa-from-tpl="t"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">import</span> org.springframework.stereotype.Component;<br mpa-from-tpl="t"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">import</span> redis.clients.jedis.Jedis;<br mpa-from-tpl="t"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">import</span> redis.clients.jedis.JedisPool;<br mpa-from-tpl="t"><br mpa-from-tpl="t"><span class="hljs-default-meta" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none;font-weight: 400;font-style: normal;">@Component</span><br mpa-from-tpl="t"><span class="hljs-default-meta" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none;font-weight: 400;font-style: normal;">@Slf</span>4j<br mpa-from-tpl="t"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">public</span> <span class="hljs-default-class" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 106px;text-decoration: none;font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none;font-weight: 400;font-style: normal;">class</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none;font-weight: 400;font-style: normal;">JedisUtil</span> </span>{<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="hljs-default-meta" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 66px;text-decoration: none;font-weight: 400;font-style: normal;">@Autowired</span><br mpa-from-tpl="t"> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none;font-weight: 400;font-style: normal;">private</span> JedisPool jedisPool;<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="hljs-default-function" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 165px;text-decoration: none;font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none;font-weight: 400;font-style: normal;">private</span> Jedis <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 52px;text-decoration: none;font-weight: 400;font-style: normal;">getJedis</span><span class="hljs-default-params" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 14px;text-decoration: none;font-weight: 400;font-style: normal;">()</span> </span>{<br mpa-from-tpl="t"> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none;font-weight: 400;font-style: normal;">return</span> jedisPool.getResource();<br mpa-from-tpl="t"> }<br mpa-from-tpl="t"><br mpa-from-tpl="t"> <span class="hljs-default-comment" style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 126px;text-dec
作者:じ☆ve宝贝
powerdesigner 16.5 右侧菜单栏不见了,怎么调出来? powerdesigner 16.5调出工具栏的方法已经变了。 点击View菜单,然后选择Toolbox选项。
作者:じ☆ve宝贝
## 16.迭代子模式(Iterator) 顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松。这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问。我们看下关系图:  这个思路和我们常用的一模一样,MyCollection中定义了集合的一些操作,MyIterator中定义了一系列迭代操作,且持有Collection实例,我们来看看实现代码: 两个接口: ``` public interface Collection { public Iterator iterator(); /*取得集合元素*/ public Object get(int i); /*取得集合大小*/ public int size(); } ``` ``` public interface Iterator { //前移 public Object previous(); //后移 public Object next(); public boolean hasNext(); //取得第一个元素 public Object first(); } ``` 两个实现: ``` public class MyCollection implements Collection { public String string[] = {"A","B","C","D","E"}; @Override public Iterator iterator() { return new MyIterator(this); } @Override public Object get(int i) { return string[i]; } @Override public int size() { return string.length; } } ``` ``` public class MyIterator implements Iterator { private Collection collection; private int pos = -1; public MyIterator(Collection collection){ this.collection = collection; } @Override public Object previous() { if(pos > 0){ pos--; } return collection.get(pos); } @Override public Object next() { if(pos<collection.size()-1){ pos++; } return collection.get(pos); } @Override public boolean hasNext() { if(pos<collection.size()-1){ return true; }else{ return false; } } @Override public Object first() { pos = 0; return collection.get(pos); } } ``` 测试类: ``` public class Test { public static void main(String[] args) { Collection collection = new MyCollection(); Iterator it = collection.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } } ``` 输出:A B C D E 此处我们貌似模拟了一个集合类的过程,感觉是不是很爽?其实JDK中各个类也都是这些基本的东西,加一些设计模式,再加一些优化放到一起的,只要我们把这些东西学会了,掌握好了,我们也可以写出自己的集合类,甚至框架!