做了个工具类的小网站---tool.vearne.cc
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 欢迎大家使用 http://tool.vearne.cc/ 大家有什么工具类的需要,也可以给我评论,我会抽空往上加
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 欢迎大家使用 http://tool.vearne.cc/ 大家有什么工具类的需要,也可以给我评论,我会抽空往上加
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 人月神话的说明,为落后项目增加人手,会导致额外的任务分配开销,协作开发的沟通成本。新分配的人员还需要重新熟悉项目。这就像5核CPU,并不能是5倍的单核CPU的性能。(资源竞争,互斥等等引起的) 同样有2年经验且受同样培训的情况下,优秀的专业程序员可以是较差程序员的10倍。 概念完整性是系统设计中最重要的考虑因素。要形成整个系统的概念完整性,就必须实施贵族式的专制。设计工作职能由一个或者具有共识的小型团队来完成 功能数量和理解上的复杂程度的比值可以作为衡量系统易用性的一种指标 对于大型项目,系统结构设计和具体实现相分离是获得概念完整性的强有力的方法。系统结构设计可以理解为,定义不同功能模块的职责划分,模块之间的接口规范。系统结构设计是针对系统的高度抽象,有点像java中的中的接口和实现类。(比如,只定义,这里需要一个数据库,至于数据库的选型,可以在实现阶段再考虑 牢记开发人员承担创造性的实现责任,架构师只能提出建议 团队组织的目标是为了减少必要的交流和协作量 传统的树状组织反映了权力的结构原理–不允许双重领导 在大型团队中,各个小组倾向于不断的局部化,以满足自己的目标,而较少考虑对用户的整体影响。这种方向性的问题是大型项目的主要危险 从系统整体出发以及面向用户的态度是软件编程管理人员最重要的职能。 构建独立小型程序的数据(开发时间)不适用大型系统项目。程序开发时间随程序规模的增长,呈指数增长。一般为指数约为1.5,大量时间消耗在集成测试中。 从文档层面来讲,我倾向于同时有设计文档和用户使用文档 设计文档针对开发人员,用户使用文档针对用户(客户) 最好的方式是,在代码中嵌入注释,然后自动生成文档
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | 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)
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | 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) 如果要求所有重叠的线段,该怎么做?
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | 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地址都依赖此值 ...
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | 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秒多 ...
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | 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 个请求。这个速度已经足够快了,下一次我们再来对程序进行优化。 ...
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因:之前的相当长时间一直在寻找mysql的分布式解决方案,一直没有特别理想的答案,有同事给推荐了kingshard,所以决定一探究竟。 1.安装 机器共3台 机器 IP 说明 机器1 192.168.122.1 安装kingshard 机器1 192.168.122.3 安装mysql实例(node1) master 没有slave 机器1 192.168.122.4 安装mysql实例(node2) master 没有slave 安装请参考官方资料 https://github.com/flike/kingshard/blob/master/doc/KingDoc/kingshard_install_document.md 我安装的kingshard 2016年8月9日的版本,目前kingshard还没有参数或配置,把kingshard以后台守护进程的方式启动,因此作者建议使用supervisor进行管理。 因为我主要是为了观察效果,所以直接在终端中启动 ./kingshard -config=../etc/ks.yaml 以下是我的配置文件 ks.yaml # server listen addr addr : 0.0.0.0:9696 # server user and password user : kingshard password : kingshard # if set log_path, the sql log will write into log_path/sql.log,the system log # will write into log_path/sys.log #log_path : /Users/flike/log # log level[debug|info|warn|error],default error log_level : debug # if set log_sql(on|off) off,the sql log will not output log_sql: on # only log the query that take more than slow_log_time ms #slow_log_time : 100 # the path of blacklist sql file # all these sqls in the file will been forbidden by kingshard #blacklist_sql_file: /Users/flike/blacklist # only allow this ip list ip to connect kingshard #allow_ips: 127.0.0.1 # the charset of kingshard, if you don't set this item # the default charset of kingshard is utf8. #proxy_charset: gbk # node is an agenda for real remote mysql server. nodes : - name : node1 # default max conns for mysql server max_conns_limit : 32 # all mysql in a node must have the same user and password user : kingshard password : kingshard # master represents a real mysql master server master : 192.168.122.3:3306 # slave represents a real mysql salve server,and the number after '@' is # read load weight of this slave. #slave : 192.168.59.101:3307@2,192.168.59.101:3307@3 down_after_noalive : 32 - name : node2 # default max conns for mysql server max_conns_limit : 32 # all mysql in a node must have the same user and password user : kingshard password : kingshard # master represents a real mysql master server master : 192.168.122.4:3306 # slave represents a real mysql salve server slave : # down mysql after N seconds noalive # 0 will no down down_after_noalive: 32 # schema defines sharding rules, the db is the sharding table database. schema : db : kingshard nodes: [node1,node2] default: node1 shard: - table: test_shard_day key: mtime # 指定分表所用的时间字段 type: date_day nodes: [node1,node2] date_range: [20160306-20160307,20160308-20160309] 由于我主要是用到kingshard的按时间分表功能,所以这里只配置了 ...
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 删除image docker rmi myapp/base 2. 给image 打tag docker tag 4424b58cae58 myapp/base 3. 容器的存储层保存下来成为镜像 docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] docker commit webserver nginx:v2
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 我需要得到peewee对象的clone对象,写个简单的小程序 def clone(instance): obj = instance.__class__() # print a._meta.fields data = getattr(instance, "_data") for key in a._meta.fields: # print key if key != 'id': setattr(obj, key, data[key]) return obj