这是很久之前写的一个typecho代码高亮插件了，由于是自己用的，所以高亮theme之类的都没有弄成可配置的；自定义修改需要更改theme的话，可以直接修改 HighLight/Plugin.php 文件里面引用css的代码行echo ' ' . "\n";@疯狂的杰作 同学提出是否要分享一下，所以就拿出来了。安装方法下载 HighLight.zip，解压上传到 /path/to/your/typecho/usr/plugins/ 目录下，使用 admin 帐号登录你的 typecho 后台，在插件管理里面启用他就可以啦。HighLight.zip
演示： 正则表达式测试工具功能介绍给定一个正则，生成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; }
整体流程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('router.utorrent.com', 6881) session.add_dht_router('router.bitcomet.com', 6881) session.add_dht_router('dht.transmissionbt.com', 6881) session.add_dht_router("dht.aelitis.com", 6881) session.start_dht() params = { 'save_path': tempdir, # 'storage_mode': libtorrent.storage_mode_t(2), # 'paused': False, # 'auto_managed': True, 'duplicated_is_error': True } handle = libtorrent.add_magnet_uri(session, magnet, params) cost = 0 while not handle.has_metadata(): if timeout is not None and cost > timeout: print("Timeout.") # session.pause() session.remove_torrent(handle) shutil.rmtree(tempdir) return None time.sleep(1) cost = cost + 1 # session.pause() print("Downloaded. %d" % (cost)) # print 'got metadata, starting torrent download...' # while handle.status().state != libtorrent.torrent_status.seeding: # s = handle.status() # state_str = ['queued', 'checking', 'downloading metadata', 'downloading', 'finished', 'seeding', 'allocating'] # print '%.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s %.3f' % (s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, s.num_peers, state_str[s.state], s.total_download/1000000) # time.sleep(3) torrent_info = handle.get_torrent_info() torrent_file = libtorrent.create_torrent(torrent_info) torrent_content = libtorrent.bencode(torrent_file.generate()) with open(output, "wb") as f: f.write(torrent_content) f.close() session.remove_torrent(handle) shutil.rmtree(tempdir) return output if __name__ == '__main__': beanstalk = beanstalkc.Connection(host='localhost', port=11300) timeout = None with futures.ProcessPoolExecutor(10) as executor: while True: job = beanstalk.reserve() torrent_hash = job.body job.delete() executor.submit(hash2torrent, torrent_hash, timeout)实测，平均每个种子的下载时间需要 15 分钟左右。
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 的时候，需要在查询出各分表数据之后，在中间件组件中自行实现对数据的处理