1. 应用MySQL InnoDB全文索引

    问题

    之前涉及的一项工作要求对某些数据做全文索引,并以API向其他内部系统提供搜索查询服务。

    由于需要建全文索引的数据量并不大,且已有的数据都以InnoDB引擎存储,简单起见,我们选择MySQL InnoDB引擎的全文索引特性来实现。MySQL从版本5.6开始支持InnoDB引擎的全文索引,不过“从5.7.6版本开始才提供一种内建的全文索引ngram parser,支持CJK字符集(中文、日文、韩文,CJK有个共同点就是单词不像英语习惯那样根据空格进行分解的,因此传统的内建分词方式无法准确的对类似中文进行分词)”,我们使用的MySQL版本为5.6.28,并且需要建全文索引的数据部分是中文,所以这是个问题。

    方案

    我们先把这项工作按“分治”的思想拆分成几个小问题:

    1. 由于版本5.6.28的MySQL不支持中文的全文索引,那么可以对需要建全文索引的数据进行预处理 - 分词,并以空格为间隔将分词结果拼接成一个字符串。
    2. 但经过第1步仍是不够的 - MySQL的系统变量ft_min_word_lenft_max_word_len分别规定了全文检索被编入索引单词的最小长度和最大长度,默认的最小值为4个字符,默认的最大值取决于使用的MySQL版本。为了不改变这个默认值同时也是兼考虑这个值对于英文的意义,则需要通过编码(urlencodebase64汉字转拼音等)将中文词变长 ...
    Tagged as : MySQL 笔记
  2. 关于并发的一个小技巧

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

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

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

    那么该怎么办呢?

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

    • 假设对同一脚本运行5个实例,为每个实例进程分配一个ID,依次为:0、1、2、3、4
    • 对脚本实例获取数据的SQL,增加选择条件:MOD(id, 5)=SID(SID为当前脚本实例的ID) - 即使用数据行的id对实例数取模,如果结果等于实例的ID,则取出来 ...
    Tagged as : 笔记 SQL
  3. 关于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 ...
    Tagged as : Nginx 笔记 工作
  4. 为什么我要送掉纸质书?

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

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

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

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

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

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

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

    Tagged as : 笔记 生活 感悟
  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编码算法是什么样的?

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

    我认为 ...

    Tagged as : 笔记 编码
  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 ...
    Tagged as : github 笔记 git 开源
  7. 青云 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 ...
    Tagged as : 笔记 工作 总结
  8. 又一次系统故障

    上周五早上9点多,我还在上班的路上,接到技术leader的电话:线上突然出故障了;接着发来一张故障信息页面截图:

    system-fault-err-page

    截图包含的信息是:数据库中没找到数据表Users

    但同事检查过数据库,Users数据表是存在的。


    我快速地回忆了一下最近的代码发布和环境变更 - 前一天有个同事对线上机器做了点改动。因此,让同事赶紧检查一下之前的改动是否有问题,经检查确认改动没有问题,而且稍微思考一下就应该明白不是配置的问题,如果是配置的问题,那么问题应该早就出现了,而不是在早上9点多时候才发生。


    我翻了翻手机中最近收到的几条告警短信,去除重复告警短信,只有两条告警:

    • 某台Web服务器上出现大量的500错误
    • 某台数据库服务器的磁盘使用率为98.99%

    由此可以推测两个故障原因:

    1. 那台Web服务器上应用的数据库配置有问题 - 但检查之后确认没有问题
    2. 由于那台数据库服务器磁盘满导致的问题,虽然一时还想不到其中的关联 - 同事在检查之后,确认那台机器的磁盘确实已满,但通过内网的数据库管理后台,可以正常访问数据库,所以认为应该不是磁盘满导致的问题

    如此,一时我也没想明白故障的原因。


    接着,同事发来消息:只有登录用户才会遇到这个问题!

    这时,基于之前的线索,基本能断定故障原因是 - 数据库服务器磁盘满。为什么呢?

    1. 数据库管理后台默认是只读:读数据表列表、数据表结构、单个表的若干条数据 ...
    Tagged as : 笔记 故障

Page 1 / 6