渴望旅行,到处走走

如果不是室友安排的活动,恐怕很难接触到微旅行这种活动,宅久了,惰性就来了,懒得动!已经不记得多久没跟朋友一起出去玩了,那种全身心放松的感觉,最觉得可回忆的,其实还是一起跟朋友在杭州的那段时光,美好的人,美好的景,尤其是考上研之后的那种心情。

其实心里一直都渴望出去走走,看看世界的美好,很多时候缺的不是想法,而是说走就走的勇气。每天,看这个城市,行色匆匆,一张张陌生的面孔,孤独、思乡的感情油然而生,为什么此时此刻,我会出现在这个陌生的城市,行走在陌生的街,老家熟悉的小巷,屋后的树,午后门前的阳光还好吗?

这个城市到处充斥着嘈杂的引擎声,恐怕已经很难听见内心声音了;雾霾的天空,蓝天白云显得那么可爱;奔波在这个钢筋混凝土的城市,青山绿水已经变得有些遥远。大城市呆久了,厌倦了,向往平和、与世无争的世界,看看巍巍的山川,面对宁静的湖面,梳理自己复杂的内心,认识一个全新的自己。

Gitlab使用手册

Groups还是Users

对于项目namespace,一般来说,团队项目,Groups更好一些,一个组内可以添加很多项目,更符合一般团队的开发习惯,而Users更适合私人的一些项目。当然,美中不足的是,Groups中成员权限一旦确定,就不能在项目中进行修改。

分支模型

一个中心库至少包含两个分支,即master,dev分支,作为基础分支,另外还有一些辅助分支的概念,常见的有feature、hotfix、release等,另外还有tag,一般也可替代release分支。

  • 基础分支

    • master:隔夜代码,定期将dev的代码合并到master
    • dev:开发主战场,一般任何修改都要合并进来
  • 辅助分支

    • feature:用于开发独立的模块,一旦跟dev合并,一般就删除
    • hotfix:一般是用于修改bug的临时分支,命运和feature类似
    • release:用于发布稳定版本

MySQL Proxy、MySQL Cluster

主从同步

在讲Mysql-Proxy之前,首先了解下,MySQL的主从同步问题。MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器,然而,异步的缺点也是显而易见,即数据复制的延时性,但未必没有中情形都要求较高时效性。整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。因此,要实现 MySQL的复制,首先必须打开 Master 端的Binary Log功能,否则无法实现。谈到Binary Log,如果你有MySQL数据误删除的经历,一定用过Binary Log来恢复数据。

关于如何主从备份,网上资料很多,不做赘述,修改完配置记得重启服务。值得注意的是,对slave服务器配置的时候,不要将master_host等参数写进去,否则无法启动,因为MySQL5.1.7之后的版本已经不支持了,解决方案,登陆slave服务器,执行以下两条命令:

mysql>change master to master_host='master_ip',master_user='username', master_password='password';
mysql>slave start;

提示:一般应用程序都会有日志,可以通过错误日志找到错误原因,日志条目虽多,但是通过几个关键词检索,如:error,fail,crash,invalid,明显加快排错速度。

读写分离

MySQL-Proxy是MySQL自家的一个反向代理器,同类产品还有Amoeba,不过逊色很多。同Web反向代理服务器类似,MySQL-Proxy可以将SQL语句转发到后端的MySQL服务器,并且通过启动时的选项参数来指定后端的MySQL服务器,从而达到服务器的负载均衡。

博客乱象

国内博客乱象,可谓是拿来主义横行,抄袭成风,很多文章甚至是不加排版,显得毫无节操。早些时候就想写一写关于国内博客圈的这些不良风气,但拖延症作怪,一直挤到现在,才勉强决发表一些自己的看法。

好的东西,的确应该拿出来宣扬和传播,但是不加思辨的拿来即用,却弊远大于利。做技术的都对国内现状深有感慨,往往一篇技术文章,一个文章帖子,百度一搜(当然,有条件尽量还是谷歌吧,不禁让我想起了某大牛的话,身为IT人,使用百度是自甘堕落),往往有成百上千的翻版,而且雷同程度几乎100%,毫无羞耻可言。一个问题解决方案,第一个讲错了,后面的人不加验证,目测说的非常在理,转之,结果十传百,百传千,遭殃了一大帮人。

作为一名IT从业者,写文章总结知识是十分有必要,然而,内容更多的应该是一些自己挖掘的,当然,引用经典值得提倡,但也尽量避免大段落的抄来抄去。业内很多大牛都开博客,写文章,有深度和高度是一大特点,一个话题,可以做深入的挖掘,一个概念,写出自己独特的注解。 相比于早些年自己的部分文章,东拼西凑,大部分来自别人的文字,后面也就不了了之,不经细致推敲,即编造成章,漏洞频出,实在羞愧难当。

聊一聊Java中double精度去哪了(3)

接下来聊一聊精度取舍的原则,然后判断是否适合自身项目的需求。

double之所以会产生精度的丢失,最根本的因素是用于表示小数的二进制位数不够,然后做round,造成丢失。

这里我们假设小数剩余的二进制位长度为x,那么,在存储的时候,如果x位后面还有内容,将做round处理,那么到底损失或者增加了多少?这里验证下:

  1. 如果x+1二进制位为1,进位,则比原数要放大一些,假设增量t,那么t < 1/2^x,以下是证明:
    tmax = 1/2^(x+1) + 1/2^(x+2) + 1/2^(x+3) + ... + 1/2^(x+n)
    tmax - 1/2^x = 1/2^x(1-1/2-1/4-1/8...) > 0,因:1/2 + 1/4 + 1/8 + ... + 1/2^n < 1

  2. 如果x+1二进制位为0,不进位,则比原数字小一些,假设减量d, 那么t < 1/2^(x+1),证明同上。

其实,在计算过程中,只要考虑的1/2^x影响有多大即可!因为1/2^x都不会影响结果,1/2^(x+1)更不会了。

聊一聊Java中double精度去哪了(2)

继续先前的话题,double奇葩的精度。试完了C,为何不看看其他的语言,如python,毕竟基本上现在的编程语言基本采用IEEE754标准,存储方式相同,计算由CPU完成,结果为什么会不同?果然使用python得出的结论也是0.060000000000000005,不免怀疑之前C的结果。C的语句是这样的:

printf("%lf", 0.01 + 0.05);  #输出结果为0.060000。

码农的直觉告诉我,似乎有些东西少了。是精度,保留的精度不对,于是设定保留小数点后18位,因为java的输出小数点后有18位:

printf("%.18lf", 0.01 + 0.05);  #输出结果为0.060000000000000005。

这才是真相,线索越来越多,0.01+0.05这道题,可能跟语言无关,而是跟IEEE754标准有关?

这个实验当中,结果比预期的多,那么有没有比预期的少?

System.out.println(0.09 + 0.01);  #输出结果为0.09999999999999999。

但是,如果取小数点后10位以内,结果还是好的,而且一般现实也不需要那么高的精度,但是,倘若每次计算都做一次round,势必性能大打折扣!然而不做round,的确是不严谨的作法,如果是支付场景,0.09+0.01<0.1,那么这次交易就完成不了,这是绝对不能容忍的错误!

谈了现象,再谈谈原因,其实很简单,10进制的世界,对于0,1的世界的计算机来说,有点悬。

聊一聊Java中double精度去哪了(1)

前段时间,因为要测试一个刚出炉的高频策略,放实盘去跑吧,怕出岔,所以写了个简单的回测系统,跑一遍历史数据。其中有一部分是关于撮合系统,简陋了点,还算能跑得起来,几个用例下来,也没什么问题,接着增加历史数据量,居然出现了负数,简直不可能发生的事情居然出现了,虽然都是小金额的偏差,但是毕竟跟钱打交道,必须谨慎,况且现在比特币那么贵,丝毫偏差都是不允许的!

当然,后面就是苦逼的找bug,逻辑没问题,发狠的,把所有的数据都打印出来,日志一页一页没有尽头,心里发麻,硬着头皮一条条排查,人品不错,开头就发现一条异常数据,0.05+0.01=0.060000000000000005,瞬间明白,google it,才发现Java的double原来精度那么蛋疼。网上推荐BigDecimal代替double,果然不错,那就用BigDecimal替换。等所有的double都换之后,狗血的事情发生了,BigDecimal是如此的慢,以至于跑一个用例花了之前N倍的时间,怎么办,只能用一个折中的办法,数值表示仍然用double,数值计算用BigDecimal,于是乎,有了如下的一个四则运算工具类MathUtil.java

打破沙锅问到底--Java的@符号

刚接触Java变成,就经常碰到“@”这个符号,所谓的Java中的annotation。很多时候它都是跟@Override,@Deprecated,@SuppressWarnings,或者更见多识广一些,还有@Retention,@Target,@Documented,@Inherieted,但是,大多数情况下,很少会有人去过问为什么这么去写,只知道这是一种理所当然的写法,在这里推荐一篇非常详细的关于Java注解的博文Java注解annotation用法和自定义注解处理器

读完上面那篇文章,相信大家应该对Java的注解有了比较初步的认识,当然,光看别人的不行,没有自己的总结体会,等于没有学到太多。

原文中提到“自定义注解是以@interface为标志的”,那么,“注释”到底是不是一个interface呢?答案可以从官方文档中找到,“Annotation types are a form of interface”,如是写道。

抛硬币也能抛出人生大赢家

抛硬币,玩家庄家概率对半开,怎么赢,关键看下注策略。资金管理领域,有两种不得不提的策略,等价鞅与反等价鞅,从表现形式看,使用等价鞅制度的资金管理方式,在出现亏损以后,倾向于使用增加投入金额的方式进行后来的游戏。一旦获得盈利后,资金投入比例会再次回到起始水平;使用反等价鞅制度的资金管理方式,在出现亏损以后,会倾向于减少投入金额的比例进行后来的游戏;而伴随盈利的增加,也会不断增加投入资金,更多相关的内容见等价鞅和反等价鞅,写的很精彩,不做赘述。在这里,抛硬币属于古典概型,理解起来,相对简单直观。

游戏开始,你有10000块钱,资金翻倍后离场,不然一直到次数上限

等价鞅策略:

1:如果前一次赢了,本次下注金额为1元。
2:如果前一次输了,本次下注金额为之前两倍,这样做到本次赢了,能把之前输的都回本。
3:第一次玩时,认为前一次是赢的,因此,开局赌注为1元。

脱离低级趣味的写作

之前也写过一些博客,但内容终究是粘贴复制居多,几乎体现不出个人的成果,似乎是拿别人的口水吞咽了一遍,学知识,是要把知识学懂,学活,提炼出自己的观点,变成自己的积累。

看过很多,也学过很多,但真正经得起时间冲刷,能长存记忆的,不多;学了那么久的技术,看的都是别人的观点,学的都是别人的想法,很多时候,都忘了回头看一看,自己到底学到了什么。作为一个研究生,的确应该写一些自己独立思考的文字,挖掘深层次的知识。

其实现实当中可以书写的素材非常丰富,一篇博客,一纸论文,一本书,都能引出无数的话题,关键在于自己愿不愿挖掘,有没有探索的精神,这个非常重要。回忆之前的学习过程中,总能感觉自己遇到难题就撤退,很多事物浅尝辄止,泛泛而学,终究只能触及些皮毛,深度的东西,无从谈起。

每天总结一些,每周梳理一遍,很多东西,学过了,懂了,肯定会有自己的体会,写不出来,说明深度不够,似懂非懂。就好比很多人看到一条英文句子,感觉懂了,但是翻译不出来,不能用中文表达,其实,这根本就不是懂的表现,懂的只是几个单词加上自己的大概猜测,如果真的懂了,不可能翻译不出来。

聊一聊不一样的比特币找零机制

刚开始接触比特币的时候,一定很多人困惑于比特币的找零,幸好资料很多,随手从网上找了一篇,很详尽《详解比特币的找零机制》,大家可以做一个入门导读。

好了,针对原文的一些概念,这里我做一些我的理解。

原文中,

比特币钱包交易100次以上时再次交易后要重新备份钱包。

值得一提的是,这里的交易指的是支出,而不包含接收。

原文中举了一个买棒棒糖的例子,

新创建的货币金额与被销毁的货币金额是完全一样的。

这种说法其实不对,这里根本没有销毁和创建一说,无非是原地址比特币数字归零,余额赋值到新地址,正是因为原文中的说法,导致很多人以为比特币是完整不可分割。

原文中,

同时为了防止双重支付和伪造,必须确保在任何时候,新创建的货币金额与被销毁的货币金额是完全一样的。

“销毁”和“创建”金额相同,跟双重支付和伪造够不成因果关系,确认交易和防止双重支付主要是有PROOF-OF-WORK机制保证的,就是常说的PoW。

Fork me on GitHub