justudy

just study


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 公益404

操作实现乐观锁

发表于 2016-10-10

获取缓存值的问题

发表于 2016-10-08   |   分类于 cache

一般我们获取缓存值得姿势是这样的:

1
2
3
4
5
6
7
Object result = cache.get(CACHE_KEY);
if(result == null){
//重新获取缓存
result = xxxx(xxx);
cache.put(CACHE_KEY,CACHE_TTL,result);
}
return result;

高并发下暴露问题
你的程序一直正常运行,直到某一日,运营的同事急匆匆的跑来找到你,你的程序挂了,可能是XXX在大量抓你的数据。我们重启了应用也没用,没几秒程序又挂了。

机智的你通过简单的排查,得出数据库顶不住访问压力,顺利的将锅甩走。 不过仔细一想,我们不是有缓存吗,怎么缓存没起作用? 查看下缓存,一切正常,也没发现什么问题啊?

进过各种debug、查日志、测试环境模拟,花了整整一下午,你终于找到罪魁祸首,原因很简单,正是我们没有使用正确的姿势使用缓存

1
2
3
4
5
6
> 问题分析
这里我们排除熔断、限流等外部措施,单纯讨论缓存问题。
假设你的应用需要访问某个资源(数据库/服务),其能支撑的最大QPS为100。为了提高应用QPS,我们加入缓存,并将缓存过期时间设置为X秒。此时,有个200并发的请求访问我们系统中某一路径,这些请求对应的都是同一个缓存KEY,但是这个键已经过期了。此时,则会瞬间产生200个线程访问下游资源,下游资源便有可能瞬间就奔溃了

guava是一个google发布的一个开源java工具库,其中guava cacha提供了一个轻量级的本地缓存实现机制,通过guava cache,我们可以轻松实现本地缓存。其中,guava cacha对缓存不存在或者过期情况下,获取缓存值得过程称之为Loading。

不过,这样虽然只有一个线程去执行loading动作,但是其他线程会等待loading线程接受后才能一同返回接口。此时,guava cache通过刷新策略,直接返回旧的缓存值,并生成一个线程去处理loading,处理完成后更新缓存值和过期时间。guava 称之为异步模式。

为你总结一些php系统类函数

发表于 2016-09-27   |   分类于 PHP

#PHP的一些系统函数

  1. assert函数:检查assertion声明是否错误
  2. extension_loaded函数:检查PHP扩展是否加载
  3. get_cfg_var函数:获取PHP配置选项的值
  4. get_current_user函数:获取当前PHP脚本的所有者的名称
  5. get_defined_constants函数:返回一个包含PHP预定义常量信息的数组
  6. get_extension_funcs函数:返回一个包含指定模块中的所有函数名称的数组
  7. get_include_path函数:返回当前配置的文件包含路径的信息
  8. get_included_files函数:返回一个关于文件包含信息的数组
  9. get_loaded_extensions函数:返回一个包含所有装载模块信息的数组
  10. get_magic_quotes_gpc函数:获取magic_quotes_gpc的状态信息
  11. get_magic_quotes_runtime函数:获取magicquotes runtime的状态信息
  12. get_required_files函数:返回一个关于文件包含信息的数组
  13. getenv函数:获取PHP环境变量的值

  14. getlastmod函数:获取当前PHP页面文件的最后修改时间

  15. getmygid函数:获取当前PHP脚本页面所有者的GID号码
  16. getmyinode函数:获取当前PHP脚本页面的INODE号码
  17. getmypid函数:获取PHP的PID
  18. getmyuid函数:获取PHP脚本页面所有者的UID号码
  19. getopt函数:从命令行参数列表获取设置
  20. getrusage函数:获取当前的资源语法
  21. ini_get_all函数:获取所有配置选项
  22. ini_get函数:获取配置选项的值
  23. memory_get_usage函数:返回PHP脚本占用的内存空间
  24. php_ini_scanned_files函数:返回配置文件目录下的配置文件列表
  25. php_logo_guid函数:获取LOGO图片的GUID
  26. php_sapi_name函数:获取PHP和Web服务器之间的接口类型
  27. php_uname函数:获取PHP脚本运行的操作系统信息
  28. phpcredits函数:打印credits列表
  29. phpinfo函数:输出PHP的信息
  30. phpversion函数:获取PHP版本
  31. zend_logo_guid函数:获取ZEND的LOGO图片的GUID
  32. zend_version函数:获取ZEND引擎的版本

  33. assert_options函数:设置或者获取不同的声明标记

  34. ini_alter函数:设置PHP配置选项的值
  35. ini_restore函数:恢复配置选项的值
  36. ini_set函数:设置PHP配置选项的值
  37. putenv函数:设置环境变量
  38. restore_include_path函数:恢复文件包含路径配置信息
  39. set_include_path函数:设置文件包含路径配置选项
  40. set_magic_quotes_runtime函数:设置magic_quotes运行时间
  41. set_time_limit函数:设置最大执行时间

使用supervisor管理进程

发表于 2016-09-27   |   分类于 linux

#使用supervisor管理进程
Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是 Python 进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用 supervisor 同时启动所有应用程序而不是一个一个地敲命令启动。

安装

Supervisor 可以运行在 Linux、Mac OS X 上。如前所述,supervisor 是 Python 编写的,所以安装起来也很方便,可以直接用 pip :
sudo pip install supervisor

##supervisord配置
Supervisor 相当强大,提供了很丰富的功能,不过我们可能只需要用到其中一小部分。安装完成之后,可以编写配置文件,来满足自己的需求。为了方便,我们把配置分成两部分:supervisord(supervisor 是一个 C/S 模型的程序,这是 server 端,对应的有 client 端:supervisorctl)和应用程序(即我们要管理的程序)。

首先来看 supervisord 的配置文件。安装完 supervisor 之后,可以运行echo_supervisord_conf 命令输出默认的配置项,也可以重定向到一个配置文件里:

echo_supervisord_conf > /etc/supervisord.conf

去除里面大部分注释和“不相关”的部分,我们可以先看这些配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[unix_http_server]
file=/tmp/supervisor.sock ; UNIX socket 文件,supervisorctl 会使用
;chmod=0700 ; socket 文件的 mode,默认是 0700
;chown=nobody:nogroup ; socket 文件的 owner,格式: uid:gid
;[inet_http_server] ; HTTP 服务器,提供 web 管理界面
;port=127.0.0.1:9001 ; Web 管理后台运行的 IP 和端口,如果开放到公网,需要注意安全性
;username=user ; 登录管理后台的用户名
;password=123 ; 登录管理后台的密码
[supervisord]
logfile=/tmp/supervisord.log ; 日志文件,默认是 $CWD/supervisord.log
logfile_maxbytes=50MB ; 日志文件大小,超出会 rotate,默认 50MB
logfile_backups=10 ; 日志文件保留备份数量默认 10
loglevel=info ; 日志级别,默认 info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ; pid 文件
nodaemon=false ; 是否在前台启动,默认是 false,即以 daemon 的方式启动
minfds=1024 ; 可以打开的文件描述符的最小值,默认 1024
minprocs=200 ; 可以打开的进程数的最小值,默认 200
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; 通过 UNIX socket 连接 supervisord,路径与 unix_http_server 部分的 file 一致
;serverurl=http://127.0.0.1:9001 ; 通过 HTTP 的方式连接 supervisord
; 包含其他的配置文件
[include]
files = relative/directory/*.ini ; 可以是 *.conf 或 *.ini

我们把上面这部分配置保存到 /etc/supervisord.conf(或其他任意有权限访问的文件),然后启动 supervisord(通过 -c 选项指定配置文件路径,如果不指定会按照这个顺序查找配置文件:$CWD/supervisord.conf, $CWD/etc/supervisord.conf, /etc/supervisord.conf):

supervisord -c /etc/supervisord.conf
查看 supervisord 是否在运行:
ps aux | grep supervisord

###program 配置
上面我们已经把 supervisrod 运行起来了,现在可以添加我们要管理的进程的配置文件。可以把所有配置项都写到 supervisord.conf 文件里,但并不推荐这样做,而是通过 include 的方式把不同的程序(组)写到不同的配置文件里。

为了举例,我们新建一个目录 /etc/supervisor/ 用于存放这些配置文件,相应的,把 /etc/supervisord.conf 里 include 部分的的配置修改一下:

[include] files = /etc/supervisor/*.conf

假设有个用 Python 和 Flask 框架编写的用户中心系统,取名 usercenter,用 gunicorn (http://gunicorn.org/) 做 web 服务器。项目代码位于 /home/leon/projects/usercenter,gunicorn 配置文件为 gunicorn.py,WSGI callable 是 wsgi.py 里的 app 属性。所以直接在命令行启动的方式可能是这样的:
cd /home/leon/projects/usercenter gunicorn -c gunicorn.py wsgi:app

现在编写一份配置文件来管理这个进程(需要注意:用 supervisord 管理时,gunicorn 的 daemon 选项需要设置为 False):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[program:usercenter]
directory = /home/leon/projects/usercenter ; 程序的启动目录
command = gunicorn -c gunicorn.py wsgi:app ; 启动命令,可以看出与手动在命令行启动的命令是一样的
autostart = true ; 在 supervisord 启动的时候也自动启动
startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true ; 程序异常退出后自动重启
startretries = 3 ; 启动失败自动重试次数,默认是 3
user = leon ; 用哪个用户启动
redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20 ; stdout 日志文件备份数
; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile = /data/logs/usercenter_stdout.log
; 可以通过 environment 来添加需要的环境变量,一种常见的用法是修改 PYTHONPATH
; environment=PYTHONPATH=$PYTHONPATH:/path/to/somewhere

一份配置文件至少需要一个 [program:x] 部分的配置,来告诉 supervisord 需要管理那个进程。[program:x] 语法中的 x 表示 program name,会在客户端(supervisorctl 或 web 界面)显示,在 supervisorctl 中通过这个值来对程序进行 start、restart、stop 等操作。

###使用 supervisorctl

Supervisorctl 是 supervisord 的一个命令行客户端工具,启动时需要指定与 supervisord 使用同一份配置文件,否则与 supervisord 一样按照顺序查找配置文件。
supervisorctl -c /etc/supervisord.conf

上面这个命令会进入 supervisorctl 的 shell 界面,然后可以执行不同的命令了:

1
2
3
4
5
6
> status # 查看程序状态
> stop usercenter # 关闭 usercenter 程序
> start usercenter # 启动 usercenter 程序
> restart usercenter # 重启 usercenter 程序
> reread # 读取有更新(增加)的配置文件,不会启动新添加的程序
> update # 重启配置文件修改过的程序

上面这些命令都有相应的输出,除了进入 supervisorctl 的 shell 界面,也可以直接在 bash 终端运行:

1
2
3
4
5
6
$ supervisorctl status
$ supervisorctl stop usercenter
$ supervisorctl start usercenter
$ supervisorctl restart usercenter
$ supervisorctl reread
$ supervisorctl update

###其它
除了 supervisorctl 之外,还可以配置 supervisrod 启动 web 管理界面,这个 web 后台使用 Basic Auth 的方式进行身份认证。
除了单个进程的控制,还可以配置 group,进行分组管理。
经常查看日志文件,包括 supervisord 的日志和各个 pragram 的日志文件,程序 crash 或抛出异常的信息一半会输出到 stderr,可以查看相应的日志文件来查找问题。

Supervisor 有很丰富的功能,还有其他很多项配置,可以在官方文档获取更多信息:http://supervisord.org/index.html

PHP那些鲜为人知的有用函数

发表于 2016-09-23   |   分类于 PHP
  1. levenshtein()

    你有没有经历过需要知道两个单词有多大的不同的时候,这个函数就是来帮你解决这个问题的。它能比较出两个字符串的不同程度。

    1
    2
    3
    4
    5
    <?php
    $str1 = "carrot";
    $str2 = "carrrott";
    echo levenshtein($str1, $str2); //Outputs 2
    ?>

    Source: http://php.net/manual/en/function.levenshtein.php

  2. get_defined_vars()
    这是一个在debug调试时非常有用的函数。这个函数返回一个多维数组,里面包含了所有定义过的变量。

    1
    2
    3
    <?php
    print_r(get_defined_vars());
    ?>

    Source: http://php.net/manual/en/function.get-defined-vars.php

  3. ignore_user_abort()

    这个函数用来拒绝浏览器端用户终止执行脚本的请求。正常情况下客户端的退出会导致服务器端脚本停止运行。

    1
    2
    3
    <?php
    ignore_user_abort();
    ?>

    Source: http://www.php.net/manual/en/function.ignore-user-abort.php

  4. highlight_string()

    你想把PHP代码显示到页面上时,highlight_string()函数就会显得非常有用。这个函数会把你提供的PHP代码用内置的PHP语法突出显示定义的颜色高亮显示。这个函数有两个参数,第一个参数是一个字符串,表示这个字符串需要被突出显示。第二个参数如果设置成TRUE,这个函数就会把高亮后的代码当成返回值返回。

    1
    2
    3
    <?php
    highlight_string(' <?php phpinfo(); ?>');
    ?>
> Source: http://php.net/manual/en/function.highlight-string.php
  1. highlight_file

这是一个非常有用的PHP函数,它能返回指定的PHP文件,并按照语法语义用高亮颜色突出显示文件内容。其中的突出显示的代码都是用HTML标记处理过的。

用法:

<?php

highlight_file(“php_script.php”);

?>

Source: http://www.php.net/manual/en/function.highlight-file.php

  1. php_strip_whitespace

这个函数也跟前面的show_source()函数相似,但它会删除文件里的注释和空格符。

用法:

<?php

echo php_strip_whitespace(“php_script.php”);

?>

Source: http://www.php.net/manual/en/function.php-strip-whitespace.php

http://www.chinaz.com/program/2014/0128/337438.shtml

PHP多进程实践

发表于 2016-09-13

利用pcntl_fork实现PHP多进程代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function runTasks($tasks)
{
$linenum = 2;
$count = count($tasks);
if ($count > 30) {
$linenum = (int)($count/15);
}
//任务分割
$chunks = array_chunk($tasks, $linenum);
$procs = array();
foreach ($chunks as $chunk) {
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
} else if ($pid) {
$procs[] = $pid;
} else {
foreach ($chunk as $line) {
system('php '. $line);
echo $line." done!\n";
}
exit(0);
}
}
foreach ($procs as $proc) {
pcntl_waitpid($proc, $status);
}
unset($pid);
$pid = NULL;
unset($procs);
$procs = NULL;
unset($chunks);
$chunks = NULL;
}

部署脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
source /etc/profile
source /root/.bash_profile
nowDate=`date +%Y%m%d`
cd /yourpath
nowTime=`date +%M`
//每小时一次 01分的时候
if [ "$nowTime" -eq "01" ]
then
ProcessCount=`ps -ef|grep "tash.php" |grep -v "grep"|wc -l`
if [ $ProcessCount -lt 1 ]
then
nohup /usr/bin/php test.php >> /dev/null &
echo "Create test.php run!"
fi
fi

ssh服务

发表于 2016-09-13   |   分类于 linux
  1. 概述
    SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议,利用SSH协议可以有效防止远程管理过程中的信息泄露问题。SSH是Secure Shell的缩写,是建立在应用层和传输层基础上的安全协议。
  2. SSH服务的功能
    • SSH可有效地提供防止DNS欺骗以及IP欺骗
    • 压缩传输数据
    • SSH提供了多种传输方式
    • SSH构建Socket5代理
  3. SSH常用配置
    linux系统,SSH配置文件在 /etc/ssh/sshd_config

    常用配置说明:

    Port 22 #SSH端口设置,这里默认使用的是22端口
    Protocol 2,1 #选择SSH协议版本
    ListenAddress 0.0.0.0 #监听的网卡IP
    PermitRootLogin no #是否允许root登入,默认是允许的
    PasswordAuthentication yes #是否开启密码验证
    PermitEmptyPasswords no #是否允许密码为空
    PrintMotd no #登入后是否显示一些信息,如上次登入时间及地点等。
    PrintLastLog yes #显示上次登入的信息
    KeepAlive yes #发送KeepAlive信息给客户端
    MaxStartups 10 #允许尚未登入的联机画面数
    DenyUsers #禁止用户登录,表示所有用户
    AllowUsers * #允许用户登录

  4. SSH的认证方式与访问策略

    • 基于口令的认证方式
      ssh options username@hostname command
    • 基于秘钥的认证方式
      ssh-keygen 生成公钥与秘钥,讲客户端公钥加入到服务端
      cat id_rsa.pub >> ~/.ssh/authorized_keys
      ssh 目录权限700 authorized_keys权限600
    • 限制用户连接
      可以修改ssh服务端配置文件 /etc/ssh/sshd_config

      DenyUsers test #禁止test用户登入
      AllowUsers test #允许test用户登入
      DenyGroups test #禁止test群组登入
      AllowUsers test #允许test群组登入

    • 限制ip连接SSH
      基于IP地址的访问策略有两种方式实现:

      • iptables防火墙

        iptables -A INPUT -p tcp –dport 22 -s 192.168.0.10/32 -j ACCEPT
        iptables -A INPUT -p tcp –dport 22 -j DROP

      • TCP Wrappers

        /etc/hosts.allow
        sshd:192.168.0.10/255.255.255.255

        /etc/hosts.deny
        sshd:ALL 或 sshd:ALL EXCEPT 192.168.0.10
        TCP Wrappers只支持长格式掩码,不能用192.168.0.0/24

配置ssh密钥认证自动登录

发表于 2016-09-13   |   分类于 linux

#配置ssh密钥认证自动登录

###在客户端来看,SSH提供两种级别的安全验证。

  1. 在本地机器创建公钥
    ssh-keygen -t rsa -C 'your email@domain.com'
    -t 指定密钥类型,默认即 rsa ,可以省略
    -C 设置注释文字,比如你的邮箱
  2. 将公钥复制到ssh服务器
    将前一步骤生成的公钥~/id_rsa.pub文件,复制到ssh服务器对应用户下的~/.ssh/authorized_keys文件,可以有多种方式,这里只介绍常用的三种。

    • [适用于osx系统]使用ssh-copy-id-for-OSX工具将公钥复制至ssh服务器

      1
      2
      3
      brew install ssh-copy-id
      ssh-copy-id username@hostname #将username和hostname替换为你的ssh服务器用户名和IP
    • 当ssh服务器username用户目录下尚未有.ssh目录时使用此方式
      cat ~/.ssh/id_rsa.pub | ssh username@hostname "mkdir ~/.ssh; cat >> ~/.ssh/authorized_keys"

    • 通用方式
      1
      2
      3
      4
      scp ~/.ssh/id_rsa.pub username@hostname:~/ #将公钥文件复制至ssh服务器
      ssh username@hostname #使用用户名和密码方式登录至ssh服务器
      mkdir .ssh #若.ssh目录已存在,可省略此步
      cat id_rsa.pub >> .ssh/authorized_keys #将公钥文件id_rsa.pub文件内容追加到 authorized_keys文件
  3. 快捷登录
    完成以上步骤后,即可使用以下命令直接登录ssh服务器
    ssh username@hostname #将username替换为你的ssh服务器用户名,hostname替换为服务器的ip
    如果你本地终端使用的是zsh,那就太简单不过了,直接给zsh添加一条别名

    1
    2
    3
    echo "alias ssh-to-username='ssh username@hostname'" >> ~/.zshrc #将username和 hostname替换为你的服务器信息
    source ~/.zshrc #重新加载更改后的zshrc文件
    ssh-to-username #使用别名,一条命令即可登录你的ssh服务器

Mac下使用launchctl创建定时任务

发表于 2016-09-09   |   分类于 MAC

#Mac下添加定时任务

  • 编写任务脚本

    把要执行的任务写好

  • 编写任务描述文件

    mac的任务描述文件是plist格式的。结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 名称,要全局唯一 -->
<key>Label</key>
<string>com.uniflor.notifier</string>
<!-- 要运行的程序, 如果省略这个选项,会把ProgramArguments的第一个
元素作为要运行的程序 -->
<key>Program</key>
<string>/Users/uniflor/script.sh</string>
<!-- 命令, 第一个为命令,其它为参数-->
<key>ProgramArguments</key>
<array>
<string>/Users/uniflor/script.sh</string>
</array>
<!-- 运行时间 -->
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>30</integer>
<key>Hour</key>
<integer>9</integer>
<key>Day</key>
<integer>1</integer>
<key>Month</key>
<integer>5</integer>
<!-- 0和7都指星期天 -->
<key>Weekday</key>
<integer>0</integer>
</dict>
<!-- 运行间隔,与StartCalenderInterval使用其一,单位为秒 -->
<key>StartInterval</key>
<integer>30</integer>
<!-- 标准输入文件 -->
<key>StandardInPath</key>
<string>/Users/uniflor/run-in.log</string>
<!-- 标准输出文件 -->
<key>StandardOutPath</key>
<string>/Users/uniflor/Bin/run-out.log</string>
<!-- 标准错误输出文件 -->
<key>StandardErrorPath</key>
<string>/Users/uniflor/Bin/run-err.log</string>
</dict>
</plist>
  1. 两种指定要执行命令的方法:

    • 使用Program和ProgramArguments

      Program, 运行命令或要执行文件路径
      ProgramArguments, 执行时传入参数

    • 只使用ProgramArguments
      此时,ProgramArguments的每个参数为要执行的命令或文件路径,其它参数为传入参数

  2. 两种设置执行时间的方法:

    • StartCalendarInterval
      使用元素Minute, Hour, Day, Month, Weekday两指定执行时间,如:

      1
      2
      3
      4
      5
      6
      7
      <key>StartCalendarInterval</key>
      <dict>
      <key>Minute</key>
      <integer>30</integer>
      <key>Hour</key>
      <integer>9</integer>
      </dict>

      每天的9:30执行

    • StartInterval
      设置执行的时间间隔,单位为秒

      1
      2
      <key>StartInterval</key>
      <integer>3600</integer>

      每小时执行一次

使用launchctl加载plist
任务描述文件写好后,怎么使用它呢?可以使用launchctl工具,添加任务到launchd。

系统定义了几个位置来存放任务列表

~/Library/LaunchAgents 由用户自己定义的任务项
/Library/LaunchAgents 由管理员为用户定义的任务项
/Library/LaunchDaemons 由管理员定义的守护进程任务项
/System/Library/LaunchAgents 由Mac OS X为用户定义的任务项
/System/Library/LaunchDaemons 由Mac OS X定义的守护进程任务项

为用户定义的任务项,只以用户登陆后才会执行,守护进程任务项无论用户是否登陆都会执行
根据添加的任务类型,把它拷贝到相应的目录,通过launchctl来加载:
建议添加到~/Library/LaunchAgents
添加 launchctl load ~/Library/LaunchAgents/com.test.plist

移除 launchctl unload ~/Library/LaunchAgents/com.test.plist
查看 launchctl list

最后这些如果你觉得麻烦,下面推荐你一款好用的工具“launchcontrol”
可以新增编辑任务,右边各种选项很方便。

INNODB关键特性

发表于 2016-09-08   |   分类于 mysql

INNODB关键特性

INNODB关键特性包括如下:

  1. 插入缓冲(insert buff)
  2. 两次写(double write)
  3. 自适应哈希索引(Adaptive Hash Index)
  4. 异步IO(Async IO)
  5. 刷新邻接页(Flush Neighbor Page)

插入缓冲

插入缓冲带来了性能上的提升

两次写

带给innodb数据页的可靠性

1234
周强

周强

个人站

32 日志
11 分类
16 标签
GitHub 知乎
Links
  • 个人站
  • laravel博客
  • 校园QA
© 2015 - 2016 周强
由 Hexo 强力驱动
主题 - NexT.Muse