PHP-PHP 并发处理,只需要往数据库插入一条数据,但是请求量很大,总是插入许多条,用memcache锁效果不明显
static function recordTest(){
$cacheLock = new CacheLock();//封装的memcache
if($cacheLock->getLock('key')){
return false;
}
$cacheLock->setLock('key');
$uid = 'test';
//去数据库查询是否存在
$recordItem = RecordItem::getWithUid($uid);
if($recordItem->createTime){
return false;
}
/**
* 执行插入部分
*/
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用 cas 和 casbykey 来做判断
我也遇到過類似的問題。最終找到的解決方案只能是使用 InnoDB 引擎,以使用行級鎖來在增加數據時進行鎖定。對於搶佔鎖和死鎖,我沒遇到有問題反饋,但數據也有髒數據的產生,但是可以接受的少量的。
function throw_err($msg) {
throw new Exception($msg);
}
mysql_query("START TRANSACTION");
try {
$sql = "SELECT * FROM table_name WHERE id=1 FOR UPDATE"; // 獲取更新鎖
$result = mysql_query($sql) or throw_err(mysql_error());
$rs = mysql_fetch_assoc($result);
mysql_query("UPDATE table_name SET `modified`='".date('Y-m-d H:i:s')."' WHERE id={$rs['id']}") or throw_err(mysql_error()); // 使其他線程進入鎖等待
// 業務邏輯
...
mysql_query("COMMIT"); // 提交數據並釋放鎖
} catch (Exception $e) {
mysql_query("ROLLBACK"); // 回滾並釋放鎖
// print_r($e->getMessage());
}
如果其他朋友有更好的方法,歡迎分享。
不清楚你的getLock()是什么样的语义,所以下面都是猜的。
我看有分开的getLock()和setLock(),我猜setLock()是上锁,getLock()返回真表示已经上锁,但是这是个错误的锁的实现。在最初没上锁的时候,并发时多个请求中getLock()返回真,就会多次进入到setLock()以及后面数据库查询和插入的代码。
正确的做法是用Memcache::add()来实现锁,add()返回假的时候表示键已经存在。不经封装看起来是这样的:
static function recordTest(){
$memc = memcache_connect("localhost", 8129);
if (!$memc->add($key, 1, FALSE, 30)) {
return false;
}
// 去数据库查询是否存在
// 执行插入部分
}