2016年3月6日星期日

Markdown

Markdown作为流行的标记语言,已经火的一塌糊涂了,你只顾写你的,反正标记就那些,然后剩下的交给转化软件和CSS去格式化吧……
GitHub上的READMD.md足以证明它火的程度。

The key design goal is readability 
Markdown理念:

  1. 简单写、容易读
  2. 字符化
  3. 极简主义

Markdown原理:

  1. 标记语言——by Author(人)
  2. 转换程序——by Markdown Program(各种Markdown程序)
  3. 最终呈现——by Viewer Program for Humers(HTML/pdf/txt/RTF)

Markdown展示:(by Ulysses)



不同的Markdown系统Markdown标记也有所区别,不过都大同小异,找一个适合自己的即可。

Markdown收益:

其实HTML也是标记语言有木有,不过因为它被掺杂了太多的样式、脚本,显得不太纯粹了,而且是基于xml的语言,天生冗余就会比较多,如果你打算在写文章的时候自行html,那你不仅要学习html还要花时间在每一次敲击标记这件事上。
Markdown则简单地多,它尽量只表达最简洁的那些样式,剩下的事情,交给程序去做吧。
所以当你开始写它的时候,请不要回忆那些生成的效果,标题就是一个#,段落就是两个##,请不要像我一样,把两个星号表达为**粗体**,而应该叫它为强调,至于你用粗体来表达还是用斜体来表达强调这件事,都是后面的事情了。

Markdown与可视化编辑:

有了上一节的铺垫这一节就容易多了,Markdown强调的是事情本身,作者认为重要的内容,就打上**标记,中国的读者,喜欢用粗体表达重要,美国的读者可能喜欢用斜体表达重要,没关系,作者不用为不同的用户写两遍。
而可视化编辑器,不论是在线编辑器还是Microsoft Word在你看到它的杰作之时它就已经定型了。

但是,就单纯从方便的角度,则是仁者见仁的,毕竟我们还是喜欢直观的东西,但这丝毫不影响Markdown成为一种选择。

Markdown延伸玩法:



在此引入两篇文章:

  1. 一篇导引文章,简要讲述了一些简单的标记:http://markdowntutorial.com
  2. 一篇非常好的文章,不仅讲了Markdown的来龙去脉,还说清楚了它的工作原理:http://lifehacker.com/5943320/what-is-markdown-and-why-is-it-better-for-my-to-do-lists-and-notes
引用文章里面的一个Web Markdown系统,供大家练习:http://hashify.me/




2016年3月4日星期五

如何编译MongoDB?

本文将在Linux环境下编译Mongodb。
您可以选择已经编译好的版本直接使用,也可以尝试自己编译。https://www.mongodb.org/downloads#production


动手开始:

1、Linux,本文选择Ubuntu 14.04 LTS 64bit,下载地址:

2、包依赖:编译器 gcc g++ clang 安装方式:

# sudo apt-get install gcc (4.8.2以上版本)
# sudo apt-get install g++ (4.8.2以上版本)
# sudo apt-get install clang(3.4以上版本)

3、包依赖:python (2.7以上版本) 安装方式:

# sudo apt-get install python

4、包依赖:scons (2.3以上版本) 安装方式:

# sudo apt-get install scons
5、包依赖

# sudo apt-get install aptitude
# aptitude install scons build-essential
# aptitude install libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev

6、源代码:从GitHub上面下载:https://github.com/mongodb/mongo 直接选择一个分支,右侧Download Zip,解压缩到目录:

# mkdir mongodb-master-src
# unzip mongodb-master.zip mongodb-master-src/
# cd mongodb-master-src/

7、新建一个 version.json 文件在 mongodb-master-src/ 目录下:在大部分能搜索到的文档中,大家都是直接下载好后就编译,但是会报一个scons错误,原因就是因为缺少这个文件。

# gedit version.json
然后输入以下内容后保存: 
{
    "version": "0.0.1-fake-"
}

8、编译源代码:
# sudo scons all -j 4
这里-j 4 是指你所使用的CPU核数。也可以直接:
# sudo scons all  
或者仅
# sudo scons mongod
# sudo scons mongo
# sudo scons mongos

9、编译后验证,执行下面语句,你将看到版本提示信息。

# ./mongod --version

10、编译后配置,新建相关目录及配置文件
# mkdir mongodb_sample
# cd  mongodb_sample/
# mkdir bin
# mkdir data
# mkdir log
# mkdir conf
# cd conf
# gedit mongod.conf
在打开的端口内输入:
port = 12345
dbpath = data
logpath = log/mongod.log
fork = true  
其中:port代表访问该数据库的端口号,fork表示是一个后台进程。

11、复制编译好的文件到bin目录
# cp ../mongod mongodb_sample/bin/

12、启动mongod:
# cd mongodb_sample/bin/
# ./mongod -f conf/mongod.conf
13、检查log和data目录将看到文件夹内有新的文件。
14、停止mongod,这里因为没有连接到mongod服务器,所以直接使用kill的方式进行关闭,关闭的时候,不使用kill -9,可以使用kill -15:

先查找进程ID:
# ps -A | grep mongod
然后
# kill 32759
关于kill命令后面的参数,详见:https://en.wikipedia.org/wiki/Unix_signal#SIGTERM

2016年2月29日星期一

Hadoop技术内幕——深入解析MapReduce架构设计与实现原理 读书笔记(1)


Hadoop 1.0.0 源代码阅读,需要先安装以下软件。
很可惜,即便一切照做了,导入的文件也各种报错。

1、Java 1.6.0下载
http://www.oracle.com/technetwork/java/javase/archive-139210.html

2、Apache Ant 1.6.0下载
http://archive.apache.org/dist/ant/binaries/
http://archive.apache.org/dist/ant/binaries/apache-ant-1.6.0-bin.zip

3、Eclipse下载
http://www.eclipse.org/downloads/packages/release/Galileo/SR2
http://archive.eclipse.org/technology/epp/downloads/release/galileo/SR2/eclipse-jee-galileo-SR2-linux-gtk-x86_64.tar.gz

4、Hadoop 1.0源代码
http://svn.apache.org/repos/asf/hadoop/common/branches/
http://svn.apache.org/repos/asf/hadoop/common/branches/branch-1/
https://archive.apache.org/dist/hadoop/common/hadoop-1.0.0/
https://github.com/apache/hadoop/tree/branch-1

2016年2月15日星期一

Google的Bigtable学习笔记(不保证正确性)

Google的Bigtable学习笔记(不保证正确性)
1、首先是一个列式存储的简单数据模型的数据库,它比键值对模型/文档模型NoSQL数据库复杂点(也就更强一点)。
2、它的分布式存储性能依靠于GFS也就对单机房网络有硬性指标。
3、它同时提供了相对均衡的顺序读写操作,也就更适用于这样的应用。
4、保证SSTable不变的结构简化了读写冲突所产生的问题复杂性。同时允许不同的tablet共享一个SSTable。
5、memtable的设计减少了大量的读写冲突,双线程+序列允许归并写入,鉴于较小概率的读恢复操作,major compaction在排序时候借助写时候留存的序号进行去重,简化了写操作。
6、高级别的缓存针对访问相同数据进行的缓存服务比较容易被想到,但是块级别的缓存解决了顺序读的读写效率,是值得学习的。
7、因为row key是依照字典序进行排序的,所以在应用级别对row key的选择就是设计的一个重心。
8、字典序的设计对跨行更新以及分布式事务都提出了挑战,但是这个系统并不适用于解决类似的问题。
9、提供了无限的列结构以及column families,是它强于键值对模型/文档模型NoSQL数据库的地方,等价于自建了各种索引。也就是所谓的半结构化数据。
10、Tablets服务器对于主服务器的依赖较低,因为主服务器仅与有限的Tablets服务器进行通信,只负责解决它们的生存问题,而不用解决直接的来自于用户的请求。
11、利用Chubby进行分布式锁机制,使用了文件句柄的冲突检测来实现对于分布式服务器的管理,并配合了主服务器对Tablets的心跳检测,实现了完整的检测,在加上自杀和他杀技术的使用,使得整套系统得到了较高的可靠性。
12、两段式压缩对于类似于不同的时间点对相类似的数据进行存储后的压缩能够做到较好的压缩比,因为内容重复度比较高。

http://research.google.com/archive/bigtable-osdi06.pdf

2016年1月27日星期三

软件开发到底是怎么一回事呢?

人生得一良友不易,友人是做数据库DBA(运维方向)出生,对软件开发算是没有什么经验,但是最近手头却有点儿事让它对软件这件事开始有了兴趣。于是就问我这个问题。我呢,水平很差,这么大的标题丢过来,怎么回答呢?好在友人给明确了方向:
代码管理,版本控制,补丁管理,架构设计,模块划分,接口设计,报错编码制定,日志设计,测试方法,安全管控,性能规划
然后我就根据这些,作答如下,既然写了这么多,就拿出来和大家分享。

1、代码管理,版本控制,补丁管理
对于单一产品的公司,其实问题就是各种迭代和这些迭代的管理。
首先是坐下来讨论一下影响我们代码变化的因素是什么?需求、bug,计划内、计划外?
传统的软件管理,通常会把需求分成很多期,然后针对每一期制定版本计划,然后按着计划做。
但是现代软件偏向于敏捷的管理方式,用用户故事将需求分解成不同的场景,进行故事管理,然后通过迭代的方式向前,然后及时修正项目的整体目标。
回到代码管理,我有个原则,就是你不管是需求还是用户故事,在你打开你的电脑开始写的时候,就要明确你在为什么功能而coding,然后你每一次提交版本必须和你的代码库,task(一种集成在项目管理工具里面的任务,你也可以理解为excel里面的一行需求)一一对应。比如你今天就是做了一个接口,接口只完成一个功能,比如修改密码。那就写清楚你在做什么,然后和你的需求哪些相关。简单地说,就是每一次提交是一个原子提交。然后提交的时候,至少需要保证你的代码是可以编译通过的。
版本控制呢,通常需要考虑到分支的管理和标签的管理。其实我有一个保证它安全的好办法,那就是不用版本控制工具。它们不如复制粘贴/压缩包来的可靠。如果你确定一个分支要发布,首先你需要用版本工具进行分支发布,然后针对分支的补丁就在上面继续,然后适时往主分支合并。但是于此同时,请做一件事,将它们下载下来,把它压缩起来,然后放到一个文件服务器上。然后一旦出现问题,找个文本比较工具,你通常就豁然开朗了。
补丁管理这件事,刚刚也提到过了,你真对哪个版本出的问题,就在哪个分支上面去改,然后适时合并,适时当然是你在差异没那么大的时候做是最好的。
这里插一句题外话,敏捷的核心我个人认为不是在怎么说清楚用户故事,而是你要有单元测试,没有这个都是扯淡……当然其它也很重要,但是UnitTest是必要级别的。这也就是外包软件行业通常做不到敏捷的一个重要原因,因为不是那么容易做到。

2、架构设计
架构设计这可不是那么牛逼的一两句能说明白的事情,不过有几个个人认为还是比较重要的原则。
a、适度设计,其实拿捏这个度,何其难,在一个人开始看待一个问题的时候,自然就有自己的观点在里面,你的视角一定不是世界的中心,那么合理拆分就可以了,本着实用主义的精神做架构设计,通常能在成本、智力等方面都能取得一个还不错的平衡。
b、合理,其实面向对象编程最牛逼的地方就是让一段代码试图去模拟一件事的本身,这就像数据库设计里面的关系表一样,它一定要表达的是正确的关系,那么哪怕它性能上有缺陷。这些其实和什么代码可读性等都是相通的。这就是为什么大部分人都认为多线程程序会比较难,因为它通常不是人类思维。这样的合理设计通常从数据库的设计上面就开始影响你整个复杂度了。这一条通常随着架构师见识和对问题的理解程度不同,在项目进展的不同时期会有不同的体会,一开始合理的东西,在项目后期可能就不是那么回事了。
上面说的都是废话,因为不具备操作性,就是在你要做决定的时候去回想一下才有帮助。那么有什么规律可循呢?
其实通常我们都是习惯带着问题去解决它们的,比如你的性能要求很高,你要求达到一个特定的SLA,那么你在开始选择技术和框架的时候就要在这些方面都比较小心,然后用你熟悉而不是你似懂非懂的技术来解决,这样就算出问题,你至少能知道怎么去思考这个问题,而不会去怀疑那个东西不靠谱。然后就是包括所有影响这些的点,既然说的是性能问题,那么数据库、索引等都是需要考虑的,还有一些可以从业务上分开的,也可以从业务上解决,比如明明一个页面用户只想看到一个数值,但是你总是在页面上带一个大列表,而大列表刚好又查询了一个大表,那么这个页面必定有问题。

3、模块划分
模块划分其实就是你把你的功能合理分拆的过程,你能把你们家的主卧、次卧、厨房卫生间拆分开,你能搞清楚为什么电商分类里面不会把电风扇放到数码产品里面,就说明你掌握了模块划分的基本规则。这些都是纵向划分,按照领域进行细分。
我觉得你这里是不是想要知道的还包括分层管理,软件是个上下叠加的层次结构,其实从你下面跑的硬件到操作系统这一层级通常被做好了,然后就是做好你的软件的部分,所以接触你的操作系统的通常是软件公司给的各种框架,比如.net framework和java虚拟机等,然后就是那些架构框架,什么asp.net、servlet等,这些都不涉及到你的业务,通常是解决了技术层面的问题,然后你现在看到的成熟的解决方案通常都从界面开始(也许是个接口,总归和外界有个交互),然后从这一层中向下,到刚刚那层底层框架之间就需要你自己来分了。看看你是不是需要访问数据了,比如数据库,不管是sql还是nosql,总归需要去联一下了,这里多是考核你层间接口的设计能力,然后你想象你设计的接口就像插座上面的标准插口一样,上层不再关心下层的实现细节,如果下层有问题,让下层去改好了。然后一层一层往上剥离,就到了你刚刚想要做的对外的那个界面了(也许是接口)。什么三层架构什么的,也只是对这些的一个大致归类。
不过按你的思路,也许你的脑子里是个VisualStudio里面的Solution的Panel,你想知道的是一个大的解决方案中各种程序集(dll/lib)的分类方式,那么你回到你最熟悉的Windows/linux下面好了,负责网络的就是网络驱动,管它怎么实现的,我反正负责网络的,你找我就可以了。然后负责IO的,就负责IO就好了。程序集的划分差不多也就是这样的,以SSO举例,加解密我们会有单独的模块,然后做具体业务逻辑的也会有,然后一些辅助的小代码(比如查一下ip地址啊什么的),大概也就是这样一点点分出去。

4、接口设计
上面的很多思路其实在接口设计中都是相通的,其实就是职责分明,一个接口尽量完成一个原子操作,不要完成很多件事,除非你把它当作一件事来做。这个粒度的把握也需要思考清楚。比如修改密码的接口,你就不要再加入重置密码的逻辑,哪怕你背后的代码恨不得调用同一套,也需要暴露两个接口。接口之所以被设计出来,就说明它是相对稳定的,任何对接口的修改,都是一次玩命,原则,约定的功能是不可以减少的,哪怕是不合理的,这个才是接口最难的地方。就像你发布了电灯底座接口,然后全世界都在为你生产电灯,然后你说不行,圆的你不喜欢你喜欢方的,我改了哈,然后,你懂得,上街不要被人打。那么接口的设计就非常需要合理,哪怕你留下一个没有用的参数,内部你压根不用,你写死都可以,但是一定要合理,只有这样,未来使用这套接口的标准程序才不会受到影响。然后单元测试的思想就很重要了,接口永远要保证之前测试的场景在每次升级后还能正常被跑过,否则你的接口随时有可能产生涟漪反应。
5、报错编码制定,日志设计
万物归本,这件事就是你确定一个列表,然后把它吐出来的过程,Windows那么多弹错,无非也是一堆编码,出了问题到kb里面一搜就出来各种编码了。至于这个规则是按类似手机号或邮编的编码方式还是按照条形码的方案来,这个仁者见仁场景也不一样,哪怕你毫无规律地来编,它们都只是起到了一个Id的作用。
这里可能需要提到的一点,这个编码和日志设计通常都在一起,其实在你程序需要记录的时候,哪怕你觉得它八百年才会发生一次,你也要需要给人一个合法的编码和完美的解释,那么你就不至于当系统弹出“有错”的时候,你一看有十几处一样的错误。我倾向于错误始终唯一的方式。
在现代软件编程中,可以借助AOP的思路来将它们收集起来,这个思路和程序横向切片差不多,它在代码上的体现通常是,你的代码明明只是做了业务逻辑,但是它自动会帮忙记录日志,而且能告诉你到底是哪个程序第几行在什么地方干了什么。当然这个也是有代价的,就像你在水龙头上安装了过滤器,那么水流自然要小一点。
现在有nosql了,海量存储变的更方便了,然后分析这件事借助离线计算的方式,总归是能算出来的,但是记得,一定要把信息尽可能多地记录下来。

6、测试方法
传统的测试当然非常重要,什么冒烟测试、用户验收测试、回归测试、集成测试等都非常重要。
这里要提到的更多的是自动化测试,虽然我在项目中很难用到这一点,但是它的思想我非常认同,因为它是用代码来测试代码,代码是什么,是你经验的积累,你找个妹子上去点一遍,点的过程就是经验,你让妹子点20遍也许妹子能朝你踹一脚,但是代码一旦完成,只会越来越趋近精确。现在软件工程上面对类似界面点击这些都已经有了成形的工具,但是说实话国内软件业掌握的还不怎么样。当然也因为有很多不完善。
通过持续的反复测试,说白了不管是人还是机器,更多的经验和体力投入都能获得更好的效果。

7、安全管控
安全管控,现在安全组做的那些事情,包括用安全工具来扫描、找红帽组织来,其实都是基于行业经验来做到监理的角色。当然软件开发,本质还是一个智慧的事情,比如你家盖房子,你知道安装了窗户,需要有锁,而且锁必须在房子里面,不能在外面,低楼层需要安装防盗窗,防盗窗必须比一个正常的人要窄,这些都是经验。有很多现成的经验,需要在程序员开始干活之前就要掌握,其实不应该假设程序员什么都懂,其实他们很萌的。我刚开始写web的时候,那个时候没有往安全方面去想,因为之前一直做的是windows界面,不同窗口之间无所谓安全的事情,但是做web的时候,真的做了那种除了登录页面之外的页面也可以不要登录,敲个地址就能进去的low事儿,后来自己发现了,才从web的原理着手去了解了这样的问题,但是这个事情,终归是个意识和见识问题。大部分不干坏事的人不知道怎么干坏事,所以大家还是需要多学习。
然后就是一个好的基础框架,开发规范,很多公司程序员并不太了解这些,但是它们也不出轨,比如单点登录就帮他们解决了这个问题,因为架构上要求一个用户至少是登录的。
这里特别要提到接口,通常很多人做完接口就不管安全了,因为它不好测,也看不见嘛,但是这一块通常需要被重视。不过像什么WebService的标准里面都有一整套安全规范,当然除了大公司用之外,大家可能掌握的也不多。

8、性能规划
性能,是个数学问题吗?你先知道一共有多少的性能压力,你把小轱辘的轮子放在卡车下面自然是承受不了的。现在比以前好多了分布式计算让性能从单一计算机性能瓶颈上分解出来,但是分布式。。。。通常适用于可以分布式的事情。。。
其实在我们常见的场景中,无非是web性能和数据库性能,web性能现在大家都是用负载均衡来分开的,其实,很多时候傻逼的程序员干的蠢事需要服务器cpu来买单的事情也不少见。性能出问题,大多出现的问题,比如耗时的程序在工作,比如网络慢了,进行IO操作了,访问数据库了,跨边界的操作通常容易导致性能问题。比如访问内存的速度通常和访问数据库都不是一个量级的。那么在一个for循环里面访问数据库就是一个比较不合适的做法。那么一次性读取后再for也许能帮到你,当然也不是所有的场景都如此。还有就是良好的算法功底,比如一个循环的算法复杂度是O(n),而一个哈希表的算法复杂度是O(1),通常大家都不需要自己去写这些,但是选择合适的数据结构来处理问题,变得很重要。
至于你说你的服务器应该买多牛逼的,那我就不知道了,压力测出来之后,看着买能买得起的最贵的,然后调程序去吧。