UTF8 encoding is longer than the max length 32766

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因:同事在向ES插入数据时,收到了如下错误 mapping结构如下: { "test": { "mappings": { "test_ignore32766": { "properties": { "message": { "type": "string", "index": "not_analyzed" } } } } } } { "error": "RemoteTransportException[[Pietro Maximoff][inet[/10.1.1.51:9300]][indices:data/write/index]]; nested: IllegalArgumentException[Document contains at least one immense term in field=\"message\" (whose UTF8 encoding is longer than the max length 32766), all of which were skipped. Please correct the analyzer to not produce such terms. The prefix of the first immense term is: '[-28, -72, -83, -27, -101, -67, -25, -69, -113, -26, -75, -114, -26, -83, -93, -27, -100, -88, -25, -69, -113, -27, -114, -122, -26, -106, -80, -28, -72, -128]...', original message: bytes can be at most 32766 in length; got 69345]; nested: MaxBytesLengthExceededException[bytes can be at most 32766 in length; got 69345]; ", "status": 400 } 此问题的原因是这样的,message字段设置为not_analyzed,表示对这个字段不做分词索引,但对这个字段本身仍然是要索引的,也就说可以用term进行搜索 ...

January 1, 2018 · 1 min

tornado 数据库初始化

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 在使用tornado构建的web服务中,我们常常需要对数据库进行访问,如何数据连接才是最为友好的方式,我们一般写法可能是这样的 db.py class DB(object): def __init__(self): self.mysql_db = MySQLDatabase(host=mysql_conf['host'], user=mysql_conf['username'], passwd=mysql_conf['password'], database='test') self.cache_redis = Redis(host=redis_conf['host'], port=redis_conf['port'], db=redis_conf['db']) 然后 import tornado.ioloop import tornado.web from db import DB db = DB() # ***注意这里*** class MainHandler(tornado.web.RequestHandler): def get(self): db.mysql_db.excute() ... application = tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": print 'starting....' application.listen(8090) tornado.ioloop.IOLoop.instance().start() 这个写法一般情况下并不会出问题,因为tornado是基于epoll模型的,整个tornado是单线程的,逐个的处理每一个收到的Event,不会出现对数据库连接的并发访问,也就不存在线程安全问题 但是db作为一个模块中的变量暴露在外部显得非常突兀,一种更内聚的做法,可能是这样 from db import DB class MainHandler(tornado.web.RequestHandler): def initialize(self): self.db = DB() # ***留意这里*** def get(self): self.db.mysql_db.excute() ... application = tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": print 'starting....' application.listen(8090) tornado.ioloop.IOLoop.instance().start() initialize(self) 是 RequestHandler 中的预留方法,供子类覆盖,用于执行数据库等初始化动作, 只会在对应的handler被初始化时,调用有且一次 ...

January 1, 2018 · 2 min

算法题(3)

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 在不考虑闰年,润日的情况下计算某人的下一次生日 from datetime import datetime, timedelta def solve(birthday): now = datetime.now() now = datetime(now.year, now.month, now.day) year = (now.year - birthday.year) + birthday.year x = datetime(year, birthday.month, birthday.day) if x < now: x = datetime(x.year + 1 , x.month, x.day ) return x else: return x b1 = datetime(1985, 11, 1) print solve(b1) b2 = datetime(1982, 3, 15) print solve(b2) b3 = datetime(1985, 7, 15) print solve(b3) ~

January 1, 2018 · 1 min

做了个工具类的小网站---tool.vearne.cc

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 欢迎大家使用 http://tool.vearne.cc/ 大家有什么工具类的需要,也可以给我评论,我会抽空往上加

January 1, 2018 · 1 min

《人月神话》读书总结

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 人月神话的说明,为落后项目增加人手,会导致额外的任务分配开销,协作开发的沟通成本。新分配的人员还需要重新熟悉项目。这就像5核CPU,并不能是5倍的单核CPU的性能。(资源竞争,互斥等等引起的) 同样有2年经验且受同样培训的情况下,优秀的专业程序员可以是较差程序员的10倍。 概念完整性是系统设计中最重要的考虑因素。要形成整个系统的概念完整性,就必须实施贵族式的专制。设计工作职能由一个或者具有共识的小型团队来完成 功能数量和理解上的复杂程度的比值可以作为衡量系统易用性的一种指标 对于大型项目,系统结构设计和具体实现相分离是获得概念完整性的强有力的方法。系统结构设计可以理解为,定义不同功能模块的职责划分,模块之间的接口规范。系统结构设计是针对系统的高度抽象,有点像java中的中的接口和实现类。(比如,只定义,这里需要一个数据库,至于数据库的选型,可以在实现阶段再考虑 牢记开发人员承担创造性的实现责任,架构师只能提出建议 团队组织的目标是为了减少必要的交流和协作量 传统的树状组织反映了权力的结构原理–不允许双重领导 在大型团队中,各个小组倾向于不断的局部化,以满足自己的目标,而较少考虑对用户的整体影响。这种方向性的问题是大型项目的主要危险 从系统整体出发以及面向用户的态度是软件编程管理人员最重要的职能。 构建独立小型程序的数据(开发时间)不适用大型系统项目。程序开发时间随程序规模的增长,呈指数增长。一般为指数约为1.5,大量时间消耗在集成测试中。 从文档层面来讲,我倾向于同时有设计文档和用户使用文档 设计文档针对开发人员,用户使用文档针对用户(客户) 最好的方式是,在代码中嵌入注释,然后自动生成文档

January 1, 2018 · 1 min

算法题(4)

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 题目: 有十个球编号分别为 0 ~ n - 1 ,放在袋中,任意抓2个,求所有可能的情况 def choice2(n): ll = [] for i in range(n): for j in range(i+1, n): ll.append((i, j)) return ll res = choice2(10) print len(res)

January 1, 2018 · 1 min

算法题(5)

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 题目: 已知一条线段从0 到 10000,给定一个L线段(x,y), 找出所有包含线段L线段 如下图所示,假定 (x, y) 为 (2,4) , 所有能否覆盖L线段的组合为 (0, 4) (0, 5) (0, 6) (1, 4) (1, 5) (1, 6) (2, 4) (2, 5) (2, 6) 解题思路: 观察线段可以看出所有能否覆盖L线段的组合(t1, t2), 左侧的坐标点t1必须满足 0 <= t1 <= x 右侧的坐标点t2 必须满足 y<= t2 <= 10000 def find_segment(x, y): res_list = [] for t1 in range(0, x + 1): for t2 in range(y, 10000 + 1): res_list.append((t1, t2)) return res_list print find_segment(2, 4) 如果要求所有重叠的线段,该怎么做?

January 1, 2018 · 1 min

gitlab安装

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 安装gitlab社区版 参考资料: 非常重要 https://about.gitlab.com/downloads/#ubuntu1404 我是直接在ubuntu14.04上安装的 PS:官方文档是最有价值的,我来当下搬运工 1. 安装必要的包 sudo apt-get install curl openssh-server ca-certificates postfix 其中 postfix 是邮件发送程序 ca-certificates使用来对公钥进行验证的 2. 安装gitlab社区版 curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash sudo apt-get install gitlab-ce 3. 安装启动gitlab sudo gitlab-ctl reconfigure 4. 访问gitlab主页 经过观察我发现gitlab默认会在机器上安装 1)Ruby 2)Redis 安装路径 /var/opt/gitlab/redis 默认监听在unix域套接字上(还好没暴露在公网上) /var/opt/gitlab/redis/redis.socket 3)PostgreSQL 4)Nginx 安装路径 /opt/gitlab/embedded/sbin/nginx 配置文件路径 /var/opt/gitlab/nginx/conf nginx作为反向代理,后面挂有用unicorn启动的ruby进程,提供web服务 默认nginx需要占用80端口,所以这有可能会与你原先配置的web服务造成冲突 upstream gitlab-workhorse { server unix:/var/opt/gitlab/gitlab-workhorse/socket; } server { listen *:8000; # 默认为listen *:80 server_name code.xxx.club; # ***必须修改*** 默认为主机名 } 这里必须修改server_name,代码库中的git project地址都依赖此值 ...

January 1, 2018 · 1 min

火车票购票问题2

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 看过火车票购票问题1 的朋友可能已经发现,还有可以优化的方案 方案1: 在处理购票请求的后期,某些站点区间可用的票数已经为0, 那么后续再有类似请求时,可以直接返回失败 这里的特殊情况是,如果有人退票,则某个站点区间又会有可卖的票,可以通过在购票高峰期限制退票来排除这个特殊情况。 对应文件 sell2.py # -*- coding: utf-8 -*- ############################################################ # 假定站点编号从 1 ~ 10 # 共20节车厢, 每个车厢20排 # 编号形如 # 1A 1B 1C 1D 1F # 2A 2B 2C 2D 2F # ... # 20A 20B 20C 20D 20F # 20 * 5 * 20 = 2000个座位 # 其实座位编号完全可以从 0 ~ 1999, 并不影响我们对问题本身的分析 ############################################################ import time MAX_CARRIAGE_NUM = 20 MAX_ROW_NUM = 20 MAX_SITE_INDEX = 10 class Seg(object): def __init__(self, carriage_no, seat_no, start_site, end_site): # 车厢编号 self.carriage_no = carriage_no # 座位编号 self.seat_no = seat_no # 完整编号 self.no = str(carriage_no) + '-' + seat_no # 能够售卖的开始站序号 int self.start_site = start_site # 能够售卖的终点站序号 int self.end_site = end_site def __str__(self): return str((self.no, self.start_site, self.end_site)) def init(): ticket_dict = {} for i in range(1, MAX_SITE_INDEX): for j in range(i + 1, MAX_SITE_INDEX + 1): ticket_dict[(i, j)] = [] for i in range(1, MAX_CARRIAGE_NUM + 1): for row in range(1, MAX_ROW_NUM + 1): for col in ['A', 'B', 'C', 'D', 'F']: # 每个座位都可以出售从s1 到 s10的车票 key = (1, 10) # print Seg(i, str(row) + col, 1, 10) ticket_dict[key].append(Seg(i, str(row) + col, 1, 10)) return ticket_dict def sell(ticket_dict, start, end, sellout_dict): ''' :param ticket_dict: :param start: 购票的起始站 :param end: 购票的终点站 :return: ''' if sellout_dict.get((start, end), False): return None # 需要找到一个有票的站点区间覆盖目标站点区间 # 所有可能的起始站 site_start = [] x = 1 while x <= start: site_start.append(x) x += 1 site_start.reverse() # 所有可能的终点站 site_end = [] y = end while y <= MAX_SITE_INDEX: site_end.append(y) y += 1 ticket = None for x in site_start: for y in site_end: if len(ticket_dict[(x, y)]) > 0: ticket = ticket_dict[(x, y)].pop() if ticket: # 判断一下这个座位的站点区间是否被完全用完了 # 如果没有还需要把新生成的余票间存回去 if start > x: temp = Seg(ticket.carriage_no, ticket.seat_no, x, start) ticket_dict[(x, start)].append(temp) if y > end: temp = Seg(ticket.carriage_no, ticket.seat_no, end, y) ticket_dict[(end, y)].append(temp) return Seg(ticket.carriage_no, ticket.seat_no, start, end) # 对于(start, end), 没有可以卖的票 # 那说明所有覆盖 (start, end) 的站点区间都没有票了 for x in site_start: for y in site_end: sellout_dict[(x, y)] = True return None def print_residual(ticket_dict): print '------------余票情况-------------' for key in ticket_dict: if ticket_dict[key]: print key, len(ticket_dict[key]) if __name__ == '__main__': ticket_dict = init() sellout_dict = {} t1 = time.time() with open('req.csv') as fp: for line in fp: ll = line.split(',') user = ll[0] start = int(ll[1]) end = int(ll[2]) ticket = sell(ticket_dict, start, end, sellout_dict) print '#' * 100 print line.strip() if ticket: print user, "bought", ticket print_residual(ticket_dict) # time.sleep(2) t2 = time.time() print t2 - t1 经过测试,速度又提升了20% ,处理10w请求只用了1秒多 ...

January 1, 2018 · 2 min

火车票购票问题1

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前段时间看了知乎的一篇文章 12306 外包给阿里巴巴、IBM 等大企业做是否可行? 李爱吉对于买票问题的优化算法,给了我非常大的启示,我决定实现出来,以享众人。 1.火车票购票问题描述 假定该车次有s1、s2、s3 … 到s6个站点,共6个站点 对于任意一个座位,初始时它可以出售的有效区间都是从首站s1到末站sN, 但是如果该座位某一段被售出,能出售有效区间就变化了。 如果上图所示: 红色的区段表示已经售出,该座位的情况是 站点2 -> 站点4 的票已经被售出 站点1 -> 站点2 的票仍可售卖 站点4 -> 站点6 的票仍可售卖 以某趟车次的车票出售为例,假定该车次有20节车厢,每节车厢有100个座位,那么共有座位 100 * 20 = 2000座位 那么在购票时(从站点x到站点y),都必须遍历这2000个座位,以找到一个合适的座位,由于有的座位的某些区段已经被售出,实际遍历的查询次数肯定大于2000次 这里把座位数记为m 查询n次的时间复杂度就是O(mn) 2. 查询优化 假定某趟车次共有10个站点,那么根据排列组合,能够售出车票,出发站、到达站的组合只能有 10 *(10 - 1) / 2 = 45 种 优化方法: 由于组合是有限的,我们可以把每个座位可以售卖的站点区间索引起来,当一个购票请求(x,y)从站点x到站点y 到达时,首先去查询 对应站点区间是否有票,如果没有就尝试在能够覆盖(x,y) 的站点区间的索引中去寻找。 # -*- coding: utf-8 -*- ############################################################ # 假定站点编号从 1 ~ 10 # 共20节车厢, 每个车厢20排 # 编号形如 # 1A 1B 1C 1D 1F # 2A 2B 2C 2D 2F # ... # 20A 20B 20C 20D 20F # 20 * 5 * 20 = 2000个座位 # 其实座位编号完全可以从 0 ~ 1999, 并不影响我们对问题本身的分析 ############################################################ import time MAX_CARRIAGE_NUM = 20 MAX_ROW_NUM = 20 MAX_SITE_INDEX = 10 class Seg(object): def __init__(self, carriage_no, seat_no, start_site, end_site): # 车厢编号 self.carriage_no = carriage_no # 座位编号 self.seat_no = seat_no # 完整编号 self.no = str(carriage_no) + '-' + seat_no # 能够售卖的开始站序号 int self.start_site = start_site # 能够售卖的终点站序号 int self.end_site = end_site def __str__(self): return str((self.no, self.start_site, self.end_site)) def init(): ticket_dict = {} for i in range(1, MAX_SITE_INDEX): for j in range(i + 1, MAX_SITE_INDEX + 1): ticket_dict[(i, j)] = [] for i in range(1, MAX_CARRIAGE_NUM + 1): for row in range(1, MAX_ROW_NUM + 1): for col in ['A', 'B', 'C', 'D', 'F']: # 每个座位都可以出售从s1 到 s10的车票 key = (1, 10) # print Seg(i, str(row) + col, 1, 10) ticket_dict[key].append(Seg(i, str(row) + col, 1, 10)) return ticket_dict def sell(ticket_dict, start, end): ''' :param ticket_dict: :param start: 购票的起始站 :param end: 购票的终点站 :return: ''' # 需要找到一个有票的站点区间覆盖目标站点区间 # 所有可能的起始站 site_start = [] x = 1 while x <= start: site_start.append(x) x += 1 site_start.reverse() # 所有可能的终点站 site_end = [] y = end while y <= MAX_SITE_INDEX: site_end.append(y) y += 1 # print 'site_start', site_start # print 'site_end', site_end for x in site_start: for y in site_end: ticket = None if len(ticket_dict[(x, y)]) > 0: ticket = ticket_dict[(x, y)].pop() if ticket: # 判断一下这个座位的站点区间是否被完全用完了 # 如果没有还需要把新生成的余票间存回去 if start > x: temp = Seg(ticket.carriage_no, ticket.seat_no, x, start) ticket_dict[(x, start)].append(temp) if y > end: temp = Seg(ticket.carriage_no, ticket.seat_no, end, y) ticket_dict[(end, y)].append(temp) return Seg(ticket.carriage_no, ticket.seat_no, start, end) return None def print_residual(ticket_dict): print '------------余票情况-------------' for key in ticket_dict: if ticket_dict[key]: print key, len(ticket_dict[key]) if __name__ == '__main__': ticket_dict = init() t1 = time.time() with open('req.csv') as fp: for line in fp: ll = line.split(',') user = ll[0] start = int(ll[1]) end = int(ll[2]) ticket = sell(ticket_dict, start, end) if ticket: print '#' * 100 print line.strip() print user, "bought", ticket print_residual(ticket_dict) # time.sleep(2) t2 = time.time() print t2 - t1 我随机生成了一个测试文件req.csv 来模拟用户的购票行为, 测试结果表明, 及时在单线程的情况下,只用了不到2秒就处理完了10w 个请求。这个速度已经足够快了,下一次我们再来对程序进行优化。 ...

January 1, 2018 · 3 min