ydjia 2015-11-17T09:17:52+00:00 ccf.developer@gmail.com 建站总结 2014-03-15T00:00:00+00:00 ydjia http://ydjia.github.io/summary 经过2天的瞎折腾,终于把一个让自己相对满意的小站建立起来了,写个总结聊以告慰这2天被我折腾过去的时间。

github pages与jekyll

github pages是一个采用jekyll解析你提交给github的代码产生的静态网页。由于github pages采用的是jekyll作为其默认的静态网页模板引擎,我就直接顺便使用jekyll了。但事实是,对于一个没用过ruby的我,使用jekyll若进行插件开发真是煞费心力。所以建议不使用ruby的孩子们,可以尝试别的模板引擎,不然就很难自定义插件,不过这个可以弥补。那既然我使用了jekyll,我就还是给大家分享一下jekyll的使用过程。

jekyll安装与使用

安装jekyll需要首先安装ruby,所以请先安装ruby的dev包,然后再安装jekyll:

$gem install jekyll

如果你事先没有安装ruby,那么安装过程会出错。

安装完毕,试一下jekyll好不好用,在命令行输入了jekyll..人家告诉我command not found..我了个擦,这怎么能行。然后我whereis jekyll查看了一下...才发现,人家安装的是/usr/bin/jekyll2.0,好吧,你赢了,jekyll2.0输入起来多不方便啊,我就建了个软链接ln -s /usr/bin/jekyll2.0 /usr/bin/jekyll,还是用jekyll吧。

jekyll的典型目录结构是这样子滴:

|-- _config.yml
|-- _includes
|-- _plugins
|-- _layouts
|   |-- default.html
|   `-- post.html
|-- _posts
|   |-- 2014-02-18-mysql-undo-redo.md
|   `-- 2014-03-01-intern-in-baidu.md
|-- _site
`-- index.html

其中config是配置文件,includes可以写一些复用文件,以在使用的时候引用之。上一句是liquid标记语言,jekyll支持liquid,使用jekyll时候会常常用到,不会的可以看一下,灰常简单的。plugins可以加一些ruby写的插件,layout是你的模板html,posts就是你的日志内容啦。site里面是jekyll运行时跑出来的静态页面,至于index.html..小伙伴们都懂得。

jekyll这个目录结构就告诉了我们,他灰常适合来帮我们做一个博客,可以说fit well。jekyll有很多的内建变量,比如site,post,pagination啥的,具体怎么用,去官网看看~~

在建自己的站之前,可以去github上找一个你喜欢的jekyll主题,比如就可以借用我的,代码全在我的github上,大家使用的时候提我一下就好~然后再自己修改,这样比较快。我借用了别人的模板之后,在我的想法驱动下,对前端代码进行了大量修改。没办法,我也是轻微的完美主义患者。我现在是自己在看别人博客过程中,看到别人哪个地方好看了,就看他的css然后copy过来用。不过前端用开源的bootstrap也很不错,因为我copy的时候发现好多都是bootstrap里的代码T-T不过已然懒得换了。

那么建好自己的博客之后,想看看效果?很简单,在你的根目录处,执行:

$ jekyll serve

他会告诉你,在0.0.0.0:4000可以看到你网页的效果,当然,如果你写的代码有错,它就不会解析成功,去改一改吧。

github pages建立

感觉效果不错了,把它提交给github吧。首先在github上建立一个你自己的网站的repository,这个repo的名字要是username.github.com,在建立repo的时候,选择github pages。然后本地fork下来,把文件都弄进去,执行

$ git add -A
$ git commit -m "build up my blog"
$ git push

走你,然后等大概10分钟,去看看username.github.com,看看你的网页是否建立成功。其实最后它会给你定向到username.github.io上。

域名绑定

呐,看到这个域名,都不独立于github,果断的买个域名自己搞吧。国内买域名太麻烦,去国外的godaddy买吧,它支持支付宝哦。

先在domain下search一下自己的名字,看看标价,像我的名字就很少有重名,所以不太有人用,所以顶级域名才10美元。

果断买下来,等大概不到半小时吧,就能看到你的帐号下面有你注册的domain了。首先ping一下你的username.github.io,看一下ip,然后改A记录@和www指向这个ip,其他的不用可以删掉。

国外的dns解析可能会比较慢,国内有个免费的dns解析服务商,dnspod。免费注册一下,让它帮你扫一下你的域名即可。

嗯,大概就是这些,如果我还有什么想法持续更新。

]]>
无线自组织能量均衡多跳树簇路由算法设计 2014-03-14T00:00:00+00:00 ydjia http://ydjia.github.io/self-organized_network 本文是对我在github上面ECTM项目中我设计出的核心算法的介绍,ECTM是一个国家级的大学生创新训练项目,因此本文仅仅为大家提供一种思路,而且算法有很大的改进余地,故而请读者请勿转载。

ETCM项目简介

ECTM:the Environment Control of Tobacco Mellowing,中文名:基于无线传感技术的烟叶醇化过程监测研究。

项目背景

烟叶在自然醇化中对环境的要求很高,若没有控制好环境的温湿度,烟叶很容易产生霉变;据了解烟叶醇化后的损失达0.8%,一个中型卷烟厂年造成的直接经济损失达2000多万元并且还会严重影响烟叶的内外在品质。为了减少损失,许多卷烟厂花费了大量的人力物力,但是收效甚微,为了解决烟草公司的实际需求,方便智能化的管理控制烟垛的温湿度,本项目在进行了实地考察的基础上设计了自组织无线传感器网络。

研究内容

研制出了一套可灵活应用于烟草醇化过程无线温湿度监测系统。

该系统包括无线传感监测网络和上位机管理及分析软件系统两个部分:

无线传感监测网络部分包括:无线温湿度采集节点,自组织无线传感器网络协议,无线传感器网络与上位机无线数据传输模块。

上位机管理及分析软件系统包括:上位机监测数据接收、存储、拓扑显示、管理、分析功能,以及根据无线采集节点位置变化的拓扑结构自适应重构功能。

在组网协议方面,我们先认真学习研究了已有的无线传感器网络组网协议,然后总结出各个协议的优势与不足,在这基础上,我们开发出了一套适合本项目的自己的协议。

根据协议,我们在硬件方面选择了功耗较低的STM32单片机作为处理器,自行搭建硬件系统。

本文介绍的内容

本文主要介绍的内容是我负责的部分:组网协议的设计、仿真与实现。针对本项目我基于leach、SEP这些经典的无线自组织网络协议进行改进。

简单来说,Leach协议是一个簇头自选举的协议,以循环的方式随机选择簇头节点,将整个网络的能量负载平均分配到每个传感器节点中,从而达到降低网络能源消耗、提高网络整体生存时间的目的。但是leach协议的前提是所有节点都能互通,不满足我们的项目要求,而SEP协议是在leach协议的基础上,提高了高能量节点作为簇头的几率,然而SEP协议的前提也是所有节点均能互通。由于我们的节点并不是全部可见的,另外我们需要的是多级树簇网络,所以需要进行多跳路由的设计。

无线自组织多跳树簇网络

设计思路

本项目中无线节点(使用电池)主要模块由温湿度传感器,stm32微处理器以及无线射频芯片,并安放于空间中不同的位置,每个节点都需要进行温湿度数据记录,并找到一条路径将自己的数据上传给汇聚节点(使用有线电源,位置不变),汇聚节点再将数据使用gprs或者数传电台方式传输给pc终端。

如何设计出一个网络,使其能够有如下特性,便是该项目的核心问题:

  • 多跳树簇网络:由于位置关系,并不是所有节点都能够与汇聚节点通信,所以必须设计一个多跳树簇网络。
  • 网络自组织:无线节点位置有变动的可能,随着位置的变动,网络拓扑必然会随着变动,否则将可能产生功耗过大甚至数据传输失败。
  • 网络能量均衡:节点若作为路由节点,消耗能量会较大,设计网络时应尽量使节点能量均衡,以保证节点的电池寿命大致相同,从而减少更换电池的次数。

组网数据包

组网数据包的数据格式如下图 datapackage 算法描述

对于汇聚节点

组网开始(从睡眠中唤醒):

  1. 设置自己id=0,自己的网络深度为0;
  2. 监听,收到组网数据包"入网广播"(以后简称"入网广播"信令),则将该节点放入邻接表中;
  3. 等待一定时间,根据配置的第一层次网络节点最大数目N,以及节点的能量和链路强度选取最合适的前N个节点(若超时仍不够N个则选取全部),回复"主节点加入"信令;
  4. 等待节点回复"允许加入ack"信令,若超时,则抛弃该节点;
  5. 进入数据传输循环。

对于普通节点

组网开始(从睡眠中唤醒),进入组网循环:

  1. while(t<T)发送"入网广播",并监听回包:若回包为"主节点允许加入"信令,则直接进入4,其他回包,则将回包节点放入邻接表;接受"入网广播",回复"入网广播ack";
  2. 开始入网,从网络深度为0开始,选取链路强度最大值作为自己的父节点,发送"请求加入你"信令;若没有则网络深度加一继续寻找;
  3. 收"允许加入"包,设置该包主人为父节点,网络深度为其主人网络深度+1,返回"允许加入ack",退出组网循环,进入数据传输循环;

数据传输循环:

  1. 仍然需要接受组网数据包,相应的包处理如组网循环一样;
  2. 接受(子节点)数据包,子节点数据包转发给自己父节点;
  3. 自己有数据上传时,发送数据包给父节点。

ydjia原创,谢绝转载

]]>
百度实习总结 2014-03-01T00:00:00+00:00 ydjia http://ydjia.github.io/intern-in-baidu 转眼间半年过去了,在百度实习了这半年,收获很多。但是仅仅过了半年让我回忆实习初期干了什么,都已经有些想不起来了,让我意识到总结这次实习的重要性了。把这次实习经历总结记录下来,可以为自己,也为看到这篇文章的人提供一些积极的借鉴。

实习求职

实习求职,十分推荐的门路是各大高校论坛,我就是在本校论坛实习兼职版中找到的百度开发测试实习生内推信息,投得简历,并最终获得实习的offer。

更早些的时候我也上大街网投过简历,投了几家公司,等了很久都没有消息。事实证明,内推比自己找要靠谱的多,在大街网上基本上所有的简历最终都石沉大海杳无音信,而内推相比而言有如下好处:

  1. 相当于绿色通道:不需要经过笔试,直接进入面试。在一天内直接面完两轮技术面,就可以回学校等信了。
  2. 效率高:我投简历的一周内收到了面试通知。面试之后第二天offer就发了出来,效率十分高。

由于我受益于内推,所以实习之后我也积极内推,想给有实习想法无门路的同学一些帮助。亲自感受了面试以及内推之后,我发现面试结果其实是在当天就可以确定你是pass或者fail。也就是说如果你通过了,第二天boss就可以跟hr说,这个人我要了,发offer吧。而你fail之后,除非你邮件询问帮你内推的人,他再帮你问boss你的面试结果,不然你死等也不会邮件的,亦即默拒。

面试经验

由于实习offer来的太快,或者说幸福来的太突然..我整个求职过程,收到过3个面试通知,进行过两次面试。

第一次就是百度测试开发实习生,面试之前准备了3天:

  1. 突击了1天算法;
  2. 网上有非常翔实的百度测试开发实习生面试资料 ,看了1天;
  3. 程序设计语言基础知识面试题,看了1天。

面试第一轮面试官就根据我简历上有的东西提一些问题,并进行展开讨论,讨论的过程夹杂着程序设计基础知识。面试官面试的过程中给我说,非常鄙视笔试卷子上那些难死人的算法题,因为大部分码农在实际工作中根本用不到,所以,第一面,根本就没问我算法题,顺利通过。

面试第二轮就不是那么轻松了,上来就是一道算法题,不过难度不大,在纸上写出来给面试官看即可,同时还有分析时间空间复杂度。然后就是各种程序设计基础,最后还面试了测试思维——经典的怎么去测试一个电梯。最后面试官问我,你还有什么问题没有。这可以说是我第一次求职面试,我第一次遇到这个问题,真的不知道怎么说,我很脑残的问了两个问题:1.结果什么时候能给?2.这次面试为啥这么简单...

很感谢,他们没有因为我这脑残的问题拒绝了我。事实是,这两个面试官,在我入职以后都是同事,一个是我的导师,一个是我的boss。

第二次面试表现非常糟糕,投递的是百度个性化推荐部的开发实习。问了我很多大数据处理的问题,我真的没接触过,答得一塌糊涂。算是长经验吧。

工作收获

在技术能力方面,我的收获是巨大的:

  1. 学会了linux和vim。进行这次实习之前,我曾看过几页鸟哥的linux私房菜,也安装过ubantu作为我的第二系统,但是之后从来都是进入windows..但是这次实习让我很快学会了linux。因为天天在用,所以学的很快。vim这个好东西,可以让人彻底脱离鼠标编代码,是非常强大的编辑器。
  2. 学习了php和zend framwork。我所在的项目组是百度商桥,项目web部分使用的是php。不过作为一个脚本语言,学习起来相对容易很多,并且调试起来要比c++这种编译型语言方便多了。除此之外,我还采用zend framework开发了一个机器管理平台,为了标明某个机器现在谁在用,以及自动化进行测试环境的部署。
  3. 开阔了视野。商桥项目的架构很复杂,但是所用的很多东西都是开源的一些软件,将他们组合在一起就能产生巨大的作用。比如使用的关系型数据库mysql,非关系型数据库mongodb,redis,还有memcached,他们一起构成了底层的数据服务。
  4. 此外还实现了hadoop大数据处理的一个实例(其实就是一个wordcount);学习了基于百度商桥产品的各种测试方式,如回归测试,压力测试;另外还经常就代码与开发人员讨论,曾参与多次code review并给出意见。

其他软实力方面,也是实习相比于在学校做项目所具有的优势:

  1. 体验上班族生活,每天乘坐公交地铁上下班,每天总结自己的测试工作,每周总结自己的所有工作;
  2. 锻炼学习能力,商桥是一个很复杂的系统,在一周或者两周之内就要上手进行测试,对学习能力有着很高的要求;
  3. 感受加班,有的时候测试任务很繁重,若不测试完成不了,之后的上线进度就会受到影响,因此时常需要加班。另外,qa也需要跟进上线流程,而上线不免会对服务产生影响,经常于晚上进行;
  4. 接触互联网产品的基本开发流程。我接触到百度商桥时,它已然是个成熟的产品了,处于迭代开发的阶段,让我对敏捷有了一定的了解。每个项目都是PM依据客户需求或者RD依据技术需求产生的,最后交由我们进行测试。整个项目开发流程大致包括了如下几个阶段:pm需求设计——需求评审——rd详细设计——详设评审——rd进行开发及自测——code review——提交测试——qa测试——验收——上线。

企业文化

百度的核心价值观是,“简单可依赖”,印在每张工卡后面。其实实习过程中对这个价值观的理解并不深刻,但我感受的很深刻的是,公司的“同学文化”,有一瞬间,让我觉得,这个公司就如同一个学校一样,大家的称呼(主要是在邮件中体现)都是同学,以及同学们。

项目组关系很融洽,没有什么所谓的同事间的勾心斗角什么的,也或许作为实习生还接触不到勾心斗角的层次,不管怎么都觉得在这里工作很舒适。每天和组里的人一起吃饭,不过半个月就可以与组员建立起很好的关系,这对工作效率有很积极的影响。

工作过程中,很多时间并不是自己闷声写代码,而是需要互相交流。pm,rd(fe)和qa,三方之间,需要很多的合作,才能最终将一个项目完成,并成功上线,提供更优质的服务。

不过大公司也有其不太好的地方,不同组之间的合作,有的时候相对困难,需要经常push才行。还有多方联调时,也有死活不愿意担责任的情况。

总而言之,作为实习生的我,还是很欣赏这样的工作环境,当然我这只是管中窥豹,不能知其全貌。

自身不足

我在去实习之前,曾下决心要将实习期间接触的代码都研读一遍。但是真正实习开始了之后,除了较为易懂的php代码读了较多之外,c++的代码读的很少。自己还是没有足够的坚持和毅力。尤其实习后期,十分松懈...

总结

总而言之,这次长达6个月的实习,是我本科学习中很重要的一次经历。这次经历,对我的技术能力有较大提高,也让我接触到了企业文化和互联网产品的生产流程。

最后希望读到这篇文章的人也能从中受益。

]]>
mysql_Innodb的undo_log和redo_log 2014-02-18T00:00:00+00:00 ydjia http://ydjia.github.io/mysql-undo-redo 众所周知,mysql支持多种存储引擎,现在常用的是MyISAM和InnoDB。MyISAM相对简单,但不支持事务,而InnoDB是事务安全型的。而InnoDB的事务处理离不开undo_log和redo_Log。

mysql innodb存储引擎

下面简单的介绍一下innodb的存储引擎

内存缓冲池

buffer pool 如果mysql不用内存缓冲池,每次读写数据时,都需要访问磁盘,必定会大大增加I/O请求,导致效率低下。所以Innodb引擎在读写数据时,把相应的数据和索引载入到内存中的缓冲池(buffer pool)中,一定程度的提高了数据读写的速度。

buffer pool:占最大块内存,用来存放各种数据的缓存包括有索引页、数据页、undo页、插入缓冲、自适应哈希索引、innodb存储的锁信息、数据字典信息等。工作方式总是将数据库文件按页(每页16k)读取到缓冲池,然后按最近最少使用(lru)的算法来保留在缓冲池中的缓存数据。如果数据库文件需要修改,总是首先修改在缓存池中的页(发生修改后即为脏页dirty page),然后再按照一定的频率将缓冲池的脏页刷新到文件。

表空间

表空间可看做是InnoDB存储引擎逻辑结构的最高层。 表空间文件:InnoDB默认的表空间文件为ibdata1。

  • 段:表空间由各个段组成,常见的段有数据段、索引段、回滚段(undo log段)等。

  • 区:由64个连续的页组成,每个页大小为16kb,即每个区大小为1MB。

  • 页:每页16kb,且不能更改。常见的页类型有:数据页、Undo页、系统页、事务数据页、插入缓冲位图页、插入缓冲空闲列表页、未压缩的二进制大对象页、压缩的二进制大对象页。

    redo log 和undo log

    为了满足事务的持久性,防止buffer pool数据丢失,innodb引入了redo log。为了满足事务的原子性,innodb引入了undo log。

redo log

redo log就是保存执行的SQL语句到一个指定的Log文件,当mysql执行数据恢复时,重新执行redo log记录的SQL操作即可。引入buffer pool会导致更新的数据不会实时持久化到磁盘,当系统崩溃时,虽然buffer pool中的数据丢失,数据没有持久化,但是系统可以根据Redo Log的内容,将所有数据恢复到最新的状态。redo log在磁盘上作为一个独立的文件存在。默认情况下会有两个文件,名称分别为 ib_logfile0和ib_logfile1。

参数innodb_log_file_size指定了redo log的大小;innodb_log_file_in_group指定了redo log的数量,默认为2; innodb_log_group_home_dir指定了redo log所在路径。

innodb_additional_mem_pool_size = 100M
innodb_buffer_pool_size = 128M
innodb_data_home_dir = /home/mysql/local/mysql/var
innodb_data_file_path = ibdata1:1G:autoextend
innodb_file_io_threads = 4
innodb_thread_concurrency = 16
innodb_flush_log_at_trx_commit = 1

innodb_log_buffer_size = 8M
innodb_log_file_size = 128M
innodb_log_file_in_group = 2
innodb_log_group_home_dir = /home/mysql/local/mysql/var

undo log

为了满足事务的原子性,在操作任何数据之前,首先将数据备份到Undo Log,然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。与redo log不同的是,磁盘上不存在单独的undo log文件,它存放在数据库内部的一个特殊段(segment)中,这称为undo段(undo segment),undo段位于共享表空间内。

Innodb为每行记录都实现了三个隐藏字段:

  • 6字节的事务ID(DB_TRX_ID)
  • 7字节的回滚指针(DB_ROLL_PTR)
  • 隐藏的ID

redo log的记录内容

undo log和 redo log本身是分开的。innodb的undo log是记录在数据文件(ibd)中的,而且innodb将undo log的内容看作是数据,因此对undo log本身的操作(如向undo log中插入一条undo记录等),都会记录redo log。undo log可以不必立即持久化到磁盘上。即便丢失了,也可以通过redo log将其恢复。 因此当插入一条记录时:

  1. 向undo log中插入一条undo log记录。
  2. 向redo log中插入一条”插入undo log记录“的redo log记录。
  3. 插入数据。
  4. 向redo log中插入一条”insert”的redo log记录。

redo log的io性能

为了保证Redo Log能够有比较好的IO性能,InnoDB 的 Redo Log的设计有以下几个特点:

  1. 尽量保持Redo Log存储在一段连续的空间上。因此在系统第一次启动时就会将日志文件的空间完全分配。以顺序追加的方式记录Redo Log。
  2. 批量写入日志。日志并不是直接写入文件,而是先写入redo log buffer,然后每秒钟将buffer中数据一并写入磁盘
  3. 并发的事务共享Redo Log的存储空间,它们的Redo Log按语句的执行顺序,依次交替的记录在一起,以减少日志占用的空间。
  4. Redo Log上只进行顺序追加的操作,当一个事务需要回滚时,它的Redo Log记录也不会从Redo Log中删除掉

redo & undo log的作用

  • 数据持久化

    buffer pool中维护一个按脏页修改先后顺序排列的链表,叫flush_list。根据flush_list中页的顺序刷数据到持久存储。按页面最早一次被修改的顺序排列。 正常情况下,dirty page什么时候flush到磁盘上呢?

    1. 当redo空间占满时,将会将部分dirty page flush到disk上,然后释放部分redo log。
    2. 当需要在Buffer pool分配一个page,但是已经满了,这时候必须 flush dirty pages to disk。一般地,可以通过启动参数 innodb_max_dirty_pages_pct控制这种情况,当buffer pool中的dirty page到达这个比例的时候,把dirty page flush到disk中。
    3. 检测到系统空闲的时候,会flush。

  • 数据恢复

    随着时间的积累,Redo Log会变的很大。如果每次都从第一条记录开始恢复,恢复的过程就会很慢,从而无法被容忍。为了减少恢复的时间,就引入了Checkpoint机制。 假设在某个时间点,所有的脏页都被刷新到了磁盘上。这个时间点之前的所有Redo Log就不需要重做了。系统记录下这个时间点时redo log的结尾位置作为checkpoint。在进行恢复时,从这个checkpoint的位置开始即可。Checkpoint点之前的日志也就不再需要了,可以被删除掉。

  • 事务回滚

    rollback1 F1~F6是某行列的名字,1~6是其对应的数据。后面三个隐含字段分别对应该行的事务号和回滚指针。假如这条数据是刚INSERT的,可以认为ID为1,其他两个字段为空。

    举例说明数据行更新以及回滚的过程:

    事务1:更改某行数据的值

    当事务1更改该行的值时,会进行如下操作:

    1. 用排他锁锁定该行
    2. 把该行修改前的值Copy到undo log,即下图中下面的行
    3. 修改当前行的值,填写事务编号,使回滚指针指向undo log中的修改前的行
    4. 记录redo log

    事务2:再次更改该行数据的值 rollback2

    与事务1相同,此时undo log中有两行记录,并且通过回滚指针连在一起。 因此,如果undo log一直不删除,则会通过当前记录的回滚指针回溯到该行创建时的初始内容。在Innodb中存在purge线程,它会查询那些比现在最老的活动事务还早的undo log,并删除它们,从而保证undo log文件不至于无限增长。

    回滚过程

    根据当前回滚指针从undo log中找出事务修改前的版本,并恢复。如果事务影响的行非常多,回滚则可能会变的效率不高。当事务行数在1000~10000之 间,Innodb效率还是非常高的。

    Innodb也会将事务回滚时的操作也记录到redo log中。回滚操作本质上也是对数据进行修改,因此回滚时对数据的操作也会记录到Redo Log中。

    一个回滚过程的redo log 看起来是这样的:

    • 记录1: <trx1, Undo log insert >
    • 记录2: <trx1, insert A…>
    • 记录3: <trx1, Undo log insert >
    • 记录4: <trx1, update B…>
    • 记录5: <trx1, Undo log insert >
    • 记录6: <trx1, delete C…>
    • 记录7: <trx1, insert C>
    • 记录8: <trx1, update B to old value>
    • 记录9: <trx1, delete A>

  • ydjia原创,转载请注明出处

    ]]>