26度5

这是一家很奇怪的酒店,奇怪之处就在于空调。风速开到最小,吹的就越猛;温度调到26度就冷,调到27度就热。

这是一个很奇怪的地方,屋外面是最毒辣的太阳,屋里面床上的被子比我在成都的冬天盖的还要厚。盖着从成都带来的凉被,两个月后却终于证明了每天的鼻塞、喉咙痒痒是盖太少引起的。

四月份刚来时,是着实享受了一把深圳的蓝天白云,傍晚舒爽的晚风,还有沙滩、海水……很快又热又湿的夏天就来到了:上班10分钟的步行路程就足以让汗水湿透T恤,时不时的暴雨和台风又来突袭你的鞋子和裤腿儿,日晒雨打风吹程度已经赶上庄稼汉了。

在这样的环境中,忍不住怀念起成都的温和来了,但当晒伤的皮肤蜕去了,变得更黑了后,人也变得更耐热了。

有时候也试图想写点什么,今晚写写删删,想说的话,那第二主线的,都删了去,如何将我这主题戳到26度5,于是我就写了26度5.

书籍转让

因工作或兴趣购买了大量书籍,有一些没有反复阅读可能性的,转让给需要的朋友。

注:书籍均为全新,价格均为半价,图片来自豆瓣。

副标题: 企业赢之道
出版年: 2009-8
页数: 242
定价: 46.00元
ISBN: 9787100058759

 

 

作者: 乔·韦曼 (Joe Weinman)
出版社: 人民邮电出版社
副标题: 企业云计算战略与布局
出版年: 2014-7-1
页数: 364
定价: CNY 75.00
ISBN: 9787115358202

 

作者: Matthew A. Russell
出版社: 机械工业出版社
原作名: Mining the Social Web
出版年: 2012-2
页数: 301
定价: 59.00元
ISBN: 9787111369608

 

作者: [美] 马歇尔·卢森堡
出版社: 华夏出版社
原作名: Nonviolent Communication
出版年: 2009-1
页数: 190
定价: 29.00元
ISBN: 9787508051000

 

作者: 托比尔斯·哈沃斯
出版社: 北京理工大学出版社
出版年: 2014-7-15
页数: 400
定价: CNY 68.00
装帧: 精装
ISBN: 9787564091392

 

作者: 张俊林
出版社: 电子工业出版社
副标题: 架构与算法
出版年: 2014-9
页数: 404
定价: 69.00元
ISBN: 9787121241536

在约束与机会中权衡

61GfmFxLh1L在我看来,经济学应该是当代人人都应该掌握的基础知识,现推荐一本《斯坦福极简经济学:如何果断地权衡利益得失》,比之前那本《经济学的思维方式》更容易入门。

经济学的三个基本问题是:

1. 社会应该生产什么?
2. 应该如何生产?
3. 谁来消费所生产的东西?

比较有启发性的内容包括:

做自己最适合的事,就有更好的生产力:在经济学教科书里,我们称之为比较优势。前段时间和几个创业的朋友聚会,发现创业起步者,尤其是靠项目盈利者,有一个最大的误区就在于复制客户或上游链条企业的模式,不少行业级的大企业也正在步入同样的误区:比如设备商做运营商的事,运营商做电商的事,电商做社交的事——这本质上都变成了服务商涉足自己客户的领域,同时又要求客户买单。

这也可以理解为,中国社会依然没有很好地理解分工合作,依然没有从农业经济模式到商业经济模式发展上进行思维的转变。

在任何情况下都必须有所取舍:公平只是一个相对的词汇,企业会说,如果有更高的产品价格,他们有办法扩大生产,创造更多的就业机会;而消费者会说,他们的收入已经无法负担当下的产品价格了。管制,包括价格管制和最低工资限制,都会掩盖成本,但以最低工资为例,如果在此标准下,企业会不愿意雇佣一批技能非常低下的工人,造成了这批人的失业,但却有90%的工人因最低工资标准而在收入上受益,那政策倾向后者就是一个相对公平的取舍。

人一生积累财富的关键是什么?发现周围许多上了30岁的朋友依然处于“储蓄—消费”偏好的阶段,非常缺乏投资的眼光。记得刚毕业时身边的“高帅富”同学已经在投资土地(而非房市)了,现在更发现越早有投资经验,就越容易真正扩大财富。

在财富积累这个层面,关键是懂得利用复利——如果储蓄是为了大额消费,无疑是损失了更高的利益收入。在投资上,无论是个人投资、企业投资,投资人的风险承担能力是最关键的因素;另外一点是自己能用多少时间来投资。

主张绝对的零污染是不可能的:几十年来,高速发展中的国家如中国,环境问题非常敏感。在经济学中我们称之为“外部性”(Externality),指在直接的买家与卖家之外,有第三方直接受到这笔交易的影响。

外部性可能是正面或负面的。例如:你的邻居正在举办宴会,找来一个很吵的乐团,邻居快乐地享受音乐,乐团也开心地表演。至于你,身为局外人,可能会有两种反应:如果你喜欢这种音乐,那很棒,你可以享受一场免费的音乐会;如果不喜欢,那就不妙了,你只好忍受(或是报警)。无论是哪种情况,你的邻居和乐团之间的交易,都没有考虑到你。

染污是负外部性(Negative externality)最重要的例子。在不受约束的市场交易中,厂商只注意生产商品的私人成本,至于社会成本,是不用支付的生产成本,因此厂商不会将其纳入考虑范围。如果倒垃圾不必花一毛钱,厂商可能会制造很多垃圾;但如果必须付钱处理垃圾,那厂商自然会想办法减少垃圾。
不过问题来了,这个社会成本也好,额外增加的处理成本也好,最终都会转嫁到消费者头上。当我们享受着便宜的工业制品时,却没有考虑到,它的便宜是建立在某些方面未支付成本上面而已——比如说靠破坏不发达地区地理环境为代价的便宜的水电,比如说靠制造空气与水高污染的廉价合成化工用品塑料,等等。

什么样的收入不均程度算合理?这依然是一个可能被“公平”掩盖的问题,许多人关注公平,但人的背景、智力、知识与努力程度,本身就不是不公平的;大多数情况下,收入是被个人的产出结果衡量的。所以更好的问题是:目前的收入不均的程度是否合理?

另一个非常容易被“公平”掩盖的问题是流动性。收入分配只是一个静态分析,它告诉你在某个时间点,人们处于某个收入水平,但并未告诉你他们的发展趋势:向上、向下或是稳定发展。对收入分配的持续动态追踪,被目前大部分政府忽略了,但我们可以通过一些事例,观察到中国大部分上代务农的低收入人群的子女,都在向城市准中产阶层转变。比如说,有篇文章叫做《我奋斗了18年,终于和你一起坐在星巴克喝咖啡》,现在又有新一篇文章叫做《我奋斗了18年,不是为了和你一起坐在星巴克喝咖啡》……

穷国可能追赶上富国吗?这是一个开放式问题,但可以肯定的是,穷国的高速增长离不开低成本获得富国现有的技术与发明。关键点在于富国是否能继续保持在技术和效率上的领先,穷国是否能降低技术升级对富国的依赖。

政府的钱怎么花?对政府的财政政策来说,具有自发性或权衡性两种。

权衡性财政政策的第三个困难,在于政治的本质。自从经济大萧条和凯恩斯的著作问世以来,很多经济政策制定者都要求政府制定反经济周期的财政政策,亦即在经济差时花钱,在经济好时节俭。但政治上很难这么做,为什么?想象经济飞快增长的情况,税金像洪水般涌入,经济学家说:“不要花掉这些钱!要累积非常大的盈余,削减支出并提高税收。”这是一个很好的反经济周期政策,但它在政治上不容易获得认同。当经济萎缩且资金吃紧时,经济学家说:“这是大肆挥霍的良机,我们知道收不到税金了,管它呢,花吧!”但很多公民和政治人物会说,如果人们都在不景气时勒紧裤带过日子,那么政府也应该这么做。在经济好时节制政府支出,经济差时扩大支出,这种敏锐的洞察力不是一般政治人物能有的智慧。
其实权衡性措施在过去的农业经济中不难看到:丰收年,地主或政府管理者会存储大量粮食在粮仓,在欠收的年份,使用粮仓中的粮食向受到损失的地区发放救助。而货币的需求供给弹性却远远高于粮食,这也是权衡性政策难以操作的原因。

未来全球经济面临的危险:能源短缺和环境危机。在上面提到,工业化生产其实是以能源高消耗和忽略环境成本为代价的,一旦能源和环境的阈值达到,当前经济的长期增长就会面临危机。

现在越发认识到,人类社会最主要的矛盾就在于内部的竞争。当一部分人的技术发展起来时,他们需要竞争获取其它人的市场来使自己获得更大的利益;当市场竞争结束后,原本落后地区的人在成本上和原产地竞争;大量生产技术的转移,又会引发新一轮的技术发展竞争。人类的智力、知识、工具甚至语言的多样性,都远远超越了造物主在自然创造的复杂度,自然的简单性与漫长的修复周期,又反过来制约着人类的欲望与想象力。

经济学告诉你的,就是在约束与机会中果断地权衡自我的利益得失。

Julia语言介绍(二)多维数组

多维数组是科学计算中最核心的部分,与其它语言多依赖于第三方实现不同,Julia的多维数组是完全独立编写,并且提供了非常优秀的性能。

对Julia语言本身来说,它只提供了数组,更高抽象度的实现如TimeSeriesDataFrames,在另一个专门面向统计和机器学习的项目Julia Statistics中,需要通过添加Package的方式进行引用。

数组

首先来看看一个基本的数组,和Python的语法类似:

julia> l = [3, 4, 5]
3-element Array{Int64,1}:
3
4
5
Julia根据输入的数据绑定数组的类型,[3., 4, 5] 将产生一个 **Array{Float64,1}** 的类型,如果数值与字符串都存在于数组中,则会绑定 **any** 类型。
julia> l = [3., "a"]
2-element Array{Any,1}:
3.0
"a"
对单个字符而言,它会被转为另一个成员的类型:数值或浮点型:
julia> l = [3., 'a']
2-element Array{Float64,1}:
3.0
97.0
可以使用大括号创建一个 any 类型的数组,在 any 类型数组内部即使包含数组也会被当作一个成员,而非多维数组:
julia> l = { 3., "a", [3, 4] }
3-element Array{Any,1}:
3.0
"a"
[3,4]

索引

如果你以前使用过NumPy的数组索引,那么会对Julia的语法不会陌生,这里的区别是,Julia使用 end 来标识索引的尾部,在NumPy中我们只需要在冒号后留空。end 关键字在Julia中很常用,函数定义、控制语句甚至索引中都出现了。还要特别注意的是,Julia的索引是从 1 开始的。

julia> l[1]
3.0
julia> l[1:2]
2-element Array{Any,1}:
3.0
"a"
julia> l[2:end]
2-element Array{Any,1}:
"a"
[3,4]

数组操作

Julia使用 push! 函数将成员追加到数组末尾,不支持追加不同类型的成员,但小数点为0的浮点类型可以自动转换。

julia> l = [3, 4, 5]
julia> push!(l, 12.0)
4-element Array{Int64,1}:
3
4
5
12
julia> push!(l, 12.1)
ERROR: InexactError() in push!
julia> push!(l, "hello")
ERROR: 'convert' has no method matching conver(::Type{Int64}, ::ASCIIString) in push!
**append!** 函数则将一个数组的所有成员追加到原始数组中:
julia> append!(l, [10, 11, 12])
7-element Array{Int64,1}:
3
4
5
12
10
11
12
对于数组,可直接使用加减乘除运算符进行操作。
julia> a = [1.1, 2.2, 3.3]
julia> b = [4.4, 5.5, 6.6]
julia> a + b
5.5
7.7
9.9
对于数组和矩阵的乘法,Julia采用了Matlab的语法,使用 **.*** 而不是NumPy式的** ***
julia> a .* b
4.84
12.1
21.78

向量和矩阵

向量可以视为 m x n 矩阵 m = 1 的情况,Jilia中的数组的表现特点可与向量等同。定义一个向量是使用不带逗号的“数组”:

julia> vec = [3 4 5]
1x3 Array{Int64,2}:
3 4 5
矩阵的转置是使用 **'** 来完成,对于复数矩阵,可以使用 **.'** 直接完成共轭复数转置。
julia> [lim, 2]'
1x2 Array{Complex{Int64},2}:
0-lim 2+0im
julia> [lim, 2].'
1x2 Array{Complex{Int64},2}:
0+im 2+0im
下面是一个 2 x 2 的矩阵创建和转置操作:
julia> M = [1 2; 3 4; 56]
3x2 Array{Int64,2}:
1 2
3 4
5 6
julia> M'
2x3 Array{Int64,2}:
1 3 5
2 4 6
最后重新提一下科学计算中的数组。上面说到数组等同于向量是什么意思呢?我们来看看它与NumPy数组运算和编程语言中数组(Array)的区别。
# Julia
julia> l = [3, 4, 5]
3-element Array{Int64,1}:
3
4
5
julia> l' # 数组通过转置变成了向量
1x3 Array{Int64,2}:
3 4 5
julia> l'' # 再次转置变成了一个矩阵
3x1 Array{Int64,2}
3
4
5
# NumPy array
In [1]: import numpy as np
In [2]: a = np.array([1, 2, 3])
In [3]: b = np.array([4, 5, 6])
In [4]: a.shape
Out[4]: (3,)
In [5]: a + b
Out[5]: array([5, 7, 9])
In [6]: a * b
Out[6]: array([4, 10, 18])
# Python basic array
In [1]: a = [1, 2, 3]
In [2]: b = [4, 5, 6]
In [3]: a + b
Out[3]: [1, 2, 3, 4, 5, 6]
In [4]: a * b
---------------------------------------------------------------------------
TypeError in () ----> 1 a * b
TypeError: can't multiply sequence by non-int of type 'list'

Julia语言介绍(一)变量、类型和函数

科学计算语言Julia在设计上融合了Lisp、Python、JavaScript、Matlab等多种特点,下面我们来看看它是如何结合这些语言的优势,为计算科学提供强大的支持。

特殊符号变量

变量定义支持Unicode字符,非常有利于数学物理公式的表达,如希腊字母表,可以输入 / + 罗马拼音 + TAB:

julia> α = 3 # /alpha + TAB
3
这也意味着可以将变量命名为中文,如果不嫌打字麻烦的话:
julia> 生肖 = "羊"
"羊"
julia> 生肖
"羊"
Julia内置了一些数学计算常见的值为常量,注意的是,即使是内置的常量和函数,我们也可以重定义:
julia> pi
π = 3.1415926535897...
julia> pi = 3
Warning: imported binding for pi overwritten in module Main
3
**ans**这个变量指向上下文最后一个值,无论有没有变量指向它:
julia> ans
3
julia> 4
4
julia> ans
4

数值计算

Julia是动态类型系统,可以完成硬件支持范围之外的高精度计算,但速度会受硬件本身影响。数值和浮点的32/64位是基于操作系统类型指定,可以使用 WORD_SIZE 查来看系统类型:

julia> WORD_SIZE
64
julia> typeof(1)
Int64
julia> typeof(1.0)
Float64
对于非常大的数值,不管操作系统的类型是什么,Julia都会选择正确的数值类型。
julia> typeof(3000000000)
Int64
在运算符操符上和其它语言没有太大不同,比较操作符类似JavaScript,使用 === 加入类型比较,其它可直接阅读官方文档[基本数学运算](http://docs.julialang.org/en/release-0.3/manual/mathematical-operations/)。 复数和有理数的计算操作也非常方便,im 表示虚数,// 表示分数:
julia> 1 + 2im
1 + 2im
julia> 3(1 + 2im)
3 + 6im
julia> 3//4
3//4
julia> 5//12 - 1//4
1//6
一些基本的复数操作函数:
# 实数运算
julia> real(1 + 2im)
1
# 共轭复数
julia> conj(1 + 2im)
1 - 2im

函数

函数定义的基本语法以 end 结尾,另一种赋值形式的定义更为简洁:

# 标准定义
function f(x,y)
x + y
end

赋值形式

f(x,y) = x + y
赋值形式只支持一个表达式,但在Julia中可以使用复合表达式:

julia> f(x,y) = (x + y + y)
f (generic function with 1 method)
julia> f(x,y) = (if x < y x + y else x -y end)
f (generic function with 1 method)
julia> f(1,3)
4
julia> f(4,3)
1

函数的使用上遵从了许多科学计算人员和数据分析师的习惯,提供了 apply() 方法,对于操作符,也可将其视为函数进行调用:

# 基本调用
julia> f(5,3)
2

apply

julia> apply(f,5,3)
2

运算符即函数

julia> +(5,3)
8
多值返回也是计算中必不可少的利器:

julia> foo(a,b) = a+b, a*b
julia> f(5,3)
(8,15)

可变参数函数提供了任意个数参数的传入,它由参数名称加“…”来定义:

julia> bar(a,b,x…) = (a,b,x)
julia> bar(1,2)
(1,2,())
julia> bar(1,2,3)
(1,2,(3,))
julia> bar(1,2,3,4,5,6)
(1,2,(3,4,5,6))

可选参数的定义和Python语法非常接近:

function parseint(num, base=10)

###
end

参考:The Julia Manual, release 0.3

Julia - 高性能科学计算语言

Julia的发明人之一Jeff Bezason的目标是:“让世界上每一个人都可以使用高性能科学计算”。从2009年项目在MIT启动起六年时间,Julia已经发展成了一个支持云端和并行计算、C和Python语言调用并集成图表分析的非常全面的科学计算平台。

语言设计上,Jeff认为Julia针对的场景是探索性计算(Exploratory Computing),结合它高性能的特点,去在大数据集上尝试理解数据和试验不同的算法,这也是当下数据科学家和分析师们的主要任务;在数据分析领域,除了Python和R之外,我们又有了一个新的选择。

语言特点

屏幕快照 2015-02-19 下午5.07.59

  • 多分派(Multiple dispatch):根据参数的类型来进行方法调用
  • 动态类型系统
  • 媲美C等静态语言的性能
  • 类似Lisp的宏和元编程
  • 支持Python调用:通过PyCall包
  • 支持C语言直接调用:无须包装器或特殊的APIs
  • 用户自定义类型与系统类型一样快
  • 对Unicode字符支持良好
    以下是Julia与其它语言在数据计算效率上的对比:
















































































































    JuliaPythonRMatlabMathe-maticaJavaScriptGoLuaJITJava
    0.3.22.7.63.1.1R2014a10.0V8 3.14.5.9go1.2.1gsl-shell 2.3.11.7.0_65
    fib2.3979.95553.574638.29163.433.732.142.380.90
    parse_int1.9312.2453.231580.5217.662.333.776.795.55
    quicksort1.2433.23255.7354.4348.212.911.112.361.69
    mandel0.7212.1854.0651.236.241.550.990.710.57
    pi_sum1.0616.9316.551.271.512.191.331.181.00
    rand_mat_stat2.1419.0416.6510.486.713.328.924.344.01
    rand_mat_mul1.111.241.911.181.2117.199.831.442.35

Juno - 集成开发环境

Juno是一个免费的Julia语言开发环境,除了一些编码书写上的自动完成等基本功能外,它还提供了数据分析特有的数值计算显示和绘图功能。

error editor

IJulia - 集成分析环境

ijulialogo和IPython notebook一样,Julia也提供了一个网页版本的代码图表分析环境,安装过程参见GitHub JuliaLang / IJullia.jl 项目,它是基于IPython进行开发的。

IJulia也提供了一个在线运行环境JuliaBox供广大爱好者直接创建notebook和协作分享,但在国内由于Google Drive的原因而无法使用。

使用Python Pandas处理亿级数据

在数据分析领域,最热门的莫过于Python和R语言,此前有一篇文章《别老扯什么Hadoop了,你的数据根本不够大》指出:只有在超过5TB数据量的规模下,Hadoop才是一个合理的技术选择。这次拿到近亿条日志数据,千万级数据已经是关系型数据库的查询分析瓶颈,之前使用过Hadoop对大量文本进行分类,这次决定采用Python来处理数据:

  • 硬件环境

    • CPU:3.5 GHz Intel Core i7
    • 内存:32 GB HDDR 3 1600 MHz
    • 硬盘:3 TB Fusion Drive
  • 数据分析工具

    • Python:2.7.6
    • Pandas:0.15.0
    • IPython notebook:2.0.0
      源数据如下表所示:




















      TableSizeDesc
      ServiceLogs98,706,832 rows x 14 columns8.77 GB交易日志数据,每个交易会话可以有多条交易
      ServiceCodes286 rows × 8 columns20 KB交易分类的字典表

数据读取

启动IPython notebook,加载pylab环境:

ipython notebook –pylab=inline

Pandas提供了IO工具可以将大文件分块读取,测试了一下性能,完整加载9800万条数据也只需要263秒左右,还是相当不错了。

import pandas as pd
reader = pd.read_csv(‘data/servicelogs’, iterator=True)
try:
df = reader.get_chunk(100000000)
except StopIteration:
print “Iteration is stopped.”

1百万条

1千万条

1亿条

ServiceLogs

1 s

17 s

263 s



使用不同分块大小来读取再调用 pandas.concat 连接DataFrame,chunkSize设置在1000万条左右速度优化比较明显。

loop = True
chunkSize = 100000
chunks = []
while loop:
try:
chunk = reader.get_chunk(chunkSize)
chunks.append(chunk)
except StopIteration:
loop = False
print “Iteration is stopped.”
df = pd.concat(chunks, ignore_index=True)

下面是统计数据,Read Time是数据读取时间,Total Time是读取和Pandas进行concat操作的时间,根据数据总量来看,对5~50个DataFrame对象进行合并,性能表现比较好。

Chunk Size

Read Time (s)

Total Time (s)

Performance

100,000

224.418173

261.358521


200,000

232.076794

256.674154


1,000,000

213.128481

234.934142

√ √

2,000,000

208.410618

230.006299

√ √ √

5,000,000

209.460829

230.939319

√ √ √

10,000,000

207.082081

228.135672

√ √ √ √

20,000,000

209.628596

230.775713

√ √ √

50,000,000

222.910643

242.405967


100,000,000

263.574246

263.574246





屏幕快照 2015-02-17 下午2.05.48

如果使用Spark提供的Python Shell,同样编写Pandas加载数据,时间会短25秒左右,看来Spark对Python的内存使用都有优化。

数据清洗

Pandas提供了 DataFrame.describe 方法查看数据摘要,包括数据查看(默认共输出首尾60行数据)和行列统计。由于源数据通常包含一些空值甚至空列,会影响数据分析的时间和效率,在预览了数据摘要后,需要对这些无效数据进行处理。

首先调用 DataFrame.isnull() 方法查看数据表中哪些为空值,与它相反的方法是 DataFrame.notnull() ,Pandas会将表中所有数据进行null计算,以True/False作为结果进行填充,如下图所示:

屏幕快照 2015-02-16 下午11.21.29

Pandas的非空计算速度很快,9800万数据也只需要28.7秒。得到初步信息之后,可以对表中空列进行移除操作。尝试了按列名依次计算获取非空列,和 DataFrame.dropna() 两种方式,时间分别为367.0秒和345.3秒,但检查时发现 dropna() 之后所有的行都没有了,查了Pandas手册,原来不加参数的情况下, dropna() 会移除所有包含空值的行。如果只想移除全部为空值的列,需要加上 axis 和 how 两个参数:

df.dropna(axis=1, how=’all’)

共移除了14列中的6列,时间也只消耗了85.9秒。

接下来是处理剩余行中的空值,经过测试,在 DataFrame.replace() 中使用空字符串,要比默认的空值NaN节省一些空间;但对整个CSV文件来说,空列只是多存了一个“,”,所以移除的9800万 x 6列也只省下了200M的空间。进一步的数据清洗还是在移除无用数据和合并上。

对数据列的丢弃,除无效值和需求规定之外,一些表自身的冗余列也需要在这个环节清理,比如说表中的流水号是某两个字段拼接、类型描述等,通过对这些数据的丢弃,新的数据文件大小为4.73GB,足足减少了4.04G!

数据处理

使用 DataFrame.dtypes 可以查看每列的数据类型,Pandas默认可以读出int和float64,其它的都处理为object,需要转换格式的一般为日期时间。DataFrame.astype() 方法可对整个DataFrame或某一列进行数据格式转换,支持Python和NumPy的数据类型。

df[‘Name’] = df[‘Name’].astype(np.datetime64)

对数据聚合,我测试了 DataFrame.groupby 和 DataFrame.pivot_table 以及 pandas.merge ,groupby 9800万行 x 3列的时间为99秒,连接表为26秒,生成透视表的速度更快,仅需5秒。

df.groupby([‘NO’,’TIME’,’SVID’]).count() # 分组
fullData = pd.merge(df, trancodeData)[[‘NO’,’SVID’,’TIME’,’CLASS’,’TYPE’]] # 连接
actions = fullData.pivot_table(‘SVID’, columns=’TYPE’, aggfunc=’count’) # 透视表

根据透视表生成的交易/查询比例饼图:

屏幕快照 2015-02-17 上午12.00.09

将日志时间加入透视表并输出每天的交易/查询比例图:

total_actions = fullData.pivot_table(‘SVID’, index=’TIME’, columns=’TYPE’, aggfunc=’count’)
total_actions.plot(subplots=False, figsize=(18,6), kind=’area’)

屏幕快照 2015-02-17 下午2.27.05

除此之外,Pandas提供的DataFrame查询统计功能速度表现也非常优秀,7秒以内就可以查询生成所有类型为交易的数据子表:

tranData = fullData[fullData[‘Type’] == ‘Transaction’]

该子表的大小为 [10250666 rows x 5 columns]。在此已经完成了数据处理的一些基本场景。实验结果足以说明,在非“>5TB”数据的情况下,Python的表现已经能让擅长使用统计分析语言的数据分析师游刃有余。

如何设计企业级大数据分析平台?

传统企业的OLAP几乎都是基于关系型数据库,在面临“大数据”分析瓶颈,甚至实时数据分析的挑战时,在架构上如何应对?本文试拟出几个大数据OLAP平台的设计要点,意在抛砖引玉。

突破设计原则

建设企业的大数据管理平台(Big Data Management Platform),第一个面临的挑战来自历史数据结构,以及企业现有的数据库设计人员的观念、原则。数据关系、ACID在关系数据库几十年的统治时期是久得人心,不少开发人员都有过为文档、图片设计数据表,或将文档、图片序列化为二进制文件存入关系数据库的经历。在BDMP之上,我们需要对多种不同的格式的数据进行混合存储,这就必须意识到曾经的原则已经不再适用——One size dosen’t fit all,新的原则——One size fits a bunch.

以下是我列出的一些NoSQL数据库在设计上的模式:

  • 文档数据库:数据结构是类JSON,可以使用嵌入(Embed)或文档引用(Reference)的方式来为两个不同的文档对象建立关系;
  • 列簇数据库:基于查询进行设计,有宽行(Wild Rows)和窄行(Skinny Rows)的设计决策;
  • 索引数据库:基于搜索进行设计,在设计时需要考虑对对每个字段内容的处理(Analysis)。
    搜索和查询的区别在于,对返回内容的排序,搜索引擎侧重于文本分析和关键字权重的处理上,而查询通常只是对数据进行单列或多列排序返回即可。

数据存储的二八原则

不少企业在解决海量数据存储的问题上,要么是把关系数据库全部往Hadoop上一导入,要么是把以前的非结构化数据如日志、点击流往NoSQL数据库中写入,但最后往往发现前者还是无法解决大数据分析的性能瓶颈,后者也无法回答数据如何发挥业务价值的问题。

在数据的价值和使用上,其实也存在着二八原则:

  1. 20%的数据发挥着80%的业务价值;
  2. 80%的数据请求只针对20%的数据。
    目前来看,不管是数据存储处理、分析还是挖掘,最完整和成熟的生态圈还是基于关系型数据库,比如报表、联机分析等工具;另外就是数据分析人员更偏重于查询分析语言如SQL、R、Python数据分析包而不是编程语言。

企业大数据平台建设的二八原则是,将20%最有价值的数据——以结构化的形式存储在关系型数据库中供业务人员进行查询和分析;而将80%的数据——以非结构化、原始形式存储在相对廉价的Hadoop等平台上,供有一定数据挖掘技术的数据分析师或数据工程师进行下一步数据处理。经过加工的数据可以以数据集市或数据模型的形式存储在NoSQL数据库中,这也是后面要讲到的“离线”与“在线”数据。

理解企业的数据处理需求

数据库到数据仓库,是事务型数据到分析型数据的转变,分析型数据需要包括的是:分析的主题、数据的维度和层次,以及数据的历史变化等等。而对大数据平台来说,对分析的需求会更细,包括:

  • 查询:快速响应组合条件查询、模糊查询、标签
  • 搜索:包括对非结构化文档的搜索、返回结果的排序
  • 统计:实时反映变化,如电商平台的在线销售订单与发货计算出的库存显示
  • 挖掘:支持挖掘算法、机器学习的训练集
    针对不同的数据处理需求,可能需要设计不同的数据存储,还需要考虑如何快速地将数据复制到对应的存储点并进行合适的结构转换,以供分析人员快速响应业务的需求。

离线数据与在线数据

根据不同的企业业务,对“离线”的定义其实不一样,在这里离线数据特指在业务场景中适用于“历史数据”的部分。常见的历史数据查询分析一般来自于特定时间段,设计上需要考虑的是将数据存入历史库中时,建立时间索引。另一种情况是某种业务问题的定位或分析,在数据量巨大的情况下,基于Hadoop或Spark等框架编写分析算法并直接在平台上运行,可以大大节约数据导出导入、格式转换与各种分析工具对接的时间。

在线数据处理按照存储和分析的先后顺序,可分为批处理(先存储后分析)和流处理(先分析后存储)两类。Cassandra数据库的设计采用上数据追加写入模式,可以支持实时批处理;流式计算平台则有Apache Storm、Yahoo S4等开源框架,商业平台有Amazon Kenisis(部署在云端)。企业的实时分析需求往往有特定的应用场景,需要对业务和现行系统有深入的理解才能设计出一个合理的架构。

大数据的OLAP技术

在互联网的技术浪潮冲击下,不少传统企业也纷纷涉水大数据技术。以笔者经历的两个项目为例,传统企业与互联网公司相比有两个特点:

  1. 企业应用比较笨重和复杂,云计算等基础架构平台,互联网需要的是水平规模化扩展,但对传统企业来讲,更需要的是垂直一体化部署复杂的依赖并且方便重用;
  2. 企业数据,包括关系型的交易数据、日志、文档、电子邮件等等,但总体还是结构化数据占多数;互联网则是非结构化数据为主,如网页、图片、服务器日志等,在网页搜索或广告推荐等领域,高维数据分析比较常见。
    和企业私有云的架构一样,对企业的大数据平台,我们很难直接去简单复制互联网的海量存储或计算平台技术,如Hadoop、HBase、Spark;因为这些技术搭建的只是一个数据的基础设施,要在传统企业实施“大数据平台”,我们的思路是,如何将传统的商业智能运行在“大数据平台”之上。

OLAP - 联机分析

OLAP联机分析是从多维信息、针对特定问题的联机数据进行访问和分析的技术。从分析的角度出发,数据源需提供以下操作支持:

  • 维度和指标
  • 聚合
  • 上卷、下钻
  • 水平、垂直切分
  • 排序
    下面是一个数据表示例:


























































    DateCountryCityOSBrowserSale
    2014-01-23ChinaBeijingOSXChrome0.0
    2014-01-24ChinaShanghaiWindowsIE88.0
    2014-01-24ChinaBeijingOSXSafari20.0
    2014-01-25ChinaChengduLinuxChrome12.0
    2014-01-26ChinaBeijingWindowsFirefox30.0
    5 visits
    4 days
    1 country
    China: 5
    3 cities:
    Beijing: 3
    Shanghi: 1
    Chengdu: 1
    3 OS-es
    Windows:2
    OSX:2
    Linux:1
    3 browsers
    Chrome:2
    Firefox:1
    IE8:1
    Safari:1
    70.0
    4 sales

上卷至Country维度

SELECT COUNT(visits), SUM(sales) GROUP BY country














CountryVisitsSales
China5$70

根据Browser拆分

SELECT COUNT(visits), SUM(sales) GROUP BY country HAVING browser = “Chrome”














CountryVisitsSales
China2$12

查询Sales最高的Browers

SELECT SUM(sales), COUNT(visits) GROUP BY browser ORDER BY sales

Browser

Sales

Visits

Firefox

$30

1

Safari

$20

1

Chrome

$12

2

IE8

$8

1



通常OLAP的多维数据源由数据方(Cube)提供,关系型数据库或数据仓库都能提供数据方的设计,相对于数据库,数据仓库是昂贵的软硬件解决方案,而互联网普遍采用基于Hadoop技术构建的海量数据处理平台,在这里是否可以作为数据仓库的替代品呢?其核心技术还是,如何基于Hadoop来构建数据方。

Pre-aggregate - 预聚合数据

对数据库来说,数据聚合通常是实时的。实时聚合的好处是灵活,可以对任意列进行查询,缺点是CPU、I/O开销较大,数据量大时查询缓慢,吞吐量低;而对Hadoop这样的非实时计算、大量数据处理的平台来说,很适合对数据进行预聚合处理,预聚合的优点是查询快速高效,但缺点是无法灵活查询,比如未进行聚合处理的数据。

在基于Hadoop进行预聚合处理上,Adobe提供了一些经验:

  1. 数据表设计需要规范
  2. 超过3个维度、10亿条数据时处理会变得复杂
  3. 维度表之间尽量不要有相关关系
  4. 只创建必须的索引

领域模型设计

这个步骤的目的是理解数据并且构建出领域模型,包括:

  • 源数据如何拆分到不同字段中?
  • 哪些字段用于维度?
  • 哪些字段用于统计指标?
  • 使用什么样的规则来对数据进行聚合?
  • 用户经常使用的组合查询是?
  • 排序规则?
    下面是Adobe SiteCatalyst的设计参考,源数据是一条日志,使用reports.json来描述整个设计:
    屏幕快照 2015-02-07 下午4.56.05

数据采集优化策略

对历史数据,采用大量数据批处理来提高吞吐量,对新增的增量数据,尽量达到低延时查询。一些优化策略包括:

对输入进行条件过滤:

  • FileDateFilter (log name patterns: log-YYYY-MM-dd-HH.log)
  • TableInputFormat start/stop row
  • File Index in HBase (track processed/new files)
    提升Map的任务数:

  • CombineFileInputFormat - 2GB-splits => 500 splits for 1TB

  • FixedMappersTableInputFormat (e.g. 5-region splits)

数据处理

数据处理的过程包括读取源数据、预聚合并且生成可供查询的数据表,对OLAP而言,需要对数据进行以下处理:

  • GROUP BY
  • COUNT, SUM, AVG
  • SORT
  • HAVING - 需进行预聚合
    以下是Adobe在线数据处理设计和SQL查询的映射:

屏幕快照 2015-02-07 下午5.22.36

在reports.json中定义了触发各个处理的类:

屏幕快照 2015-02-07 下午5.23.50

 

整个处理过程如下:

屏幕快照 2015-02-07 下午4.58.12

云端自动化(下):使用Ansible和Heat进行软件部署

Ansible是一个使用Python开发的自动化运维管理开源工具,适用于批量管理服务器资源,基本概念包括:

  • Inventory:描述服务器资源,服务器资源以分组的模式放置在Inventory中,默认目录为 /etc/ansible/hosts
  • Dynamic Inventory:如云计算平台基础设施平台,在ansible执行时目标服务器资源可能还未创建,可以使用脚本动态创建资源列表写入Inventory路径
  • Playbook:Playbook译为“剧本”,顾名思义,它提供了ansible如何自动化执行的所有场景和任务描述
  • Modules:ansible是一个模块化平台,官方提供的模块库非常全面,包括cloud、command、database、network、packaging,也可以开发自己的自定义模块
    Ansible的安装,可以通过pip完成:
    >> pip install ansible

    接下来创建一个Inventory:
    >> sudo mkdir /etc/ansible
    >> touch /etc/ansible/hosts
    >> vim /etc/ansible/hosts

    在hosts中描述一组服务器和IP地址,我们指定组名openstack,两台OpenStack虚拟机IP:
    [openstack]
    10.74.149.12
    10.74.149.13

    验证访问:
    >> ansible openstack -m ping

    Playbook使用yaml语法描述,通常为一个主文档和多个同级目录下多个子文件夹和文档组成。

Ansible-Heat模块开发

Ansible是基于模块的架构,每个模块都是独立的Python文件,可以轻松地进行扩展。引入自定义模块文件有三种方法:

  1. 定义环境变量 ANSIBLE_LIBRARY 指向文件所在的目录路径;
  2. 在使用 ansible 命令时带上参数 –module-path 和目录路径;
  3. 在Playbook的根目录下创建 library 文件夹并放入模块文件。
    由于官方还未提供对OpenStack Heat的支持,在这里需要自己开发一个Heat的模块。Ansible Module的实现接口主要分为参数获取、实例化模块类、输出结果三部分,模块的输入接收一个dict对象,接收参数键值对,输出是接收一个JSON对象,在输出屏幕上打印出字符串:
  • 定义模块需要的参数组:参数组决定Ansible配置文件的键值对
  • 使用参数构建模块实例:调用 AnsibleModule 方法
  • 输出模块执行结果:JSON格式输出
    # 模块参数接收
    argument_spec = openstack_argument_spec()
    argument_spec.update(dict(
        stack_name=dict(required=True),
        template_parameters=dict(required=False, type='dict', default={}),
        action=dict(default='create', choices=['create', 'delete']),
        template=dict(default=None, required=True),
        disable_rollback=dict(default=False, type='bool')
    )
    
    )

构建模块实例

module = AnsibleModule(
argument_spec=argument_spec,
)

模块执行出错,返回错误信息

module.fail_json(msg={“error”:”can’t connect the server.”})

模块执行完成退出

result = {}
module.exit_json(**result)

了解基本知识后,现在开始我们的Heat模块开发。

配置约束结构定义

首先根据Heat Template的配置需求,定义一个Ansible Heat的配置文件结构:

- name: launch ansible heat example
  heat:
    stack_name: "ansible-heat"
    action: "create"
    disable_rollback: "false"
    template: "files/heat-example.yaml"
    template_parameters:
      KeyName: "keypair"
      DiskType: "ephemeral"
      InstanceType: "m1.small"
      Images: ["uuid", "uuid"]
配置说明如下: * heat - 指定执行这个配置时的模块名 * action - 对Stack的操作,创建或删除 * stack_name - 被创建的Stack的名称,是Heat必需的参数 * disable_rollback - 创建失败时的回滚标志,默认为false * template - 指定Heat Template文件的位置 * template_parameters - 命令行参数,提供灵活的调用 接下来对 ansible-module-core 项目源代码进行分析,它已经提供了一些OpenStack的模块如用户身份、计算和网络资源请求等,也提供了针对OpenStack的一些公共方法。 ### **开始编码** 创建一个heat.py文件,在底部引用公共模块:
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.openstack import *
引用Heat的Python包并检查,由于身份认证比较简单,我们就直接引用KeyStone:
try:
    from heatclient.client import Client
    from heatclient.common import template_utils
    from heatclient.common import utils
    from keystoneclient.v2_0 import client as ksclient
except ImportError:
    print("failed=True msg='heatclient and keystoneclient is required for this module'")
实现身份认证和创建删除Stack的代码可以参考之前的文章《[云端自动化(上):使用Heat对OpenStack进行流程管理](http://www.justinablog.com/archives/1278 "云端自动化(上):使用Heat对OpenStack进行流程管理")》,在这里我们只需要与Ansible Module调用进行集成:
result = {}
action = module.params['action']
stack_name = module.params['stack_name']

if action == 'create':
    try:
        heat.stacks.create(**fields)
        operation = 'CREATE'
    except Exception, err:
        module.fail_json(msg=err.message)
    result = stack_operation(heat, stack_name, operation)

if action == 'delete':
    heat.stacks.delete(**fields)
    operation = 'DELETE'
    result = stack_operation(heat, stack_name, operation)

module.exit_json(**result)
完整的模块代码参见:[https://github.com/RCFans/ansible-modules-extras/tree/devel/cloud/openstack](https://github.com/RCFans/ansible-modules-extras/tree/devel/cloud/openstack) 开发完成后,先对模块进行测试,测试工具包含在Ansible项目源码中,需要从GitHub上下载:
>> git clone git@github.com:ansible/ansible.git --recursive
>> source ansible/hacking/env-setup
>> chmod +x ansible/hacking/test-module

>> ansible/hacking/test-module -m ./heat.py
测试结果是参数缺失,由于还没有进行配置文件编写,这里可以认为代码实现已经正确:
PARSED OUTPUT
{
    "failed": true,
    "msg": "missing required arguments: stack_name,template"
}

Heat Playbook编写

在自动化部署时,基础设施如果已经创建,先需要对之前创建的资源进行检查和回收,再创建新一批基础设施。对文件目录结构可定义为:

- openstack-heat
  - roles
    - delete
      - files
      - tasks
    - create
      - files
      - tasks
由于我们操作的是基础设施而非目标服务器,hosts可指定为本机。roles下定义的delete、create为文件夹名称,files用于放置Heat Template文件。Ansible会查找文件夹下的.yml文档并执行。根目录下的文档 auto-deploy.yml 编写如下:
---
# This playbook deploys a simple standalone openstack server.

- hosts: localhost
  users: root

  roles:
    - delete
    - create
Tasks文件夹下为我们在Heat模块中定义的结构,下面是示例:
---
- name: launch ansible heat example
  heat:
    stack_name: "ansible-heat"
    action: delete
    disable_rollback: false
    template: roles/delete/files/single-instance.yaml
现在模块和Playbook配置已经完成,先在命令行中进行检查,我们把模块拷贝到了/usr/share/ansible目录下并使用环境变量方式引入:
>> ANSIBLE_LIBRARY=/usr/share/ansible/
>> ansible-playbook --syntax-check ansible-examples/openstack-heat/auto-deploy.yml
执行整个脚本:
>> ansible-playbook ansible-examples/openstack-heat/auto-deploy.yml
在输出和OpenStack的栈上都可以看到基础设施的创建了。 完整配置参见:[https://github.com/RCFans/ansible-examples/tree/master/openstack-heat](https://github.com/RCFans/ansible-examples/tree/master/openstack-heat) ## 部署脚本集成 Ansible提供Shell命令模块,只需要将软件的安装编写为脚本并集成到Playbook中即可:
- name: Install
  shell: sh files/application-install.sh
© 2018 Silent River All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero