admin

该用户没有分享资料


admin

Jeff Dean谈如何在大型在线服务中做到快速响应

之前在公司内网看到fanli分享过该类的内容,里面提到了backup requests和canary requests,印象比较深刻,也是深有体会,

所以这里就转载下这篇文章,以便后续加深理解。

原文:

Jeff首先以Google的搜索服务为例,说明了何为大扇出服务(Large Fanout Service),即一个搜索请求需要有大量子系统(Web、新闻、图像、视频、博客等等)参与其中,以便提供更丰富的搜索结果。在Google,基本不 会为特定的服务提供特定的机器,而是将服务都部署在一个机器池中,这被称为共享环境(Shared Environment),Google的共享环境大致会包含以下几个部分——Linux、调度系统、文件系统ChunkServer、多种其他系统服 务、Bigtable Tablet Server、随机MapReduce任务、CPU密集型任务以及随机应用。它的好处是可以极大地提升利用率,但同时也会带来诸多无法预测的问题,比如网 络拥塞等等。尤其是响应时间的长尾现象比较明显,一次请求的平均响应时间是10毫秒,但是却有99%ile的响应时间大于1秒,在大扇出服务中,如果需要 调用100台服务器获得最终结果,那有63%的请求耗时会大于1秒。

(备注:99%ile的含义:%ile means the percentage of people ranked below you)

针对延时问题,有些基本的降低延时的技术:

  • 定义不同的服务级别,针对服务器上的请求队列和网络流量设定优先级。
  • 减 少线头阻塞(head-of-line blocking),将大的请求打散成一系列小请求;比如,一个读请求需要读取64MB数据,而另有一个100KB的读请求必须等前者完成了才能得到处 理,此时可以将大请求分为多个小请求,以便100KB的那个请求能及时得到处理。
  • 管理好昂贵的后台活动,比如分布式存储系统中的日志压缩就算昂贵的后台活动,此类活动可以考虑在负载低峰期去执行。

Jeff指出,我们要做的事就是基于一堆不可靠的资源打造一个可靠的整体,基于一堆无法预估的资源打造可以预测的整体。在延时处理方面,Jeff将对应的技术分为两大块:

  • 跨请求适应(cross request adaptation),通过检测最近的行为,采取一些措施来优化后续的请求处理,通常会和负载均衡有关,生效时间大约是十几秒到几分钟。
  • 同请求适应(within request adaptation),在当次请求中,对响应较慢的子系统采取一些措施,以改善本次请求的整体响应时间,通常是立刻生效的。

随后,他分别就两类技术进行具体展开说明。

更多 >

awk中ord的实现:将字符转化对应的ascii码

在awk中并未直接提供ord函数,所以在将某个字符转换为码时,需要自己来实现


awk 'BEGIN{for (i = 0; i < 256; ++i) {ord[sprintf("%c", i)] = i;} }'  ' { print ord['a'];  ord ['b']; }'

这里主要是构造了ord为key,val的数据结构,key为char字符,val对应的ascii码

awk学习笔记之正则表达式

正则在Awk中用处比较多,这里就其主要用法做个大概的介绍。

  • 使用正则

awk中的regexp是用斜线包括,如/xx/, 就是一个比较简单的正则

awk '/foo/ {print $2}'

上面的示例是每行的记录只要包括foo字符串的,就将其第二个字段打印

注:/foo/ : 是指只要记录包含子串即可,不管其出现的位置

  • 两种匹配方式~  !~
  1. str ~ /regexp/    str匹配正则表达式时,返回true
  2. str !~  /regexp/   str不匹配正则表达式时,返回true
  • 正则中的转义字符
    对于一些非可打印的字符,使用\进行转义。
    如 \t : 代表tab  \\  代表\,   \*代表*
  • 正则中使用的operator
    1. ^ : 头部开始匹配
      如^Sep :  则str必须以Sep开头,正则匹配才会返回true
    2. $ :  尾部匹配
      如end$ :  则str必须以end结尾,则正匹配才会返回true
    3. . : 匹配任意的字符
    4. [...] : 匹配[]包含字符的某一个
      如[0-9] 匹配任意的一个数字
      [a-zA-Z] 匹配任意的字母
      [MVX] 匹配字符’M’ ‘V’ ‘X’中的某一个
      内置的表示:[:alnum:] 代表所有的字母和数字,[:alpha:] 代表所有的字母  [:digit:] 代表所有的数字
    5. [^...] : 中括号中加入^, 匹配非[]内的所有字符
    6. | : 或的关系,^P | [0-9] 匹配所有的以P开头的字符串,或者包含数字的字符串
      注:| 的优先级最低
    7. () : 将正则括起来
    8. 出现次数的operator: * + ? {m,n}
  • awk的正则匹配是大小写敏感,可使用tolower(str) ~ /regexp/

参考文章:http://www.math.utah.edu/docs/info/gawk_5.html

awk学习笔记【一】

今天主要介绍下awk中内置的String函数和awk中内置的变量。

awk中内置的string函数

  • index(in, find): 在 string “in”中查找 find 的第一次出现位置,返回的find在in中第一个字符出现的位置,从1开始
    awk 'BEGIN { print index("peanut", "an") }'
    # 打印3
    
  • length(string) : 返回字符串的长度,如果是number类型,返回对应字符的长度
  • match(string, regexp) : 正则匹配regexp的规则,如果匹配,则返回对应第一个字符的位置
  • split(string, array, fieldsep) : 按照fieldsep分割字符串,并将结果放置到array中,array的下标从1开始
    split("yaronspace.cn", fields, ".")
    # fields[1] = "yaronspace"
    # fields[2] = "cn"
    
  • sprintf(format, expression1, …): 格式化字符串
  • sub(regexp, replacement, target): 将第一个匹配的regexp的部分使用replacement替代,替代后的结果还是保存在target变量中。所以target必须是变量,不可为字符常量
    str = "yaronspace.cn";
    sub(/yaronspace/, "xiaofangdeng", str);
    # str="xiaofengdeng.cn"
    

    使用&符号引用匹配regexp部分的字符长,示例如下:

    str = "yaronspace.cn";
    sub(/yaronspace/, "&_xiaofangdeng", str);
    # str = "yaronspace_xiaofangdeng.cn"
    
  • gsub(regexp, replacement, target):  与sub功能类似,但是会替换所有匹配regexp的子串,g代表”global”的含义
  • substr(string, start, length) : 获取子串
  • tolower(string) : 转化为小写
  • toupper(string) : 转化为大写

awk中内置的变量

  • FS: Input Field Seperator variable: 对每行记录的分割符,可以通过-F参数修改,或者在awk文件中,直接使用FS=”XX”进行修改
  • OFS : Output Field Seperator variabble: 输出时默认每个记录的分隔符,默认为空格
    $ awk -F':' '{print $3,$4;}' /etc/passwd   # $3 $4以空格分割
    $ awk -F':' 'BEGIN{OFS="_"} {print $3, $4}' # 此时$3 $4是以_分割
    
  • RS : Input Record Seperator variable: 记录的默认分隔符,默认为\n换行符
    可以修改,如将其修改为\n\n,以两个空行为分隔符
  • ORS: Ouput Record Seperator variable: 默认的记录的输出的分隔符,默认为\n
  • NR: Number of records variable: 当前已读取记录数,默认情况为当前的行数
  • NF: Number of fields vairable : 当前记录的域的个数
  • FILENAME : Name of the current input file
  • FNR: Number of Records relative to the current input file : 当awk的输入文件只有一个时,NR == FNR;当awk的输入文件时多个时,FNR是当前文件的当前行数,NR是全局的行数

参考文章:

1. http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_92.html

2. http://www.thegeekstuff.com/2010/01/8-powerful-awk-built-in-variables-fs-ofs-rs-ors-nr-nf-filename-fnr/

libmemcached的retry_timeout问题分析

最近在线上中遇到使用libmemcached的svr连接memcached间隔性的出现47错误,每次在2s的时间内大量出现,

其宏定义为MEMCACHED_SERVER_TEMPORARILY_DISABLED,表示memcached临时性不可用.

libmecached的版本是0.53
刚开始以为是网络间隔性异常导致,但是在排查无果的情况,只能深入看下libmemcached的源代码,发现了其内部实现的
retry_timeout的机制:
  • 当某个时刻,某台memcached机器出现连接超时情况时,会将server的状态标识为MEMCACHED_SERVER_STATE_IN_TIMEOUT
  • 在接下来的retry_timeout(默认为2s)的时间内,libmemcached将不会重新连接该memcached,总是直接返回47错误码,表示服务临时不可用

我们遇到的情况就是当某个时刻网络抖动(这个在跨机房通信应该比较常见),可能会是在ms级的,但是libmemcached会直接将该server不可用,并且在2s内不再重试。这里就是所谓的“快隔离、慢恢复”的理念,会在2s内导致该memcached不可用,出现大量47错误的原因。

可以通过MEMCACHED_BEHAVIOR_RETRY_TIMEOUT将retry_timeout设置为1s来减少网络抖动的影响,但是不能设置为0,最少是1s.

snprintf函数的返回值问题

平时在程序设计中,我们推荐使用snprintf, 主要是为了避免str写越界的情况发生,但是对snprintf的返回值理解有个误区,

今天特别记录下。

snprintf的函数原型为:

int snprintf(char *str, size_t size, const char *format, …);

说明:

之前以为snprintf的返回值是实际写入到str字符串的长度,其实不然

case 1 : 如果要输出的字符串的长度< size, 主要这里不包括=, 因为snprintf会自动将\0加入到str中,

snprintf的返回值是实际str的长度

case 2 : 如果要输出的字符串长度>= size, 则表明str的长度不够写入原有的长度,则snprintf的返回值

在理想情况下(即str的长度足够长)的字符串长度,所以其返回值可能会出现>= size的情况。

另外需要说明的snprintf会自动将’\0′追加到str的末尾,而snprintf的返回值是不包括’\0′的

这个在官方的manual里写的比较清楚:

If the output was truncated due to this limit then the return
value is the number of characters (not including the trailing ’\0’) which would have been written to the final string if  enough  space  had  been  available.
Thus,  a  return value of size or more means that the output was truncated. (See also below under NOTES.)  If an output error is encountered, a negative value
is returned.

阿里技术嘉年华2013年PPT下载

总有一个适合你的 :)

阿里技术嘉年华2013年

1. 阿里分布式数据库服务原理与实践
2. 实时计算服务化实践
3. 构建一个跨机房的Hadoop集群
4. Android设备体验优化
5. 无线互联网-产品质量保证
6. 探求计算性能极限-探求计算密集应用优化的天花板
7. 基于Hadoop_HBase的一淘搜索离线系统
8. 深度学习:机器学习的新浪潮
9. 阿里分布式数据库服务原理与实践
10. 百度媒体云技术及架构
11. 后端-大型网站SEO优化实践
12. 去哪儿酒店实时搜索技术分享
13. 淘宝消息中间件技术演变
14. AB测试和灰度发布平台架构设计和实践
15. 淘宝网CRM平台架构for ADC
16. HouseMD介绍
17. Inside TAE
18. Nashorn与JDK8——动态语言在JVM上的高性能实现
19. Scala中的函数式特征与并发
20. TMS模块化页面搭建平台
21. Web页面分层交叉实验
22. 北冥神功- 新一代数据查询中间层
23. 互联网系统的稳定性保证:微博的实践
24. 基于OpenStack构建网易云主机服务
25. 架构模式与实践漫谈
26. 容量规划与授权限流降级
27. 淘宝文本中的语义分析以及技术展望
28. 天猫个性化推荐架构
29. 新一代前端代码开发与部属方案——独角兽系统功能简介
30. 让店铺飞起来
31. 商品详情页静态异步化
32. 架起前端和开发的桥梁
33. 淘宝网商品详情页静态异步化
34. 不一样的装修
35. 跨终端的文件加载及缓存
36. 开放JS在淘宝的应用
37. 你所不知道的TAE SDK
38. DBFree-阿里数据库自动化运维平台
39. CAP 理论与实践
40. iDB-阿里集团数据库服务平台
41. MySQL at NetEase
42. OceanBase0.4:从API到SQL
43. 阿里巴巴离线大数据处理平台概述
44. 阿里“去IOE”实践
45. 阿里数据同步前世今生
46. 大数据时代的月光宝盒
47. 分布式数据分析算法
48. 构建一个跨机房的Hadoop集群
49. 大众点评网高可用数据架构
50. 如何打造360 MySQL服务
51. 实时计算服务化实践
52. 实时计算平台及相关业务实践
53. 探索阿里数据藏宝图——数据地图管理实践
54. 腾讯广点通的数据挖掘
55. 小公司的服务管理和监控成长之路
56. 页面资源位监测和价值分析
57. Cascadb/TokuDB性能与适用场景分享
58. Mysql高并发热点更新性能优化
59. 开源软件的商业价值
60. CM–集群管理与负载均衡系统
61. 垂直抓取系统——EtaoSpider介绍
62. 个性化搜索技术和应用
63. 关系搜索和推荐
64. 海量商品的聚合技术及其在搜索中的应用
65. 机器学习在搜索排序中的应用
66. 基于Hadoop_HBase的一淘搜索离线系统
67. 搜索引擎和淘宝搜索不得不说的故事
68. 实时个性化系统和应用
69. 文本挖掘在电子商务场景中的应用
70. 一站式搜索服务平台-Tsearcher
71. Android动态部署与插件化的原理与实践——ATLAS
72. Android设备体验优化
73. 百度云推送介绍和架构分享
74. 无线客户端数据实战
75. 一个移动互联网技术创业的故事
76. 移动设备客户端安全
77. 移动系统中的Java虚拟机
78. 如何有效控制Andoid应用的耗电量
79. Lua wax在ios上的应用
80. Hybrid组建实践-WindVane项目简述
81. Android自动化测试
82. ios客户端稳定性
83. android app性能优化之list篇
84. iOS客户端应用测试实践
85. Fault injection实现原理与应用
86. iOS WEB自动化测试方案的探索与实践
87. 更好更快的Android自动化测试
88. 建设持续交付组织
89. 数据质量中心的设计与实现
90. 无线互联网-产品质量保证
91. 无线质量全过程保障实践
92. 不写代码实现UI自动化测试
93. 多浏览器兼容性测试平台xbrowser剖析
94. 前端无痛质量方案探索
95. 淘宝电子商务云应用安全
96. 淘宝网应用性能管理的原理和实践
97. 性能持续集成的探索和实践
98. TCPFLOW业务网络服务质量分析
99. 高性能网关产品的设计与实践
100. 海量未知木马机器分析
101. 深入理解CPU的读写及优化
102. 探求计算性能极限-探求计算密集应用优化的天花板
103. 自动化运维和数据化运维-从硬盘开始
104. 跨平台体验融合
105. 设计之外 我们还追求什么样的设计
106. 逸境人机
107. 数据可视化设计
108. Golden Age Of RTB
109. Tanx业务发展及系统架构
110. 阿里广告中的机器学习平台
111. 个性化推荐技术在广告中的应用
112. 淘宝联盟前端引擎技术发展
113. 深度学习:机器学习的新浪潮
114. 时间-兴趣耦合的IPTV用户收视模型
115. 搜索广告触发的挑战和应用
116. 淘宝DMP平台
117. 实时定向广告技术-DSP框架及算法
118. 广告中的Match新架构和CVR预估
119. 逸境人机
120. 广告引擎的索引设计实现和性能优化
121. canal产品介绍
122. Druid数据库连接池介绍
123. Dubbo开源
124. Fastjson介绍
125. Introduction to KISSY
126. MySQL复制
127. OceanBase介绍
128. tengine介绍
129. Tsar介绍
130. OpenStack Summit Intel Efforts
131. 纠错码技术在hadoop分布式文件系统的应用
132. 利用固态硬盘解决存储瓶颈

使用Bash中Complete自动补全命令

大家在Linux下都用shell的TAB自动补全功能,非常方便,但是有时自己开发程序,可能需要自定义实现TAB自动补全功能,这时可能就会用到complete命令来实现对命令的自定义补全,本文主要介绍complete的用法,下一篇会着重介绍对ssh的自动补全的实现。

入门

首先先看一个非常简单的例子:

$ # Create a dummy command:
$ touch ~/bin/myfoo
$ chmod +x ~/bin/myfoo

$ # Create some files:
$ touch a.bar a.foo b.bar b.foo

$ # Use the command and try auto-completion.
$ # Note that all files are displayed:
$ myfoo <TAB><TAB>
a.bar a.foo b.bar b.foo

$ # Now tell bash that we only want foo files.
$ # This command tells bash args to myfoo are completed
$ # by generating a list of files and then excluding
$ # everything # that doesn't match *.foo:
$ complete -f -X '!*.foo' myfoo

$ # Tray again:
$ myfoo <TAB><TAB>
a.foo b.foo
  • 首先自定义了command: myfoo,  然后测试对myfoo的自动补全功能,默认情况下,myfoo会自动列出当前目录的文件作为自动补全
    内容
  • complete -f -X ‘!*.foo’ myfoo : 使用complete命令对myfoo自定义补全功能,参数含义:-f 是列出当前的文件 -X pattern 将符合pattern条件的文件exclude,这里主要是显示*.foo的文件,将*.bar文件排除在外

complete参数详解

complete [-abcdefgjksuv] [-o comp-option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] name [name ...]
  • -W wordlist: 自动补全使用的wordlist, 使用IFS分割,会和当前用户输入的Word做前缀比较,提示那些匹配的word list.
  • -S suffix: 向每个自动补全word后添加suffix 后缀.
  • -P prefix: 向每个自动补全word后添加prefix 前缀.
  • -X filterpat: 对于文件名,将匹配pattern的文件名从completion list中移除(exclude), pattern中使用!表示否定
  • -G globpat: 对于文件名,将匹配pattern的文件名作为可能的completion. 与-X刚好相反,-X “!*.foo” 与 -G “*.foo”作用相同
  • -C command: 将command命令的执行结果作为可能的completion.
  • -F function: 执行shell function,在function中对COMPREPLY这个数组复制,作为可能的completion
  • -p [name]: 打印当前自定义的complete
  • -r [name]: 删除当前自定的complete
  • -A action : 表示生成可能的completion的方式,包括alias, file, directory等,具体请参看文后的参看资料

使用样例

  • 使用-C -G -X参数
    complete -C "pwd" ls  # ls的自动补全为当前目录
    complete -G "*.py" ls # ls的自动补全为.py文件
    complete -X "*.py" ls # ls的自动补全为非.py文件
    
  • 使用-F 参数自定义补全函数

    function _mycomplete_()
    {
        local cmd="${1##*/}"  # 当前命令
        local word=${COMP_WORDS[COMP_CWORD]}  #当前输入的字符串
        local line=${COMP_LINE}  #整行字符串
        local xpat='*.py'  # pattern
        # 根据word的值来补全当前非.py的文件file.
        COMPREPLY=($(compgen -f -X "$xpat" -- "${word}"))
    }
    # _mycomplete_函数可定义在.bash_profile中,然后执行
    source ~/.bash_profile
    # 当然也可多个命令共用一个function, 只要_myfunction_作区分即可,比如对cmd执行case语句
    # 生成不同的xpat
    
    complete -F _mycomplete_ myfoo  #使用_mycomplete 作为myfoo的自动补全
    

参考资料

Hadoop MapReduce学习笔记1

Hadoop MapReduce是比较经典的Master/Slave架构设计,系统主要包括两大模块:

  • JobTracker : 也就是我们所说的Master, 包括资源管理功能和作业调用功能;
  • TaskTracker : Slave模块,或者称为Worker,任务执行的节点;

JobTracker中资源管理

  1. Hadoop以slot(槽位)代表计算资源,包括一定的内存和cpu核,具体细分为Map Slot和Reduce Slot,一个Task可占用多个slots;一个TaskTracker可划分多个slots(可配置), slots间的资源隔离目前hadoop做的不是太好;
  2. TaskTracker作为具体的执行单元,采用pull的的方式拉取任务,TaskTracker会定期的向JobTracker发送心跳,心跳的信息包括:我还活着,TaskTracker中运行的task的状态,如果有空闲的slots的话,向JobTracker表明我有空闲资源,JobTracker以心跳应答的方式向TaskTracker分配新的Task;
  3. JobTracker不会主动的和TaskTracker联系,只会接收心跳,然后再应答中向TaskTracker发送指令,如启动Task, 杀死Task;如果长时间未收到TaskTracker的心跳,表明TaskTracker可能已宕机,则会重启TaskTracker上已经分配的任务到其他的TaskTracker中;
  4. 任务的调度策略:默认简单任务调度策略FIFO,可用户自定义任务的调度策略;

JobTracker中的作业控制

  1. Hadoop将作业分为三个层次:
    • 作业: 用户提交的作业,使用JobInProgress控制作业的运行状态,包含多个Tasks
    • Tasks: 包括Map Task 和 Reduce Task: 使用TaskInProgress控制任务的运行状态,可能包含多个Task Attempt.
    • Task Attempt : 某个Task的运行一次尝试,这里采用的类似two-phase commit的协议,因为jobtracker可能会针对同一Task启动两个Attempt(谁先执行完,使用谁的计算结果,并把另外一个杀掉),然后才会提交task attempt的结作为Task的计算结果,在TaskTracker中执行.
  2. JobTracker会从TaskTracker的心跳汇聚TaskAttempt的运行状态,然后调度未完成的task,分配给TaskTracker.
clipboard

c++中const变量问题的简单分析

今天同事问了关于const 值被更改的问题,这个问题在面试中也会经常被问到,所以专门写篇博客总结下。

代码如下

输出结果:a:10 p:20

简单分析:

其实针对该问题,原因比较简单,在printf调用中,由于a是常量,编译器做了优化,将a的值直接替换为10,所以在后续对a的内存位置进行更改为20时,并未对printf的a参数影响。当然,同事并未相信我的分析,我只能调用汇编后的代码进行分析。

深度分析:

1. 生成汇编代码:

g++ -S test.cpp   # 输出的汇编代码位于test.s中

2. 汇编代码如下:


根据第26行,验证了我上述的分析,此时同事想让我讲下整个汇编代码的逻辑(我心里暗喜,刚好最近在上@林士鼎 的课程,顺便复习下)
3. 函数调用的知识
理解函数调用栈,有几个概念需要事先明确:
a. 栈的增长方式由高到低(大学课本里早就会背了,但是要真正理解)
b. 参数传递方式:寄存器 + 栈
c. %rsp : 栈头指针 , push pop会更改对应的指针值
d. %rbp : 帧指针, 这个概念非常重要,当前函数的栈的起始位置,
使用%rbp + offset访问局部变量及传递的参数,下面这张图是@林士鼎 老师的课件中某个图

4. 汇编分析:

main:
.LFB2:
pushq %rbp    # 将原来的帧指针保存
.LCFI0:
movq %rsp, %rbp   # 将当前%rsp 保存至%rbp, 当前帧
.LCFI1:
subq $32, %rsp   # 将栈下移32Bytes, 这32字节保存了main的参数和main中局部变量
.LCFI2:
movl %edi, -4(%rbp)   # 取 argc的值
movq %rsi, -16(%rbp)    # 取argv的值, 为何会占12Bytes呢? 后续分析
movl $10, -20(%rbp)    # 将10赋值给a
leaq -20(%rbp), %rax   #取a的地址到%rax
movq %rax, -32(%rbp)     #将a的地址赋值给p(int *), 32的偏移有待分析
movq -32(%rbp), %rax    # 去p的值到%rax
movl $20, (%rax)     # 对*p赋值
movq -32(%rbp), %rax
movl (%rax), %edx   #这两步相当于*p,同时将其赋值到寄存器作为printf的参数
movl $10, %esi     #传递10参数(其实是a)
movl $.LC0, %edi    # "a:%d p:%d\n"
movl $0, %eax   #这个作用稍后分析
call printf
movl $0, %eax  #main函数的返回值
leave
ret

变量在栈的位置分布情况:


5. 其他问题分析:

a. 为何argv 和 p在栈的位置偏移异常,这里主要是因为argc 和a 的大小为4Bytes,  而系统是64Bits, 所以存在8Bytes对齐,
这里可以验证,在a后面单独声明一个b变量,发现其在栈的空间刚好为间隙的位置

b.  movl $0, %eax   这句话的作用:当对于变参的参数传递时,%eax标示的使用vector register的数目(可以向printf传递float类型参数进行验证)

参考资料:

1. http://stackoverflow.com/questions/6212665/why-is-eax-zeroed-before-a-call-to-printf

2. http://yaronspace.cn/blog/archives/1347