Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)
CAP定理
Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)
CAP定理
# flock --wait 超时时间 -e 锁文件 -c "要执行的命令"# 例如:flock --wait 5 -e "lock_myscript" -c "bash myscript.sh"
保证脚本的独立运行
LevelDB 的内部已经内置了内存缓存和持久层的磁盘文件
是如何实现的从内存到硬盘的写入,以及查询过程中硬盘文件是如何应用的
也不会叫钩子
是的是的SD
整体的运行流程为:时效性同学在DA做策略,传递信号给US,架构同学根据信号执行具体的主更动作。
主更流程
主动更新,简称主更,是US2AC Cache的一种更新机制。顾名思义,就是在Cache失效前,如果我们发现某次请求中了Cache,但是内容已经过时了,就主动发起一次更新请求(当前这次中Cache的结果会直接返回给用户),这样,当下一个用户来请求相同Query时,就会拿到更为新鲜的结果。
主动更新介绍
bcloud local
本地编译命令
bcloud build
远程编译命令
如何在远程服务器运行一个本地脚本
ssh user@server 'bash -s' < local.script.sh
ssh user@server ARG1="arg1" ARG2="arg2" 'bash -s' < local_script.sh
将错误IP放到数组里面判断是否ping失败三次
#!/bin/bash
IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"
for IP in $IP_LIST; do
NUM=1
while [ $NUM -le 3 ]; do
if ping -c 1 $IP > /dev/null; then
echo "$IP Ping is successful."
break
else
# echo "$IP Ping is failure $NUM"
FAIL_COUNT[$NUM]=$IP
let NUM++
fi
done
if [ ${#FAIL_COUNT[*]} -eq 3 ];then
echo "${FAIL_COUNT[1]} Ping is failure!"
unset FAIL_COUNT[*]
fi
done
获取随机8位字符串:
方法1:
# echo $RANDOM |md5sum |cut -c 1-8
471b94f2
方法2:
# openssl rand -base64 4
vg3BEg==
方法3:
# cat /proc/sys/kernel/random/uuid |cut -c 1-8
ed9e032c
获取随机8位数字:
方法1:
# echo $RANDOM |cksum |cut -c 1-8
23648321
方法2:
# openssl rand -base64 4 |cksum |cut -c 1-8
38571131
方法3:
# date +%N |cut -c 1-8
69024815
注意事项
1)开头加解释器:#!/bin/bash
2)语法缩进,使用四个空格;多加注释说明。
3)命名建议规则:变量名大写、局部变量小写,函数名小写,名字体现出实际作用。
4)默认变量是全局的,在函数中变量local指定为局部变量,避免污染其他作用域。
5)有两个命令能帮助我调试脚本:set -e 遇到执行非0时退出脚本,set-x 打印执行过程。
6)写脚本一定先测试再到生产上。
创建vim session文件 :mks filename, 重写session :mks! filename, 载入session vim -S sessionFile
该命令可以将当前Vim打开的窗口以文件的方式进行保存,当下次打开时直接以保存时的状态打开
保存当前会话session: :mks filename
更新当前会话session: :mks! filename
载入会话session: vim -S sessionFile
cost
单位: 1/1000000 元
ACID
原子性
持久性
隔离性
一致性
mysql_install_db --basedir=/usr --datadir=/data/mysql_3307/mysql
新增数据端口在本机时,需要先执行安装才能进行
mysqladmin -uroot -S /data/mysql_3307/mysql.sock shutdown
这里指定sock,则可以直接免密登录账号
Zvalue是用来保存一个变量的实际数据。因为要存储多种类型,所以zvalue是一个union,也由此实现了弱类型。
这里是关键union是实现弱类型的点睛之笔
注意:这里除非是使用了索引会启用行级锁,不然是会使用表锁,将整张表都锁住。
这里需要注意下
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一个子进程 所以只有三个儿子
FFMPEG -i uploadfile/video/test.wmv -c:v libx264 -strict -2 uploadfile/mp4/test.mp4
可以将视频类型、视频编码进行重新转码操作
_, _, exc_tb = sys.exc_info()
返回结果为元组时,不需要关注的值,可以使用『_』来不获取该值
如何将开发的分支代码,merge到主干上?
$ git checkout -b dev
$ echo 'Readme' > ./readme.txt
$ git add readme.text
$ git commit -m "dev branch test"
$ git checkout master
$ git merge dev
$ git branch -d dev
$ git branch
git checkout -b dev
创建新的开发分支进行开发,与下面一组命令相同
$ git branch dev $ git checkout dev
$ git branch dev $ git checkout dev Switched to branch 'dev'
$$git checkout$$
命令加上 \(-b\) 参数表示创建并切换
该命令与 \(git checkout -b dev\) 相同
先说说原理。本地过程调用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之类。
事例举得不错
RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据
这里的介绍我觉得更直白的表现出与http协议的区别,当然从网络七层传输协议上来将也是一种解释,但我更喜欢此处的介绍
允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
简单的实现:
可以这么简单的理解,一个类中包含了实例化各种子类的方法(功能具体实现类),然后该类中提供了一个接口,可以采用传递几个参数,就是实现对应对象的实例化
个人感觉从下面的笔记中更好理解这个模式,主要实现方式理解为:
blocking
阻塞
recvfrom
接收数据
为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。
内核对cpu上运行进程的挂起和恢复操作,称为进程切换
若二叉树为空,则空操作,否则先后序遍历左子树访问根节点,再后序遍历右子树,最后访问根节点
后序遍历
若二叉树为空,则空操作,否则先中序遍历左子树,再访问根节点,最后中序遍历右子树
中序遍历
若二叉树为空,则空操作,否则先访问根节点,再先序遍历左子树,最后先序遍历右子树
先序遍历
深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为** 完全二叉树 **。
完全二叉树
一棵深度为k,且有2^k-1个节点的二叉树称之为** 满二叉树 **;
满二叉树
volatile
翻译 volatile 易变的
transfer
翻译:传输
pipelining
HTTP Pipelining是这样一种技术:在等待上一个请求响应的同时,发送下一个请求。(译者注:作者这个解释并不完全正确,HTTP Pipelining其实是把多个HTTP请求放到一个TCP连接中一一发送,而在发送过程中不需要等待服务器对前一个请求的响应;只不过,客户端还是要按照发送请求的顺序来接收响应。)但就像在超市收银台或者银行柜台排队时一样,你并不知道前面的顾客是干脆利索的还是会跟收银员/柜员磨蹭到世界末日(译者注:不管怎么说,服务器(即收银员/柜员)是要按照顺序处理请求的,如果前一个请求非常耗时(顾客磨蹭),那么后续请求都会受到影响),这就是所谓的线头阻塞(Head of line blocking)。 http://blog.csdn.net/qq_28885149/article/details/52922107
如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
这个锁就永远得不到释放了
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
Redis分布式锁
但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误。
尾递归的优点
递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。
递归的问题点
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
尾递归概念
尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。
尾调用优化的精髓
函数调用会在内存形成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息
函数调用记录在内存中的实现
尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。
尾调用的概念
汉明距离是使用在数据传输差错控制编码里面的,汉明距离是一个概念,它表示两个(相同长度)字对应位不同的数量
解释了什么是汉明距离,即两个相同长度的字对于位不同的数量
例: 0000000 1111111 这两个的汉明距离就是 1 + 1 + 1 + 1 + 1 + 1 + 1 = 7
这篇文章对堆和栈的解释比较明朗。
这里指名 栈 和 堆栈 是一个概念,而解决了在其他文章中说两个为不同概念的误导。
区别:
32位机器,理论上可以malloc(4G)的大小,因为2^32=4G,但事实上linux的进程地址空间是这样的:
所以经过实验,使用malloc最大能够申请的空间是3G左右,这里要注意,要使用下面这样的方式申请空间:
int MB = 0;
while(malloc(1 << 20))
{
MB++;
}
printf("Allocate %d MB total\n", MB);
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)
参考代码:
"汉明距离"
汉明距离: 在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。
汉明重量:汉明重量是字符串相对于同样长度的零字符串的汉明距离,也就是说,它是字符串中非零的元素个数:对于二进制字符串来说,就是1的个数,所以11101的汉明重量是4。
参考资料:
如果我想多级排序呢,先用score排序,再用name排序:
这是针对列表中字典排序的更高升华
new_s_2 = sorted(new_s,key = lambda e:(e.__getitem__('score'),e.__getitem__('name')))
多级排序,先用score排序,再用name排序
${FUNCNAME[@]}
常量FUNCNAME,但是有一点区别是,它是一个数组而非字符串,其中数组的第一个元素为当前函数的名称
$LINENO
获取当前行的行号
caller 0 | awk '{print$1}'
获取调用该函数所在行的行号
defaults write com.apple.finder _FXShowPosixPathInTitle -bool TRUE;killall Finder
MAC在Finder栏显示所浏览文件夹路径的方法
#!/bin/sh(cat <<EOFstart(){ echo "start"}EOF) >/tmp/b
shell 如何把多行内容输出到一个文件
0 6 * * * /root/zwk/test.sh >> /root/zwk/operate_`date +"\%Y\%m\%d"`.log 2>&1
crontab 执行命令,将对应运行日志按照日期进行存放
tail -n +k /etc/passwd
从开头第k行处开始输出
git show [commit]
显示某次提交的元数据和内容变化
查看某个文件在某次提交的变动信息: git show [commit] [filename]
git show [commit]:[filename]
显示某次提交时,某个文件的内容
git cherry-pick [commit]
选择一个commit,合并进当前分支
git merge [branch]
合并指定分支到当前分支
git checkout [branch-name]
新建一个分支,与指定的远程分支建立追踪关系
git branch --track [branch] [remote-branch]
新建一个分支,与指定的远程分支建立追踪关系
git branch [branch] [commit]
新建一个分支,指向指定commit
git checkout -b [branch]
新建一个分支,并切换到该分支
git branch [branch-name]
新建一个分支,但依然停留在当前分支
git branch
列出所有本地分支
git log --stat
显示commit历史,以及每次commit发生变更的文件
git diff --shortstat "@{0 day ago}"
显示今天你写了多少行代码
git blame [file]
显示指定文件是什么人在什么时间修改过
$ 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}*
}