66 Matching Annotations
  1. Mar 2019
    1. 创建vim session文件 :mks filename, 重写session :mks! filename,  载入session vim -S sessionFile

      该命令可以将当前Vim打开的窗口以文件的方式进行保存,当下次打开时直接以保存时的状态打开

      保存当前会话session: :mks filename

      更新当前会话session: :mks! filename

      载入会话session: vim -S sessionFile

  2. Oct 2018
  3. Aug 2018
    1. mysql_install_db --basedir=/usr --datadir=/data/mysql_3307/mysql

      新增数据端口在本机时,需要先执行安装才能进行

    2.    mysqladmin -uroot -S /data/mysql_3307/mysql.sock shutdown

      这里指定sock,则可以直接免密登录账号

    1. Zvalue是用来保存一个变量的实际数据。因为要存储多种类型,所以zvalue是一个union,也由此实现了弱类型。

      这里是关键union是实现弱类型的点睛之笔

  4. May 2018
    1. 注意:这里除非是使用了索引会启用行级锁,不然是会使用表锁,将整张表都锁住。

      这里需要注意下

    1. for( $i = 1; $i <= 3 ; $i++ ){ $pid = pcntl_fork(); if( $pid > 0 ){ // do nothing ... } else if( 0 == $pid ){ echo "儿子".PHP_EOL; exit; } }

      至于在fork子进程退出的时候 i=1 =2 =3的时候都只有一个父进程fork一个子进程 所以只有三个儿子

    1. FFMPEG  -i  uploadfile/video/test.wmv -c:v libx264 -strict -2 uploadfile/mp4/test.mp4

      可以将视频类型、视频编码进行重新转码操作

    1. _, _, exc_tb = sys.exc_info()

      返回结果为元组时,不需要关注的值,可以使用『_』来不获取该值

  5. Apr 2018
    1. 如何将开发的分支代码,merge到主干上?

      • 创建新分支开发

      $ git checkout -b dev

      • 在新分支下新增测试文件

      $ echo 'Readme' > ./readme.txt

      $ git add readme.text

      • 将文件提交到分支

      $ git commit -m "dev branch test"

      • 分支开发工作完成,我们现在可以切回 master 分支

      $ git checkout master

      • 将 dev 分支的工作成果合并到 master 分支上

      $ git merge dev

      • 合并完成之后,dev 分支没有作用就可以放心删除了

      $ git branch -d dev

      • 删除后,查看剩余分支列表,就只剩下 master 分支了

      $ git branch

    2. git checkout -b dev

      创建新的开发分支进行开发,与下面一组命令相同

      $ git branch dev $ git checkout dev

    3. $ git branch dev $ git checkout dev Switched to branch 'dev'

      $$git checkout$$

      命令加上 \(-b\) 参数表示创建并切换

      该命令与 \(git checkout -b dev\) 相同

  6. Mar 2018
    1. 先说说原理。本地过程调用RPC就是要像调用本地的函数一样去调远程函数。在研究RPC前,我们先看看本地调用是怎么调的。假设我们要调用函数Multiply来计算lvalue * rvalue的结果:1 int Multiply(int l, int r) { 2 int y = l * r; 3 return y; 4 } 5 6 int lvalue = 10; 7 int rvalue = 20; 8 int l_times_r = Multiply(lvalue, rvalue); 那么在第8行时,我们实际上执行了以下操作:将 lvalue 和 rvalue 的值压栈进入Multiply函数,取出栈中的值10 和 20,将其赋予 l 和 r执行第2行代码,计算 l * r ,并将结果存在 y将 y 的值压栈,然后从Multiply返回第8行,从栈中取出返回值 200 ,并赋值给 l_times_r以上5步就是执行本地调用的过程。远程过程调用带来的新问题在远程调用时,我们需要执行的函数体是在远程的机器上的,也就是说,Multiply是在另一个进程中执行的。这就带来了几个新问题:Call ID映射。我们怎么告诉远程机器我们要调用Multiply,而不是Add或者FooBar呢?在本地调用中,函数体是直接通过函数指针来指定的,我们调用Multiply,编译器就自动帮我们调用它相应的函数指针。但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的。所以,在RPC中,所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,必须附上这个ID。然后我们还需要在客户端和服务端分别维护一个 {函数 <--> Call ID} 的对应表。两者的表不一定需要完全相同,但相同的函数对应的Call ID必须相同。当客户端需要进行远程调用时,它就查一下这个表,找出相应的Call ID,然后把它传给服务端,服务端也通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。序列化和反序列化。客户端怎么把参数值传给远程的函数呢?在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。甚至有时候客户端和服务端使用的都不是同一种语言(比如服务端用C++,客户端用Java或者Python)。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。这个过程叫序列化和反序列化。同理,从服务端返回的值也需要序列化反序列化的过程。网络传输。远程调用往往用在网络上,客户端和服务端是通过网络连接的。所有的数据都需要通过网络传输,因此就需要有一个网络传输层。网络传输层需要把Call ID和序列化后的参数字节流传给服务端,然后再把序列化后的调用结果传回客户端。只要能完成这两者的,都可以作为传输层使用。因此,它所使用的协议其实是不限的,能完成传输就行。尽管大部分RPC框架都使用TCP协议,但其实UDP也可以,而gRPC干脆就用了HTTP2。Java的Netty也属于这层的东西。所以,要实现一个RPC框架,其实只需要把以上三点实现了就基本完成了。Call ID映射可以直接使用函数字符串,也可以使用整数ID。映射表一般就是一个哈希表。序列化反序列化可以自己写,也可以使用Protobuf或者FlatBuffers之类的。网络传输库可以自己写socket,或者用asio,ZeroMQ,Netty之类。

      事例举得不错

    2. RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据

      这里的介绍我觉得更直白的表现出与http协议的区别,当然从网络七层传输协议上来将也是一种解释,但我更喜欢此处的介绍

    1. 允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

      简单的实现:

      1. 定义一个抽象类,然后再定义N个具体操作类,集成抽象类中的公共方法
      2. 定义一个装饰类,该类同样继承上面的抽象类,然后参照工厂模式的方法,在里面实现可以实例化对应具体类
      3. 在装饰类的继承方法中,将实现具体对象的方法进行重载,并在重载代码的上下,增加需要的内容即可
    1. 可以这么简单的理解,一个类中包含了实例化各种子类的方法(功能具体实现类),然后该类中提供了一个接口,可以采用传递几个参数,就是实现对应对象的实例化

    1. 个人感觉从下面的笔记中更好理解这个模式,主要实现方式理解为:

      1. 创建一个抽象类
      2. 定义几个实现类,用于继承抽象类,并实现里面的具体方法
      3. 定义测试类,用于创建接受者对象的实例化(多个对象保存),然后,调用方法进行变量实例化对下,并调用他们的实现方法来进行发送通知
    1. blocking

      阻塞

    2. recvfrom

      接收数据

    3. 为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。

      内核对cpu上运行进程的挂起和恢复操作,称为进程切换

    1. 若二叉树为空,则空操作,否则先后序遍历左子树访问根节点,再后序遍历右子树,最后访问根节点

      后序遍历

    2. 若二叉树为空,则空操作,否则先中序遍历左子树,再访问根节点,最后中序遍历右子树

      中序遍历

    3. 若二叉树为空,则空操作,否则先访问根节点,再先序遍历左子树,最后先序遍历右子树

      先序遍历

    4. 深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为** 完全二叉树 **。

      完全二叉树

    5. 一棵深度为k,且有2^k-1个节点的二叉树称之为** 满二叉树 **;

      满二叉树

    1. pipelining

      HTTP Pipelining是这样一种技术:在等待上一个请求响应的同时,发送下一个请求。(译者注:作者这个解释并不完全正确,HTTP Pipelining其实是把多个HTTP请求放到一个TCP连接中一一发送,而在发送过程中不需要等待服务器对前一个请求的响应;只不过,客户端还是要按照发送请求的顺序来接收响应。)但就像在超市收银台或者银行柜台排队时一样,你并不知道前面的顾客是干脆利索的还是会跟收银员/柜员磨蹭到世界末日(译者注:不管怎么说,服务器(即收银员/柜员)是要按照顺序处理请求的,如果前一个请求非常耗时(顾客磨蹭),那么后续请求都会受到影响),这就是所谓的线头阻塞(Head of line blocking)。 http://blog.csdn.net/qq_28885149/article/details/52922107

    1. 如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

      这个锁就永远得不到释放了

    2. 先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。

      Redis分布式锁

    1. 但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误。

      尾递归的优点

    2. 递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。

      递归的问题点

    3. 函数调用自身,称为递归。如果尾调用自身,就称为尾递归。

      尾递归概念

    4. 尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。

      尾调用优化的精髓

    5. 函数调用会在内存形成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息

      函数调用记录在内存中的实现

    6. 尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

      尾调用的概念

    1. 汉明距离是使用在数据传输差错控制编码里面的,汉明距离是一个概念,它表示两个(相同长度)字对应位不同的数量

      解释了什么是汉明距离,即两个相同长度的字对于位不同的数量

      例: 0000000 1111111 这两个的汉明距离就是 1 + 1 + 1 + 1 + 1 + 1 + 1 = 7

    1. 这篇文章对堆和栈的解释比较明朗。

      这里指名 堆栈 是一个概念,而解决了在其他文章中说两个为不同概念的误导。

      区别:

      1. 队列先进先出,在对头做删除操作,在队尾做插入操作;
      2. 栈先进后出,在栈顶做插入和删除操作;
      3. 堆和他们不同,不存在是先进后出还是先进先出,他类似与KV存储,但是不用了需要做释放操作;
    1. 32位机器,理论上可以malloc(4G)的大小,因为2^32=4G,但事实上linux的进程地址空间是这样的:

    2. 所以经过实验,使用malloc最大能够申请的空间是3G左右,这里要注意,要使用下面这样的方式申请空间:
      int MB = 0;  
      while(malloc(1 << 20))  
      {  
              MB++;  
      }  
      printf("Allocate %d MB total\n", MB);
      
  7. Feb 2018
    1. imgHash.py

      具体实现:

      #!/usr/bin/python
      
      import glob
      import os
      import sys
      
      from PIL import Image
      
      EXTS = 'jpg', 'jpeg', 'JPG', 'JPEG', 'gif', 'GIF', 'png', 'PNG'
      
      def avhash(im):
          if not isinstance(im, Image.Image):
              im = Image.open(im)
          im = im.resize((8, 8), Image.ANTIALIAS).convert('L')
          avg = reduce(lambda x, y: x + y, im.getdata()) / 64.
          return reduce(lambda x, (y, z): x | (z << y),
                        enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())),
                        0)
      
      def hamming(h1, h2):
          h, d = 0, h1 ^ h2
          while d:
              h += 1
              d &= d - 1
          return h
      
      if __name__ == '__main__':
          if len(sys.argv) <= 1 or len(sys.argv) > 3:
              print "Usage: %s image.jpg [dir]" % sys.argv[0]
          else:
              im, wd = sys.argv[1], '.' if len(sys.argv) < 3 else sys.argv[2]
              h = avhash(im)
      
              os.chdir(wd)
              images = []
              for ext in EXTS:
                  images.extend(glob.glob('*.%s' % ext))
      
              seq = []
              prog = int(len(images) > 50 and sys.stdout.isatty())
              for f in images:
                  seq.append((f, hamming(avhash(f), h)))
                  if prog:
                      perc = 100. * prog / len(images)
                      x = int(2 * perc / 5)
                      print '\rCalculating... [' + '#' * x + ' ' * (40 - x) + ']',
                      print '%.2f%%' % perc, '(%d/%d)' % (prog, len(images)),
                      sys.stdout.flush()
                      prog += 1
      
              if prog: print
              for f, ham in sorted(seq, key=lambda i: i[1]):
                  print "%d\t%s" % (ham, f)
      

      参考代码:

      1. http://www.ruanyifeng.com/blog/2011/07/imgHash.txt
    2. "汉明距离"

      汉明距离: 在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。

      汉明重量:汉明重量是字符串相对于同样长度的零字符串的汉明距离,也就是说,它是字符串中非零的元素个数:对于二进制字符串来说,就是1的个数,所以11101的汉明重量是4。

      参考资料:

      1. 维基百科
    1. 如果我想多级排序呢,先用score排序,再用name排序:

      这是针对列表中字典排序的更高升华

    2. new_s_2 = sorted(new_s,key = lambda e:(e.__getitem__('score'),e.__getitem__('name')))

      多级排序,先用score排序,再用name排序

    1. ${FUNCNAME[@]}

      常量FUNCNAME,但是有一点区别是,它是一个数组而非字符串,其中数组的第一个元素为当前函数的名称

  8. Jan 2018
  9. Dec 2017
    1. defaults write com.apple.finder _FXShowPosixPathInTitle -bool TRUE;killall Finder

      MAC在Finder栏显示所浏览文件夹路径的方法

    1. #!/bin/sh(cat <<EOFstart(){    echo "start"}EOF) >/tmp/b

      shell 如何把多行内容输出到一个文件

    1. 0 6 * * * /root/zwk/test.sh >> /root/zwk/operate_`date +"\%Y\%m\%d"`.log 2>&1

      crontab 执行命令,将对应运行日志按照日期进行存放

  10. Nov 2017
    1. git show [commit]

      显示某次提交的元数据和内容变化

      查看某个文件在某次提交的变动信息: git show [commit] [filename]

    2. git show [commit]:[filename]

      显示某次提交时,某个文件的内容

    3. git cherry-pick [commit]

      选择一个commit,合并进当前分支

    4. git merge [branch]

      合并指定分支到当前分支

    5. git checkout [branch-name]

      新建一个分支,与指定的远程分支建立追踪关系

    6. git branch --track [branch] [remote-branch]

      新建一个分支,与指定的远程分支建立追踪关系

    7. git branch [branch] [commit]

      新建一个分支,指向指定commit

    8. git checkout -b [branch]

      新建一个分支,并切换到该分支

    9. git branch [branch-name]

      新建一个分支,但依然停留在当前分支

    10. git branch

      列出所有本地分支

    11. git log --stat

      显示commit历史,以及每次commit发生变更的文件

    12. git diff --shortstat "@{0 day ago}"

      显示今天你写了多少行代码

    13. git blame [file]

      显示指定文件是什么人在什么时间修改过

    14. $ git log -p [file]

      显示指定文件相关的每一次diff

      显示效果如下,但会显示高亮:

      commit 32e0c4f6bbb91617126b1cf2ab8c403ce7691ffe
      Author: lishuailong <lishuailong@baidu.com>
      Date:   Tue Jul 11 15:14:59 2017 +0800
      
          delete by loc
      
      diff --git a/bin/server_control b/bin/server_control
      index 6d81daa..4cf5106 100755
      --- a/bin/server_control
      +++ b/bin/server_control
      @@ -48,7 +48,7 @@ function cleanup() {
       function realtime_cleanup() {
           mkdir -p ../realtime_delete/data
           DATE_TO_CLEANUP=`date +"%Y%m%d" -d "-7 days"`
      -    cat ../data/*${DATE_TO_CLEANUP}*.succ | $PYTHON_BIN delete_succ.py 2> ../log/realtime_cleanup.log
      +    cat ../data/*${DATE_TO_CLEANUP}*.succ | $PYTHON_BIN delete.py --format json 2> ../log/realtime_cleanup.log
           rm -f ../data/*${DATE_TO_CLEANUP}*
       }
      
      
      commit 47a2565e033dc1ed60a0ffd4df5e760dbcaebad8
      Author: lishuailong <lishuailong@baidu.com>
      Date:   Thu Jul 6 16:18:47 2017 +0800
      
          fix realtime cleanup
      
      diff --git a/bin/server_control b/bin/server_control
      index 13b756f..6d81daa 100755
      --- a/bin/server_control
      +++ b/bin/server_control
      @@ -48,7 +48,7 @@ function cleanup() {
       function realtime_cleanup() {
           mkdir -p ../realtime_delete/data
           DATE_TO_CLEANUP=`date +"%Y%m%d" -d "-7 days"`
      -    cat ../data/*${DATE_TO_CLEANUP}.succ | $PYTHON_BIN delete_succ.py 2> ../log/realtime_cleanup.log
      +    cat ../data/*${DATE_TO_CLEANUP}*.succ | $PYTHON_BIN delete_succ.py 2> ../log/realtime_cleanup.log
           rm -f ../data/*${DATE_TO_CLEANUP}*
       }