在我的Controller中,我需要检查会话是否已过期,如果是,更新值:
public function some_method(Request $request)
{
// get previous last activity
$session_last_activity = session('session_last_activity');
// update last activity to now
session(['session_last_activity'] => now());
if ($session_expiry_date < now()->subMinutes(10)) {
$some_value = Str::random(30);
session(['some_value' => $some_value]);
} else {
$some_value = session('some_value');
}
// proceed to update or create some record on the DB
}
当会话过期,并且对同一页有多个快速请求时,会出现问题。然后,对于那些立即请求,每个请求创建一个新的随机字符串并更新会话。
因此,最后一个请求将具有最后一个会话值,然而,到那时,数据库创建了多个记录,因为对于这些请求中的每个请求,会话都过期了一会儿。
例如,用户在会话过期时快速单击example.com/page1
两次。现在有2个请求读取会话过期,设置一个新键,并使用2个不同的键创建2个记录,即使应该只有一个。
如何在不使用缓存的情况下防止这种情况发生,或者不在DB端(即使用DB锁),而是在代码端?
2条答案
按热度按时间gmxoilav1#
一种方法是使用存储在会话本身中的标志来指示请求是否已经在更新会话的过程中。
vybvopom2#
要锁定会话,您可以在路由上使用
block
。每当有许多同时的请求传入时,将为此请求获取会话锁定。所以,如果这个请求是针对
example.com/page1
的,那么代码片段将是:但是,要使其生效,您必须使用支持原子锁的缓存驱动程序。引用文档:
若要利用会话阻塞,应用程序必须使用支持原子锁的缓存驱动程序。目前,这些缓存驱动程序包括memcached、dynamodb、redis和数据库驱动程序。此外,您不得使用Cookie会话驱动程序。