很多时候需要让系统的某些操作串行化,如抢购(先到先得)、报名等,这个时候就要对这些操作来加上一把锁。(好比上厕所,需要挨个来,待你用完之后把门打开,别人再进去,保证厕所永远只有1个人, 上厕所的过程是串行化的)
也许通过文件(加锁创建一个文件/解锁再删掉,或直接使用flock函数) 或者 MySQL结合InnoDB引擎 去实现,方法也比较多。但个人感觉都不是很优秀,尤其在新浪云SAE这种不支持IO的PaaS上,文件锁的实现方式是不能用的。
在SAE,其实有非常多的方法、很简单的实现这个需求,这里写个利用 Counter 服务模拟锁的实现方法:
<?php
class Lock {
const LKEY = 'GOLD_LOCK';
static private $ct = NULL;
//初始化操作,取得计数器实例,如果计数器不存在则创建
static public function init() {
is_null(self::$ct) && self::$ct = new SaeCounter();
self::$ct->exists(self::LKEY) || self::$ct->create(self::LKEY);
}
//加锁
static public function add() {
self::init();
return self::$ct->set(self::LKEY, 1);
}
//开锁
static public function del() {
self::init();
return self::$ct->set(self::LKEY, 0);
}
//获取锁状态
static public function get() {
self::init();
return self::$ct->get(self::LKEY) > 0;
}
}
//1、判断是否已加锁
if (Lock::get()) {
/*
* 这里可以直接exit
* 也可以while写个死循环结合sleep,实现类似小米抢购的那种等待状态,在服务器内部进行排队抢购
* ....
* ....
*/
}
//2、加锁
Lock::add();
/*
* 这里就是你业务逻辑代码
* ....
* ....
*/
//3、开锁
Lock::del();
Counter是SAE为开发者提供的计数器服务,用来实现高并发情景下的计数功能。用户可以在控制面板或程序中创建计数器,通过API对计数器进行设置,加减和统计。
Counter简化了计数应用的开发.开发者可以轻松实现高并发情景下的计数功能,实现如兔年春晚投票,广告渠道访问计数等应用,同时可以使用Counter的统计功能轻松实现数据汇总。
你可以通过SAE的KVDB、Memcache 等服务,轻松实现串行,当然还有专门为队列而生的 TaskQueue,这里就不一一介绍了