Comments

设计表

首先是设计表结构。建表语法差别不大,有一些地方可以注意一下:

  • Redshift 貌似没有无符号类型,所以要把 unsigned 类型的字段修改成相应的 INT 或 BIGINT 类型。
  • FLOAT 类型改成 REAL 或 FLOAT4
  • 把索引语句去掉,保留主键、外键、唯一性约束,Redshift 不会检查这些约束,但是查询时会用于优化。
  • Redshift 的 CHAR 类型只能包含单字节 ASCII 字符,对于非 ASCII 数据需要把 CHAR 改成 VARCHAR 类型
  • 有可能 MySQL 中存的是 unicode,而 Redshift 中存的是 bytes,所以 VARCHAR 的长度也要调整,避免溢出。最简单的,可以用 MySQL 的字段长度 * 3.

关于 sort key, dist key 等设计,只属于 Redshift 范畴,参考官网文档即可。

Read on →
Comments

启动 EC2 实例

先根据 Tableau Server 的使用情况确定需要的配置,从而确定实例类型。

  • AMI: Microsoft Windows Server 2012 R2 Base(简体中文)
  • 类型: m4.4xlarge

启动、配置步骤略去不表,有两点需要注意:

  • VPC 需要开启 3389 端口用于远程登录(RDP)
  • 密钥对会用于解密登录密码

安装 Tableau Server

从 Tableau 官网下载然后安装,配置、激活过程比较简单,略去不表。

Read on →
Comments

前段时间帮同事处理了一个把 CSV 数据导入到 MySQL 的需求。两个很大的 CSV 文件, 分别有 3GB、2100 万条记录和 7GB、3500 万条记录。对于这个量级的数据,用简单的单进程/单线程导入 会耗时很久,最终用了多进程的方式来实现。具体过程不赘述,记录一下几个要点:

  • 批量插入而不是逐条插入
  • 为了加快插入速度,先不要建索引
  • 生产者和消费者模型,主进程读文件,多个 worker 进程执行插入
  • 注意控制 worker 的数量,避免对 MySQL 造成太大的压力
  • 注意处理脏数据导致的异常
  • 原始数据是 GBK 编码,所以还要注意转换成 UTF-8
  • click 封装命令行工具

具体的代码实现如下:

Read on →
Comments

在 Flask 项目中使用 Celery 这篇文章谈到了如何在 Flask 项目中集成 Celery,也讲了在 celery 任务中引用 Flask 的 application context 的方法。一般情况下那样使用是没问题的,但是如果需要在 task 中使用 gevent,就需要一些额外的改进。至少有两点。

1. 使用 gevent 并发模型

如果在 task 中要使用 gevent,就必须使用 gevent 并发模型。这很好处理,只需要修改启动选项就行:

$ celery worker -A celery_worker.celery -P gevent -c 10 -l INFO

上面的命令,-P 选项指定 pool,默认是 prefork,这里是 gevent; -c 设置并发数。

Read on →
Comments

生产环境上用了 MongoDB,三个节点组成的 ReplicaSet(复制集)。部署好后,应用一直没出过问题,所以平时也没管过。今天早上突然想上服务器看看,于是登录了 primary 节点查看日志,发现这条日志不断重复:

2016-04-15T03:02:39.470+0000 W NETWORK  [ReplExecNetThread-28676] Failed to connect to 172.31.168.48:11102, reason: errno:111 Connection refused

其实就是有个 secondary 节点一直连接不上。不太可能是网络问题,所以很可能是那个节点的 mongod 进程挂掉了。登录上 secondary 节点,mongod 进程果然不在运行;查看日志发现最后一条是在 2016-03-21. 一时间有两个疑问涌上心头:

  1. 为什么会挂掉?
  2. 如何修复?
Read on →
Comments

最近生产环境上出现了一个奇怪的问题。某日下午,APP 向某个域名发出的所有请求没有响应,服务端也没收到请求;而向另一个域名的请求却没有问题。先记录一下背景:

  • 两个域名:api.example.com, web.example.com
  • 环境:AWS + ELB + Nginx
  • 后端:Python + Django + Gunicorn

出问题的是 api.example.com (下文简称 API)这个域名,所以 web.example.com 就不细说。由于一些历史原因,API 的请求链路大概是这样:

                      proxy_pass         backends                      proxy_pass
APP -----> API Nginx -------------> ELB -----------> Backend Nginx(s) ------------> Gunicorn(s)

其中 API 的 Nginx 配置大概是这样:

location /test {
    proxy_pass http://name.of.elb.aws.com;
}
Read on →
Comments

上一篇博客 简单介绍了 zhihu-go 项目的缘起,本篇简单介绍一下关于处理 HTML 的细节。

因为知乎没有开发 API,所以只能通过模拟浏览器操作的方式获取数据,这些数据有两种格式:普通的 HTML 文档和某些 Ajax 接口返回的 JSON(返回的数据实际上也是 HTML)。其实也就是爬虫了,抓取网页,然后提取数据。一般来说从 HTML 文档提取数据有这些做法:正则、XPath、CSS 选择器等。对我来说,正则写起来比较复杂,代码可读性差而且维护起来麻烦;XPath 没有详细了解,不过用起来应该不难,而且 Chrome 浏览器可以直接提取 XPath. zhihu-go 里用的是选择器的方式,使用了 goquery.

goquery 是 “a little like that j-thing, only in Go”,也就是用 jQuery 的方式去操作 DOM. jQuery 大家都很熟,API 也很简单明了。本文不详细介绍 goquery,下面选几个场景(API)讲讲在 zhihu-go 里的应用。

Read on →
Comments

我是知乎重度用户,每天都会花点时间在知乎上面看点东西。有段时间时间线里经常出现爬虫相关的话题,也看到不少直接爬知乎信息的项目;其中一个就是 zhihu-python. 实际上 zhihu-python 不是一个完整的爬虫,正如其文档说明的那样,是一个 API 库,可以基于这些 API 实现一个爬虫应用。zhihu-python 实现了用户、问题、答案、收藏夹相关的信息获取类 API,对于大多数信息获取的目的已经足够。这个项目很受欢迎,然而说实话,代码质量一般,不过思路值得借鉴。

Read on →
Comments

极光推送 是国内最早的第三方消息推送服务,官方提供了多种语言的 SDK 和 REST API,详情见 官方文档。遗憾的是缺少一个 Go 语言版本的 SDK,于是我就动手造轮子,封装了一个 Go 的版本。

实际上这个项目在今年 3 月份就完成了主要的推送相关的接口,在 GitHub 上也收获了几个 star 和 fork. 最近几天突然兴起,又翻出来把 device, tag, alias, report 的一些相关接口也封装完成了。

啰嗦了一大堆,差点忘了最重要的东西,下面给出链接:

欢迎使用,并 反馈 issues创建 pull request.

Comments

前一篇 Blog 简单介绍了 Celery 及其用法,现在我们看看在 Flask 项目中如何使用 Celery.

注意,这篇 Blog 严重参考了这两篇文章:

  1. Using Celery With Flask: 写了一个完整而且有意义的例子来展示如何在 Flask 中使用 Celery.
  2. Celery and the Flask Application Factory Pattern: 是上文的姊妹篇,描述的是更为真实的场景下,Celery 与 Flask Application Factory 的结合使用。
Read on →
getElementsByTagName('BODY')[0]).appendChild(s); }()); getElementsByTagName('BODY')[0]).appendChild(s); }()); getElementsByTagName('BODY')[0]).appendChild(s); }());