装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,
装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、
缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能
本身无关的雷同代码并继续重用.
装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因为就产生了装饰器,使得其满足:
git cherry-pick可以理解为”挑拣”提交,它会获取某一个分支的单笔提交,并作为一个新的提交引入到你当前分支上。
、当我们需要在本地合入其他分支的提交时,如果我们不想对整个分支进行合并,而是只想将某一次提交合入到本地当前分支上,
那么就要使用git cherry-pick了。
git cherry-pick [] ...
常用options:
--quit 退出当前的chery-pick序列
--continue 继续当前的chery-pick序列
--abort 取消当前的chery-pick序列,恢复当前分支
-n, --no-commit 不自动提交
-e, --edit 编辑提交信息
git cherry-pick 2555c6e
当cherry-pick时,没有成功自动提交,这说明存在冲突,因此首先需要解决冲突,
解决冲突后需要git commit手动进行提交:
$ git commit
[branch1 790f431] [Description]:branch2 commit 2
Date: Fri Jul 13 18:36:44 2018 +0800
1 file changed, 1 insertion(+)
create mode 100644 only-for-branch2.txt
或者git add .后直接使用git cherry-pick --continue继续。
git reset --hard HEAD~
git cherry-pick -n 23d9422
git cherry-pick -e 23d9422
git cherry-pick --quit
git cherry-pick --abort
git cherry-pick master
# 如果在git cherry-pick后加一个分支名,则表示将该分支顶端提交进cherry-pick
$ git cherry-pick master
1,commit 之前的撤销
未添加至暂存区的撤销(add 之前)
git status
git checkout .
已添加至暂存区的撤销(add 之后,有或者没有commit操作都可以执行)
git reflog
git reset --hard bca6882(relog 中展示的commitId)
2,push之后的撤销
(
git add .
git commit -m "commit"
git push origin brandname
)
等一系列操作后的撤销
不想将本次的操作生效
git revert commitId(提交的id)
git push origin brandname
此次操作就会撤销掉上一次的push
在这个分支上,会生成一条revert 的提交记录
revert 是负负得正,什么意思呢,就是说第一次revert的时候,
上一次push的命令就失效了,再一次revert 后,会回退到之前的之前的状态,
详细的介绍一下
比如我操作一个文件UserController.java
将userName 改为username 经过一系列的git操作
git add .
git commit -m "commit"
git push orgin
后,再进行git revert commitId
再进行git push origin branchname
userName 还是userName,
如果我再revert 的时候,
git revert
git push origin branchname
将userName 还是改为username.
总结为:
git revert 为奇数时生效,为偶数时,失效
3,git 回滚:
将git 回滚到某一次commit操作,在该commitId之前的操作,将全部失效(此方法不建议使用,有风险),
git reset --hard commitId
git push origin branchname --force (强制覆盖)
因为是不可逆的,不建议使用
git reflog
git reset --hard bca6882(relog 中展示的commitId)
git push origin branchname --force
git revert commitId
git push origin branchname
二者区别:
revert 是放弃指定提交的修改,但是会生成一次新的提交,需要填写提交注释,以前的历史记录都在;
reset 是指将HEAD指针指到指定提交,历史记录中不会出现放弃的提交记录。
Git中tag的用法及作用
首先说一下作用:Git 中的tag指向一次commit的id,通常用来给开发分支做一个标记,如标记一个版本号。
下面就说一下具体的用法:
1.添加标签: git tag -a version -m "note" commitId
注解:git tag 是打标签的命令,-a 是添加标签,其后要跟新标签号,-m 及后面的字符串是对该标签的注释。
2.提交标签到远程仓库
:git push origin -tags注解:就像git push origin master 把本地修改提交到远程仓库一样,-tags可以把本地的打的标签全部提交到远程仓库。
3.删除标签:git tag -d
version注解:-d 表示删除,后面跟要删除的tag名字
4.删除远程标签:git push origin :refs/tags/version注解:就像git push origin :branch_1 可以删除远程仓库的分支branch_1一样, 冒号前为空表示删除远程仓库的tag。
5.查看标签:git tag或者git
tag -l
git tag -a version -m "note" commitId
git show version
git push or --tags
git tag -d version
git push or :refs/tags/version
$ git checkout mywork
$ git rebase origin
git add -u
git rebase --continue
git rebase --abort
Lucene实现快速搜索的核心就是倒排索引,那什么是倒排索引(单词到文档id的关联关系)一个字段有一个自己的倒排索引。18,20这些叫做term,而[1,3]就是posting list。Posting list就是一个int的数组,
存储了所有符合某个term的文档id和term Index
假设我们有很多个term,比如:
Carla,Sara,Elin,Ada,Patty,Kate,Selena
如果按照这样的顺序排列,找出某个特定的term一定很慢,因为term没有排序,需要全部过滤一遍才能找出特定的term。排序之后就变成了:
Ada,Carla,Elin,Kate,Patty,Sara,Selena
这样我们可以用二分查找的方式,比全遍历更快地找出目标的term。这个就是 term dictionary。有了term dictionary之后,可以用 logN 次磁盘查找得到目标。但是磁盘的随机读操作仍然是非常昂贵的(一次random access大概需要10ms的时间)。
所以尽量少的读磁盘,有必要把一些数据缓存到内存里。但是整个term dictionary本身又太大了,无法完整地放到内存里。于是就有了term index。term index有点像一本字典的大的章节表。比如:
A开头的term ……………. Xxx页
C开头的term ……………. Xxx页
E开头的term ……………. Xxx页
如果所有的term都是英文字符的话,可能这个term index就真的是26个英文字符表构成的了。但是实际的情况是,term未必都是英文字符,term可以是任意的byte数组。而且26个英文字符也未必是每一个字符都有均等的term,比如x字符开头的term可能一个都没有,而s开头的term又特别多。实际的term index是一棵树。
lucene/Elasticsearch就是尽量将磁盘里的东西搬进内存(term index是放在内存里面的),
减少磁盘随机读取次数(同时也利用磁盘顺序读特性),结合各种压缩算法(term index用FST进行压缩, term dictionary压缩),高效使用内存,从而达到快速搜索的特性。
大大提升开发效率
让应用开发更加规范、拓展性更强
让程序员把更多的精力放在业务逻辑的实现上,而不是重复、而复杂的基础环境上(比如web服务器、底层实现等)
天生异步,性能强悍是 Tornado 的名片,然而 Tornado 相比 Django 是较为原始的框架,
诸多内容需要自己去处理。当然,随着项目越来越大,框架能够提供的功能占比越来越小,更多的内容需要团队自己去实现,而大项目往往需要性能的保证,这时候 Tornado 就是比较好的选择。Tornado项目代表:知乎
集群是个物理形态,分布式是个工作方式。
分布式:一个业务分拆多个子业务,部署在不同的服务器上
集群:同一个业务,部署在多个服务器上
分布式中的每一个节点,都可以做集群。而集群并不一定就是分布式的。
分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。
好的设计应该是分布式和集群的结合,先分布式再集群,具体实现就是业务拆分成很多子业务,然后针对每个子业务进行集群部署,
这样每个子业务如果出了问题,整个系统完全不会受影响
微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。
在所有情况下,每个任务代表着一个小的业务能力。
集群模式是不同服务器部署同一套服务对外访问,实现服务的负载均衡。区别集群的方式是根据部署多台服务器业务是否相同。
注:集群模式需要做好session共享,确保在不同服务器切换的过程中不会因为没有获取到session而中止退出服务。
一般配置Nginx*的负载容器实现:静态资源缓存、Session共享可以附带实现,Nginx支持5000个并发量。
快排在最糟糕得情况下时间复杂度是O(n²),平均的复杂度是O(nlogn),
这里的n和logn, 分别代表了调用栈的高度,和完成每层的时间,在a取
数组的第一项时候,是最糟的情况,完成每层需要的时间是n,栈的高
读是n,时间复杂度就是n²,当取中间的值得时候,完成每层的时间是
n,但是调用栈的高度变成了logn,所以这个时候时间复杂度是nlogn
退出服务。
一般配置Nginx*的负载容器实现:静态资源缓存、Session共享可以附带实现,Nginx支持5000个并发量。
快排在最糟糕得情况下时间复杂度是O(n²),平均的复杂度是O(nlogn),
这里的n和logn, 分别代表了调用栈的高度,和完成每层的时间,在a取
数组的第一项时候,是最糟的情况,完成每层需要的时间是n,栈的高
读是n,时间复杂度就是n²,当取中间的值得时候,完成每层的时间是
n,但是调用栈的高度变成了logn,所以这个时候时间复杂度是nlogn
冒泡排序的时间复杂度是O(n^2)