算法:动态规划解法及例题
算法:动态规划解法及例题经历过很多算法题,其中最常见的解题方法便是动态规划  动态规划(dynamic programming,即DP),是一种常见的求解最优解的方案,他通过将复杂的问题拆分为单阶段的小问题求解,核心思想是递推,通过简单基础的解一步步接近最优解  对于一个算法问题,总有一个相对令人满意的解,但却不一定是我们想要的最优解,譬如在解决动态规划中最经典的背包问题时,有些人首先想到简单省心的贪心算法,取价值最高或是性价比最高的物品组合,这种方案得到的很有可能是最优解,但贪心的算法并不适用于动态规划领域,若是物品中恰好有能将背包塞得很满的组合,而采用贪心策略却浪费了很多背包空间  其实贪心策略本身更多也是一种“相对最优”的解决方案,而很少是真正的最优,这一点请务必斟酌  

2020-03-11鱼鱼
分布式系统中的一致性算法和问题解决
分布式系统中的一致性算法和问题解决在撰写脑裂问题相关的博客时发现脑裂问题的产生原因在不同算法下的分布式系统各不相同,需要先大致了解一致性算法并针对性的解决  市面上有很多开源的分布式系统,他们的数据一致性算法不尽相同,例如k-v系统的祖师爷——zookeeper采用的是ZAB的算法,而最近流行的Consul是raft算法,不同数据中心server沟通的方式则是gossip协议  不同的协议和方式对选举和数据同步有不同的处理机制,利用这篇文章来对比常见的分布式一致性算法  一个系统可能会使用多个不同的一致性算法,以便于在不同的业务环节上有着各自更贴切的处理  ps:有种观点是一致性算法不是很准确,因为replica也能保证数据某种程度上具有一致性,有人称之为共识算法  

2021-03-13鱼鱼
IO与NIO
IO与NIO我们都知道IO流传输,其实IO模型有很多,例如BIO、NIO、AIO等,传统的IO都是同步的  IO为各种流操作    IO操作分类 I        IO操作分类 II  其中,输入流可以为InputStream和Reader,分别为字节流和字符流,对应地,输出流为OutputStream和Writer,具体的使用在此不详述  NIO是IO模型中后推出的新IO模型  NIO并不一定是多线程的,但是NIO是多管道的,利用缓冲作为中间介质进行数据传输,运用的其实是多路复用技术,它恰恰是通过减少线程数量从而减少上下文的频繁切换,提高性能  Channel:通道,相当于一个连接,不能直接输出数据,只能与Buffer交换数据  

2019-05-11鱼鱼
mysql orderby排序
mysql orderby排序where 字段和orderby字段组成一个联合索引,这个样一个普通业务的order只需要通过这个索引就能确定排序顺序,不需要额外的临时表来计算字段的排序  可以通过配置max_length_for_sort_data改变mysql判断采取方式  全字段排序 将命中的行的所有要查询的结果集都放到排序的临时表内,排序后将数据结果集返回  rowid 排序 将命中的行的排序字段和主键id放到临时表内排序,再根据排序后的主键id进行一次回表查询  虽然有联合索引,但是当where的条件不止一个时候,order by就会失效,可以采取多次查询结果,然后在服务中排序的方式来解决问题          

2020-05-17yangwcn
扫盲——加密那些事
扫盲——加密那些事扫盲加密解密算法  日常开发中我们经常接触MD5算法,以此进行简单的文件完整性校验或者是后台密码验证,MD5是最常见也是最简单快捷的散列算法,常用于参数或文件完整性校验,譬如网络请求发起方与接收方分别对参数做MD5编码,一旦不一致便判断请求被篡改从而拒绝该请求,从而保证信息安全,编码后的字符串是编码前文本的一个简要梗概,因此它也被称作是信息摘要算法  这个算法的特点就是不可逆,只用于信息准确性和防篡改的校验,当然,MD5作为老牌的散列算法,很多经典的编码已经可以被反向解码出来(依靠正向的暴力穷举)以及被碰撞模仿(王小云院士团队的"破解"能够根据MD5编码后串码模拟原始消息,即使它可能与原信息不同),类似的还有SHA1,因此衍生了SHA224、SHA256、SHA512等更多安全的散列算法  

2021-05-14鱼鱼
阻塞队列与Protobuf的Udp通信 - 基于Cat的代理(Agent)项目拆解
阻塞队列与Protobuf的Udp通信 - 基于Cat的代理(Agent)项目拆解CAT是美团点评的一个基于Java开发的异常和性能监控项目,github地址:https://github.com/dianping/cat  本篇文章不是对CAT本身的源码拆解,而是基于本人依赖CAT client开发的代理项目进行拆解,但是并不会纰漏任何技术细节  CAT当前已有很多不同语言的Client,当然暂且是不  CAT本身是通过CAT client收集数据并上报至CAT server,server会进行并,共有六种常见数据格式:Transaction、Event、Problem、Metric、HeartBeat、调用链标记,其实如果不考虑复杂的处理(譬如Metric是可以基于指标生成折线图,Problem可以根据具体的异常类型追溯到相应的会话Track)除去Transaction剩余的数据格式都可以理解为特殊的Event  

2020-07-19鱼鱼
Rocket MQ的基本应用
Rocket MQ的基本应用消息队列,常用于应用间通信  本篇文章基于RocketMQ官方文档  Topic:消息分类,依靠topic来定义消息类型  Tag:消息二级分类,可选,同个topic用不同的tag区分消息类别  Message : 泛指MQ所传送的消息体  Producer:消息生产者  Consumer:消息消费者  Name Server:有点类似于zookeeper,负责服务的注册与发现,维护Broker与Topic的映射关系  Broker:负责消息的存储与生产者消费者消息接收与分发,与Name Server建立长连接,保持心跳上传负责的topic信息  Producer:消息生产者,从Name Server获取Broker对应Topic映射关系,然后与Broker建立连接发送消息  

2019-06-28鱼鱼
使用RPC与Restful接口调用服务
使用RPC与Restful接口调用服务在SOA和微服务架构中,远程通信是无法避免的,最常用的远程通信有两种方式:  restful的接口,使用Http通信  使用dubbo或是Spring Cloud组件进行 RPC协议远程调用,可选地使用socket通信  不同的人对 RPC调用会有不同的看法,甚至对rpc本身的理解都不甚相同,但我认为 RPC有两种倾向:  一为语义化的 RPC  没有统一的请求规范,数据格式在开发人员中很难达成一致,在使用传统Http调用时,交互的双方需要约定一份“API文档”以保证数据格式的唯一性,这样API格式本身就成为了一道大墙,耽误研发双方的时间  但如果服务间采用语义化 RPC进行交互,双方可能并不需要一份文档,只要一份约定好的代码,并以此作为双方的依赖,在请求时也仅仅是直接调用方法本身,如此强的语义性怎能让人不爱  

2021-01-13鱼鱼
Springboot源码原理:从启动方法看配置加载
Springboot源码原理:从启动方法看配置加载首先看一个springboot项目的配置,我们可以定义一个application.yml,对于不同的环境有时也通过profile配置项指定不同的配置文件(譬如application-dev.yml),也可以通过命令行覆写具体的VM options配置项(举个栗子,启动时执行 java -jar xxx.jar --server.port=8080),此文讲解这些配制的读取原理  整体配置项的优先级从高到低为:  命令行配置;  系统属性(System.getProperties())  系统环境变量  jar包外的主配置文件(带有)  jar包内的主配置文件  jar包外的次要配置文件(由spring.profile指定的)  

2021-03-09鱼鱼
CAT的使用和原理简介
CAT的使用和原理简介开发中刚好碰到了CAT的应用,利用这篇文章总结一下  
![CAT的使用和原理简介]()
2019-08-07鱼鱼
使用Shiro和token进行无状态登录
使用Shiro和token进行无状态登录我们之前可以使用shiro实现登录,但这些都是基于session或是cookie实现的,这些只能用于单机部署的服务,或是分布式服务共享会话,显然后者开销极大,所以JWT(JSON Web Token)应运而生,JWT是一套约定好的认证协议,通过请求携带令牌来访问那些需鉴权的接口  我们在这里使用token,原理类似,但是规则更为简单,没有形式上的约束,只是在请求Head或是body中添加token用于校验用户身份,token是可以和会话共存的,此处我们使用Shiro的会话登录结合JWT来实现无状态登录,从而实现扫码登录和一般的接口访问授权  项目中,需要实现无状态登录(单点登录,SSO),但是同时也要保持Shiro本身自带的会话登录  
![使用Shiro和token进行无状态登录]()
2020-03-22鱼鱼
算法:递归
算法:递归递归算法主要寻找:  终止条件:递归的尽头  单级递归的行为:在一次递归里要做的事情  返回值:每次迭代要return的东西  例如  首先,假定方法是已经实现的  终止条件为:当当前节点(传了空节点)或下一节点(传了单节点)为空,则无需反转返回当前节点  递归行为:假定之后的节点均已实现反转,则需要将已经反转的尾部的next变为当前节点,而当前节点由于是第一个节点,其next为null  此处注意在反转前需要先留存反转后的尾部;  返回值:返回反转后的头结点    
![算法:递归]()
2020-06-24鱼鱼