Continue...

有感:英语与未来

这篇博文的内容并不是准备将英语的重要性夸赞一番,而是笔者不想一日发两篇博文,且两篇博文多少有些联系,那将「英文」与「未来」这两篇题材的博文写在一起业务大碍。 英语 回想三年前的大三暑假,或是因为着急证明自己,亦或是因为对未来的憧憬,笔者做了一个跟身边同学不一样的选择——投社招。给自留的退路是:若不成功就准备老老实实的回校当一名“在校大四学生”。当时投了三家公司,幸运的是投的第一家公司就给了OFFER,当时也没有面试经验,于是就直接拒绝了后面两家公司的面试,在这家公司一直工作到了现在。至今,在公司里,与大部分同事不同,我工作可能有三分之二的时间花在了调发新技术、新框架、新工具上。深刻体会到两样东西的重要性——「梯子」与「英语」。 梯子 梯子本身并不是一个好东西。最基本的,从我国法律的定义上来看这就是一个“不好的东西”。其实我也不大喜欢这个东西,因为搭建和使用这东西过程就像是与“长城”玩捉迷藏,得小心翼翼,且麻烦。但是通过它才能找到解决各种疑难杂症的解决办法,这些疑难杂症在百度上几乎是找不到解决方法的。 英语 学生时期英语一直不好,很多人也说英语不好不影响做程序员。确实,敲业务代码不需要英语很好,懂一些专业名词就够了。可是对于调研一些新技术,官方的文档就只有英文。如果英语对你来说还是很头疼的一件事,那英文文档就会成为绊脚石,太依靠翻译工具也只会弄得你晕头转向。对于国内外技术交流,若你只停步在与国内程序员交流,那这点大可忽略。 我英语的提升还得从刚入职公司后的三个月说起,当时主要的原因是觉得能像电影明星那样说一口流利的英语真的很酷,另一个原因是或许未来自己能用上英语进行商务交流。于是就自费上了两年的周末成人英语班,除了周末,工作日的晚上也需要完成线上作业,也忘记怎么坚持过来的,但是帮助确实挺大。特别是口语,进行日常交流不会有太大困难。笔者离开周末班也一直有在坚持学习,或许在未来会有更大的帮助。 不大理解一些同事,对于一些问题的解决方法,官方文档明明是最好的教程,为什么还要花很多时间找一些奇奇怪怪的方法,而且这些方法还不一定能从根本上解决问题。 未来 我也有梦想,想去大公司掌握一些新技术,规范自己的开发流程,有朝一日能做上IT公司高管。深圳是个令程序员向往的城市,当然也包括笔者。对于笔者有多向往呢?当我看到深圳的宣传片,就联想到了GOOGLE/APPLE/FACEBOOK等等这些众多的硅谷明星企业,或许深圳在我眼中就是中国的“硅谷”吧,着实令人着迷。对比了一下所在城市和深圳众公司的技术要求,发现自己技术似乎还不足以入职在深圳的大企业,无他,只能在工作之余抽更多的时间去提升自己的技术能力。生于忧患,死于安乐。

Continue reading...

(二)Mybatis架构原理

架构设计 Mybatis的功能架构分为三层: API结构 提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层接收到调用请求就会调用数据处理层来完成具体的数据处理。 Mybatis和数据库的交互有两种方式:a. 使用传统的MyBatis提供的API;b. 使用Mapper代理的方式。 数据处理层 负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。 基础支撑层 负责最基础的功能支撑、包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。 主要构建及其相互关系 构件 描述 SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库层删改查。 Executor MyBatis执行器,是MyBatis调度的核心,负责SQL语句的生成和查询缓存的维护。 StatementHandler 封装了JDBC Statement操作,负责对JDBC Statement的操作,如设置参数、将Statement结果集转换为List集合。 ParameterHandler 负责对用户传递的参数转换成JDBC Statement所需要的参数。 ResultSetHandler...

Continue reading...

(一)自定义持久层设计思路

笔者开始对Mybaits源码进行分析、学习,并记录下学习的历程,既对自己的成长有帮助,也对有可能看到本文的读者起到帮助。 对直接使用JDBC链接数据库的读者或许知道,要操作数据库需要以下几部分(相关JDBC操作数据库代码可自行Google/Baidu): 指定驱动类; 指定数据库链接地址、数据库登陆账号及密码; SQL语句; 预执行SQL语句(PrepareStatement); 设置参数及执行; 封装返回结果集。 使用持久层框架可以在业务系统简化以上步骤的代码,将链接的创建、销毁;SQL的执行与结果封装等这些“模版类”代码交由持久层负责,程序员只需要关注业务代码(SQL)即可。其中1与2步骤交由业务系统指定,3-6由持久层框架本身处理。 项目工程(业务系统) 业务系统引入自定义持久层的Jar包,并提供Jar包所需要的两种配置信息: 1. 数据库配置信息(自定义为:sqlMapperConfig.xml) 数据库驱动类,如:com.msyql.jdbc.Driver等; 数据库地址及账号密码; mapper.xml全路径信息(在此处定义mapper.xml全路径信息的好处是Jar包只需要配置sqlMapperConfig.xml的路径即可,方便扩展)。 2. SQL配置信息(自定义为:mapper.xml) SQL语句 参数类型 返回值类型 自定义持久层框架(Jar包) 持久层框架的本质就是对JDBC代码进行封装 步骤1:加载配置文件 创建Resources类,根据配置文件的路径,加载配置文件成字节输入流,存放至内存中。类的方法:InputStream getResourceAsStram(String...

Continue reading...

JVM运行时数据区

根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如图1所示。 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器对的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器完成。 由于JVM的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。 Java虚拟机栈 与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stack)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 本地方法栈 本地方法栈(Native Method Stacks)与虚拟机所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。 Java堆 对于Java应用程序来说,Java堆(Java Heap)是虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java世界里“几乎”所有的对象实例都在这里分配内存。书的作者在这里使用“几乎”是从实现角度来看,随着Java语言的发展,现在已经能看到些许迹象表明日后可能出现值类型的支持。 如果从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓存区(Thread Local Allocation Buffer, TLAB),以提升对象分配时的效率。不过无论从什么角度,无论如何划分,都不会改变Java堆中内存储内容的共性,无论是哪个区域,存储的都只能是对象的实例,将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存。 方法区 方法区(Method...

Continue reading...

有感:研发与开发

在毕业至今近乎三年的时间里,做过业务系统的开发,也帮助公司做过新技术的研发。从身边一些朋友的交谈中不难看出,“研发”好像相较于“开发”更加让人充满自豪感。在参与研发的前一年多我对这两词没什么认知和感想,现在通过视野的拓宽、兴趣的发掘、独立的思考,自己也有了一些看法。 一些读者或许能通过历史文章猜到,笔者在上段所述的新技术正是“区块链”。刚接触“区块链”不久,笔者也成了一个非区块链不可的人,研究底层技术,参与社区讨论,翻译白皮书,买卖“加密货币”,买矿机挖矿。除了技术研究外,韭菜该做的事情笔者应该都做齐了,更甚,还拉上了几个朋友一起“玩币”。结局:损失在自己能承受的范围内。 国内企业想要在“区块链”产业中发展,必然离不开另一种形式的“区块链”——联盟链。笔者所在的公司也必然存在这样的情况,当然选择发展何种类型的“区块链”,也是一步一步探索出来的,毕竟,公司在最初没有一个同事对区块链有着完整的认识。 着手研究“区块链”一年后,带着新技术做了DEMO,也做了两三个上线的案例。回过头总结发现,其实框架上是否加入区块链对项目的影响不大,甚至不用可能还会更方便一些。那为什么会用?中间当然有商业的因素。从技术角度上来想,也许一项新技术的盛行会经历这样一段尴尬期,一段“难落地”的尴尬期?笔者见识不广,猜测而已。 “开发”这词就相对来说更贴近生活一些,更多一些“烟火气”。这类业务系统更能为人们带来生活上的便利。笔者因为一些大赛,新认识的程序员朋友,生活上的一些经历。对软件开发有了一些变化,动力源于兴趣的比例变多了。于是开始用代码帮助身边的朋友解决一些生活上的问题(或者说是便利化吧)。曾经跟身边一些程序员朋友说“开发源于兴趣”的时候并没有什么共鸣,可能想法不同吧,无谓勉强。 个人感觉,“研发”除了技术层面的难以外,可能也难在短时间找到“落地”特别合适的项目吧。无论“研发”或“开发”,能真正帮助到人们减轻生活的负担,这才是笔者敲代码动力的源泉吧。如果这些代码也能让读者过上小资生活,那可真是太好了。

Continue reading...

Redis之应用解决方案记录

本文内容仅为个人记录,并未记录书中完整内容。更详细的内容请查看本文引用的书籍,书名请查看文末。 1. 分布式锁 分布式应用进行逻辑处理经常会遇到并发问题。一个操作要修改用户的状态,修改状态需要先读出用户的状态,在内存里进行修改,改完了再存回去。 如果这样的操作同时进行,就会出现并发 问题,因为“读取”和“保存状态”这两个操作不是原子操作。这个时候就要使用到分布式锁来限制程序的并发执行 1.1 超时问题 Redis的分布式锁不能解决超时问题,如果在加锁和释放锁之间的逻辑执行太长,以至于超出了锁的限制,就会出现问题。为了避免这个问题,Redis分布式锁不要用于较长时间的任务。如果真的偶尔出现了问题,造成的数据小错乱可能需要人工介入解决。 有一个稍微安全一点的方案是匹配随机参数value和删除key,但这不是一个原子操作,Redis也没提供类似的原子操作指令,这时就需要用Lua脚本处理。但这也不是一个完美的方案,只是相对安全一点,因为如果真的超时了,当前线程逻辑没有执行完,其他线程也会乘虚而入。 2. 延时队列 Rabbitmq和Kafka这两个都是专业的消息队列中间件,特性之多超出了大多数人的理解能力。对于那些只有一组消费者的消息队列,使用Redis可以非常轻松地搞定,需要注意,Redis不是专业的消息队列,没有非常多的高级特性,没有ack保证,如果对消息的可靠性有着极高要求,那么他就不适用。 2.1 异步消息队列 Redis的list常用来作为异步消息队列使用,用rpush和lpush操作入队列,用lpop和rpop操作出队列。 2.2 队列空了怎么办? 如果队列空了,客户端就会陷入pop的死循环,不停pop,没有数据。空轮询不但拉高客户端CPU消耗,Redis的QPS也会被拉高。有以下两种种解决办法。 使用sleep来解决问题,睡个1S就可以了。不但客户端CPU消耗能降下来,Redis的QPS也能降下来; 如果有多个消费者,上面的就会导致消息延迟增大。使用阻塞读就是更好的解决方案,阻塞读在队列没数据时会立即进入休眠状态,一旦数据进来,就会立即醒来,消息的延迟几乎为零。blpop/brpop替代lpop/rpop。 阻塞读有可能造成空闲连接问题,所以编写客户端消费者时,如果捕获到异常,还要重试。 2.3 锁冲突处理 客户端在处理请求加锁没成功怎么办?一般有以下三种策略来处理加锁失败。 直接抛出异常,通知客户稍后重试;...

Continue reading...

区块链服务网络BSN方案分享

最近笔者参加了BSN这一项赛事,随着赛事的完毕,现将此次个人的作品方案出来。由于参赛的前提是参赛者必须同意其方案可以向公众无偿展示,笔者就无谓在博客分享该方案。但其版权和署名权均归原作者(即笔者)所有,欢迎转载,但请告知。 此次赛事无须敲代码,只需写业务流程、软件架构等模块的方案。笔者感觉更适合架构师,或者产品经理参加此次赛事。笔者自认还没达到架构师的水平,但还是想将内心的想法表达出来,就将思路以相对简单的文档表达出来并提交了,全文如下: 《基于地图软件的链改方案》 2020/2/14Robin 前言 在最终敲定该方案前,笔者也曾构思过其它方案。或是因业务不熟悉且流程复杂,又或是因不能实际解决问题,最终没被笔者采纳。但这并不代表本方案完美无瑕,在笔者看来该方案存在的最大问题就是商业合作,似乎各方不能直接从中获得利益,但从“老百姓”的角度来看,实属一件惠民之事。 该想法曾在去年和公司的业务提起,无奈业务对“目前看不到利益”的事情不感兴趣,也因为公司力量有限,该想法一直被埋在心底。本方案在“现状与痛点”的章节从软件使用者的角度提出疑问及期待,利益方的盈利方式思考甚少。 曾经笔者也是“唯链不可”的人,经过一段时间的洗涤与沉淀,现在笔者认为能解决大众生活问题的应用才是好应用。也正逢此次机会,将我个人的想法描述出来,或许所述机构能从本方案中看到笔者所看不到的利益点,次之,有眼光长远的读者能在此之上添砖加瓦,普罗大众。 归根结底,想将区块链用在真正解决问题之处。至于其中的利益分配,就转由更专业的人士去分析罢。 现状及痛点 随着现代人民的生活水平逐渐提高,各式各样的娱乐消费场所也越开越多。对于绝大多数消费者来说,去一趟从未涉足过的场所,几乎都会使用手机地图导航。如:高德地图、百度地图、腾讯地图等。而现在负责各地图软件营运的公司处于相互竞争的状态,地标数据都存自身的数据库中,导致出现同一处场所在A地图软件中出现而B地图软件中没有出现的情况。 遇此情况使用者还需下载另一个地图软件,若另一个地图软件也缺少该地标信息,可能还需要再重复下载。笔者站在使用者角度来思考,营运各地图软件的公司应该基于这些齐全的地标信息去完善自身提供的服务、功能,提升自身软件的服务价值,从而获得更多的盈利。 笔者从两个不同的地图软件中截图,由图可见地图软件B没有“灯塔咖啡”这个地标。 各地图软件的技术实现细节无法深入调研,只能大致画出如上图所示的三层结构,各方的数据存在各自的数据库中,没有进行数据交换。 地图软件营运各方搭建联盟链节点,形成一条共享地图标点信息的联盟链。审核通过后的标点信息入链。 标点信息包括:1. 地址;2. 经纬度;3. 联系电话(若有);4. 商铺(场所)名称等。 改造前后的对比 改造前 每个地图软件或多或少都会缺失某些场所标点,这些缺失的标点往往能在另一个地图软件中找到。给用户的使用上带来不便,习惯了某一地图软件的用户可能为了找一处标点而下载另一个地图软件。即便自身的服务(例如导航、实景地图等)做得很好,也可能因为标点的缺失而流失用户; 各地图软件营运方可能因缺少的这些标点的信息,无法做到精准推荐或者算法参数的缺失; 若政府部门有获取齐全地标的需求,按照现有的系统,需要分别调取各地图软件营运方的数据库所有标点信息,流程上较复杂,且标点信息重复率极高,需要进行筛选后才能得知哪些标点不是各方数据库都存在。 改造后...

Continue reading...

Shell的内建命令

上周笔者在使用Linux服务器时频繁遇到以下问题,大概能猜测到问题的原因,也知道如何解决。可一直无法找到相对官方和详细的解释。可最近书上看到了详细的说明,便记录一下。 问题: 在Windows上使用Putty连接Linux云服务器,输入命令 $ export PATH=$PATH:/opt/gradle-5.2/bin 按下回车后gradle命令能正常使用,但将Putty关闭后再打开,服务器会提示找不到gradle命令。再次输入以上命令仅能暂时解决问题,除非修改~/.bashrc(针对当前登录用户)或者/etc/profile(针对所有用户)。 原因: export属于shell的内建命令,像cd和exit命令都内建与bash shell。可以用过type命令来了解某个命令是否是内建的。 $ type cdcd is a shell builtin $ type exportexport is a shell builtin 使用内建命令设置的环境变量仅在当前的shell进程中才有效。 放在笔者的例子上,简单点来说,使用内建命令所产生的作用范围仅仅在当前的Putty的图形输入框中。当关掉当前Putty图形输入框,内建命令所产生的“效果”就会消失。...

Continue reading...