1. 关于并发的一个小技巧

    前段时间在参与实现一个新业务系统的Demo。该系统集成了多个已有系统的数据,涉及的数据量较大,但由于人力少,时间短,没法专门做一个数据处理子系统,所以只能写了很多数据处理的脚本。

    a-simple-concurrency-trick

    为了复用一些代码,这些数据处理脚本和业务系统一样都是使用PHP实现。在某些数据上报API写入的数据较快较多时,脚本处理不过来(特别在脚本涉及一些网络请求时),只能搞起并发处理 - 在我们的情况下,最简单的并发方式就是多运行几个脚本实例。

    但一切没那么简单:脚本从数据库中取出未经处理的多行数据,逐行处理数据,并将处理后的数据更新到原来的数据行中,运行多个脚本实例时,为了避免更新冲突,只好加事务,但加事务后就会频繁发生事务回滚,数据处理速度还是上不去。

    那么该怎么办呢?

    参考哈希的思路,我对脚本做了一点调整,下面举例说明:

    • 假设对同一脚本运行5个实例,为每个实例进程分配一个ID,依次为:0、1、2、3、4
    • 对脚本实例获取数据的SQL,增加选择条件:MOD(id, 5)=SID(SID为当前脚本实例的ID) - 即使用数据行的id对实例数取模,如果结果等于实例的ID,则取出来 …
    标签: 笔记 SQL
  2. 关于API访问频率限制的一个问题

    工作中涉及一些对外开放的无需特殊权限的API,用户会因为某些需求而通过程序来频繁访问这些API,导致系统的负载陡增,可能影响系统其它功能的正常使用。虽然做了一些优化让这种API尽可能地轻量,但仍然不够,因此需要进行访问频率的限制。

    由于这样的API并不多,所以我们并没有在Nginx这样的反向代理接入层中实现频率限制,而是API自己去实现,而且实现方案比较粗糙 - 基于Memcached的缓存自动过期特性。

    方案的PHP示例实现如下所示:

    // 每个IP一分钟10次
    $limit = 10;
    
    $cache = new Memcached();
    $cache->addServer('127.0.0.1', 11211);
    
    $key = __FUNCTION__.$_SERVER['REMOTE_ADDR'];
    $requestNum = $cache->get($key);
    
    if ($requestNum !== FALSE && $requestNum > 10) {
        echo json_encode(array(
            'code' => 403,
            'message' => '请求太频繁,请一分钟后再试',
        ));
        return;
    }
    
    $cache->add …
    标签: Nginx 笔记 工作
  3. 为什么我要送掉纸质书?

    小时候,不知为何喜欢读书,而又没钱买,所以在家都是翻两个哥哥的课本 - 语文、历史、地理等,都翻个遍。更有甚者,竟然还从邻居家偷偷地拿了本书回来,这应该算是我品行上的污点,这事在此说起,也是第一次。

    因为书少,所以至今还记得爸爸第一次送给我的书 - 《一个变两个》 - 连书里的情节都没忘过。

    读初中时,因为读书,还和好朋友闹过一点不愉快:朋友买了一些好书,我想借来看,他不肯,我就每天比大家早起一些,偷偷从他抽屉里拿来看几页,在他到教室之前再放回去,后来“事发”,。。。当然这一切都已过去,朋友还是朋友。

    高中后,开始有一些零花钱/饭钱,从其中挤出部分钱来买书成了我的一个习惯,书也由此越来越多。

    其实我根本看不了那么多书,最终累积了大量的书没认真读过。有时觉得可惜了,就会为读书而读书,精神为读书所累。

    这些年,几次搬家 - 从本科学校到研究生学校、读研期间换宿舍、毕业工作 - 每次最多最重的都是书,“书生搬家 - 尽是书!”。

    工作后租的房子没那么宽敞,导致到处塞的都是书 …

    标签: 笔记 生活 感悟
  4. 如何杀死defunct进程(译)

    原文:How to kill defunct process

    译者:youngsterxyf

    defunct进程是指出错损坏的进程,父子进程之间不会再通信。有时,它们会演变成“僵尸进程”,存留在你的系统中,直到系统重启。可以尝试 “kill -9” 命令来清除,但多数时候不管用。

    为了杀死这些defunct进程,你有两个选择:

    • 重启你的计算机
    • 继续往下读...

    我们先看看系统中是否存在defunct进程:

    $ ps -A | grep defunct
    

    假设得到的输出如下所示:

    8328 ? 00:00:00 mono <defunct>
    8522 ? 00:00:01 mono <defunct>
    13132 ? 00:00:00 mono <def …
    标签: Linux
  5. Base64编码原理与应用

    2015年,我们在青云平台上实现了“百度云观测”应用。青云应用本质上是一个iframe,在向iframe服务方发送的请求中会携带一些数据,青云平台会使用Base64 URL对这些数据进行编码,其提供的编码解码算法示例如下:

    // php版本
    function base64_URL_encode($data) {
      return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }
    function base64_URL_decode($data) {
      return base64_decode(str_pad(strtr($data, '-_', '+/'), 
                                strlen($data) % 4, '=', STR_PAD_RIGHT));
    }
    

    可以看出,Base64 URL 是标准Base64编码的一个变种,分别用 -_ 替换标准Base64编码结果中的 +/ ,并删除结果最后的 =

    在实现 “百度云观测” 青云应用时,我在想:

    • 为什么要使用Base64编码?
    • Base64编码算法是什么样的?

    本文是围绕这两个问题思考和实践的结果。

    我认为 …

    标签: 笔记 编码
  6. 基于Github的pull request流程做开源贡献

    最近给 beego 提了几个 pull request (简称PR),都已被接受。在使用pull request的过程中,遇到了一点小问题,才知以前并非真的理解这个流程,故在此做点记录整理。

    我以 beego 为例,将pull request的整体使用流程绘图如下:

    fork-pull-request

    beego代码库有两个长期分支 masterdevelopmaster为稳定分支,develop为开发分支,所有PR都要求提交到 develop 分支。

    1. 先将 astaxie/beego 代码库 fork 一份到自己的名下(如我的 youngsterxyf/beego)。
    2. youngsterxyf/beego clone 到本地机器上做开发。因为PR要提到 astaxie/beego 的 develop 分支,所以最好对应地在你fork的代码库的 develop …
  7. 关于Redis与Memcached的一点澄清(译)

    原文:Clarifications about Redis and Memcached

    译者:youngsterxyf

    译注:本文为Redis的作者所写

    如果你了解我,就会知道我并不是那种认为竞品是一件坏事的人。实际上我喜欢用户有选择的空间,因此我很少做将Redis与其他技术做对比这类事情。

    然而,为了选择正确的方案,用户必须获取正确的知识,这一点也是理所应当的。

    本文的起因是读了Mike Perham写的一篇博文,你也许知道他是Sidekiq这一流行程序库的作者,Sidekiq又恰好使用Redis做后端。因此我毫不认为Mike是一个“反对”Redis的人。但在博文(你可以在 http://www.mikeperham.com/2015/09/24/storing-data-with-redis/ 找到这篇博文)中,他陈述到:要用缓存,“你可能应该选择Memcached(而不是Redis)”。这样看来,Mike确实简单地相信Redis不适合用做缓存,在文章中他是这样论述的:

    • 1) Memcached专为缓存而设计
    • 2) 它根本不会有磁盘I/O操作
    • 3 …
  8. 青云 iframe 应用开发

    上周的主要工作是将产品的功能集成到青云。青云提供 iframe 的方式来集成第三方服务,这是一种互利的做法,而且对于青云来说,实现的代价也非常小。

    先上图,看看集成的效果:

    ygc-in-qingcloud


    对于青云来说,一个iframe应用就是一个URL,由应用开发者提供这个URL,当青云用户访问应用所在的页面时,页面先自动向应用服务器的URL发送数据请求,请求会携带认证信息,应用服务端需要先校验请求确实来自青云,并获取请求中的用户信息,最终响应一个HTML页面内容,青云应用页面收到响应数据后将其置于一个iframe标签中,之后青云用户在iframe页面中的操作都是直接与应用服务器交互。

    qingcloud-iframe-interaction

    上图交互流程的第2步中,青云服务器向用户响应的内容最终会生成一个包含以下内容的页面:

    <form method="POST" action="URL" target="appframe">
        <input type="hidden" name="payload" value="...">
        <input type="hidden" name="signature" value="...">
    </form>
    <iframe id="..." name="appframe" width="100 …
    标签: 笔记 工作 总结

Page 3 / 18