也就这样， - 2016年9月
type: channel
link: https://type.so/2016/09/
description: 凡出言，信为先；诈与妄，奚可焉。
items: typecho代码高亮插件
items: 正则-编程语言调用代码的生成
items: 根据magnet下载torrent
items: 分库分表的策略

typecho代码高亮插件
type: item
date: 2016-09-30T22:05:43+08:00
description: 这是很久之前写的一个typecho代码高亮插件了，由于是自己用的，所以高亮theme之类的都没有弄成可配置的；自定义修改需要更改theme的话，可以直接修改 HighLight/Plugin.php 文件里面引用css的代码行echo ' ' . "\n";@疯狂的杰作 同学提出是否要分享一下，所以就拿出来了。安装方法下载 HighLight.zip，解压上传到 /path/to/your/typecho/usr/plugins/ 目录下，使用 admin 帐号登录你的 typecho 后台，在插件管理里面启用他就可以啦。HighLight.zip

正则-编程语言调用代码的生成
type: item
date: 2016-09-26T23:50:00+08:00
description: 演示： 正则表达式测试工具功能介绍给定一个正则，生成php的正则调用代码。一般正则中都会或多或少的包含具体编程语言中的特殊字符，还需要考虑到具体语言中字符串的转义;下面列出了一些常见的要考虑的情况:1. 语言是否支持多行字符串? 2. 是否有定界符? 3. 语言的正则引擎是否支持逆序环视? 4. 正则修正符?具体场景我们拿PHP做个例子：写一个特殊字符覆盖比较全的正则，并写出他的PHP匹配代码：要匹配的内容 '引用\/' 正则 '(.+?\\/)' PHP匹配代码$contents = <<<EOT '引用\/' EOT; if (preg_match('/ \'(.+?)\\\\\/\'<\/div>/', $contents, $match)) { var_dump($match); }注意： 上面的正则写到PHP代码中的时候，以下字符进行了转义：1. ' 单引号 2. / 定界符 3. \ 转义字符，这是个比较特殊的字符实现思路要实现一个可用的代码生成，无非就是要把上面提到的特殊字符给转义了；本想要用正则再对正则的字符串转义，最后发现不太靠谱，越写越复杂;记起之前看过的redis conf分析相关的代码之后，遂选择逐字判断字符，并对字符转义，效果不错；注意优先级！public function escape($value) { $chars = str_split($value); $len = count($chars); $result = ''; for ($i = 0; $i < $len; $i++) { if ($chars[$i] === '\\' && $i < $len - 1) { // 转义字符的判断优先级最高，可以避免 \' 正则的重复转义 $i++; // 跳过后面一个字符 if ($chars[$i] === '\\') { $result .= '\\\\\\\\'; } else { $result .= '\\' . $chars[$i]; } } else if ($chars[$i] === '\'') { // 单引号，php字符串边界 $result .= '\\\''; } else if ($chars[$i] === '/') { // / php正则定界符 $result .= '\\/'; } else { $result .= $chars[$i]; } } return $result; }

根据magnet下载torrent
type: item
date: 2016-09-26T23:37:00+08:00
description: 整体流程requirement# 安装virtualenv pip install virtualenv # 创建虚拟环境 virtualenv env # source . ./env/bin/activate 安装依赖包 pip install beanstalkcClient实现往beanstalkd里面塞hashimport beanstalkc import sys if __name__ == '__main__': if len(sys.argv) < 2: print("usage: %s <hash>" % sys.argv[0]) sys.exit(1) if len(sys.argv[1]) != 40: print("hash code is error.") sys.exit(1) beanstalk = beanstalkc.Connection(host = "localhost", port = 11300) beanstalk.put(sys.argv[1]) print("hash has put")server依赖libtorrent下载torrentwget https://github.com/arvidn/libtorrent/releases/download/libtorrent-1_0_10/libtorrent-rasterbar-1.0.10.tar.gz tar zxf libtorrent-rasterbar-1.0.10.tar.gz cd libtorrent-rasterbar-1.0.10 ./configure --enable-python-binding PYTHON=`which python` --prefix=$VIRTUAL_ENV LIBS='-liconv' make -j2 && make install依赖beanstalkd队列mkdir /usr/local/beanstalkd/bin wget https://github.com/kr/beanstalkd/archive/v1.10.tar.gz tar zxf v1.10.tar.gz cd beanstalkd-1.10/ make mv beanstalkd /usr/local/beanstalkd/bin mkdir /data/beanstalkd/ # /usr/local/beanstalkd/bin/beanstalkd -b /data/beanstalkd/使用supervisor管理beanstalkd[program:beanstalkd] directory = /data/beanstalkd/ command = /usr/local/beanstalkd/bin/beanstalkd -b /data/beanstalkd/Python2.7 支持 ThreadPoolExecutor 的话还需要 futures 包pip install futures上Server端代码import time import tempfile import libtorrent import os import os.path as path import shutil from concurrent import futures import beanstalkc def hash2torrent(torrent_hash, timeout = None): torrent_hash = torrent_hash.lower() print("start download: %s" % (torrent_hash)) magnet = "magnet:?xt=urn:btih:" + torrent_hash directory = path.join("torrents", torrent_hash[0:2], torrent_hash[-2:]) output = path.join(directory, torrent_hash + ".torrent") if not path.exists(directory): os.makedirs(directory) if path.exists(output): print('Already exists.') return output tempdir = tempfile.mkdtemp() session = libtorrent.session() session.add_dht_router('router.bittorrent.com', 6881) session.add_dht_router…

分库分表的策略
type: item
date: 2016-09-04T09:50:00+08:00
description: 1. 主键+业务虚拟键分表这种方式适合查询比较单一的业务，最大的缺点就是业务对分库分表这层是有感知:查询返回的时候需要在接口层拼接业务的真实Id根据真实业务Id查询，或者更新数据的时候，需要拆分真实业务Id，路由到数据所在表，再根据数据库Id查询虚拟场景假设我们分了1024张表，具体表结构如下：插入流程1. 插入数据，必须带有userId 2. 根据userId计算出xId xId = userId % 10000; 3. 根据xId定位数据所在表 tNum = xId % 1024; // 最简单的取模hash(具体策略由中间件决定) 4. 插入数据，返回realId realId = id + xId;单条查询流程1. 根据realId查询, 获取单张表中的Id值 id = realId / 10000; // 整除 2. 获取虚拟键xId xId = realId % 10000; 3. 根据xId定位数据所在表 tNum = xId % 1024; // 最简单的取模hash(具体策略由中间件决定) 4. 根据表和Id获取单条数据批量查询流程基本和单条查询一致，可优化的点：第3步，根据xId进行分组，将查询同一张表的query放在一次sql的查询语句中2. 主键/业务外键分表这种策略对业务代码可以无侵略性, 为避免Id冲突， 使用外部Id生成器, 以下步骤全在中间件中执行：(根据业务外键的处理同理，查询比较复杂的情况一般都是使用冗余表)虚拟场景假设我们分了1024张表，具体表结构如下：插入流程1. 从Id生成器获取Id 2. 根据Id进行hash (简单的可以使用取模), 获取数据应该插入的表名 tNum = id % 1024; 3. 插入数据表单条查询流程1. 根据Id进行hash (简单的可以使用取模), 获取数据所在表名 tNum = id % 1024; 2. 查询数据批量查询流程基本和单条查询一致，可优化的点：第1步，根据Id进行hash后进行分组，将查询同一张表的query放在一次sql的查询语句中数据的聚合在批量查询的时候，需要 order by group by distinct 的时候，需要在查询出各分表数据之后，在中间件组件中自行实现对数据的处理