2015-11-27 3 views
2

Я пишу PHP-скрипт, который по запросу совершает вызов службе SOAP с различными параметрами, некоторые из которых берутся из запроса.Увеличение переменной между запросами PHP

Однако конкретная служба SOAP, которую я использую, требует, чтобы каждый запрос включал уникальный идентификатор, который в этом случае должен увеличиваться для каждого запроса. Он не должен основываться на времени и должен быть уникальным для каждого запроса, однако не имеет значения, пропускаются ли значения.

Использование базы данных MySQL для хранения одного значения кажется массово излишним. Я подумал о том, чтобы хранить и загружать его в файл, но проблема условий гонки возникает из виду.

У меня есть полный доступ к серверу, который будет представлять собой особый стиль Linux, посвященный этой задаче.

Есть ли простой способ добиться этого?

+0

SESSION и COOKIE - еще один способ достичь настойчивости – pavlovich

+0

Memcache или еще что-то. Но, на мой взгляд, это тоже негабарит. Каждый номер должен быть больше, чем предыдущий или только другой идентификатор? –

+0

$ i ++? ну, просто говоря: –

ответ

0

Так я достиг этого в конце. Рассмотрев различные варианты, базы данных и различные варианты кеширования казались немного переполненными. Кроме того, кэширование, файлы cookie и сеансы, по-видимому, предназначены для относительно временных, тогда как я действительно искал нелетучее решение.

Это то, к чему я придумал - простое решение для блокировки файлов. Я не понял, что PHP может иметь дело с файловыми замками, но, обнаружив это, кажется, лучший способ.

Этот пример приобретает исключительную блокировку файла перед чтением и обновлением значения. Если он достигает максимума int, он сбрасывается. Затем он ждет 5 секунд. Если сценарий вызывается несколько раз подряд, обратите внимание, что каждый запрос будет ждать выхода блокировки из предыдущего, прежде чем продолжить.

Приятно, поскольку это PHP, несуществующий файл, недопустимое содержимое и т. Д., Просто приведет к тому, что значение по умолчанию будет равным нулю.

<?php 

$f = fopen('sequence_num.txt', 'r+'); 

echo "Acquiring lock<br />\n"; 
flock($f, LOCK_EX); 

echo "Lock acquired, updating value<br />\n"; 
$num = intval(fread($f, strlen(PHP_INT_MAX))); 
echo "Old val = " . $num; 
if ($num >= PHP_INT_MAX) { 
    $num = 0; 
} else { 
    $num++; 
} 
echo " New val = " . $num; 
echo "<br />Waiting 5 seconds<br />\n"; 
rewind($f); 
ftruncate($f, 0); 
fwrite($f, $num); 
sleep(5); 

echo "Releasing lock<br />\n"; 
flock($f, LOCK_UN); 
fclose($f); 
0

Прежде чем какой-либо новый запрос получит инкрементное значение с помощью функции PHP time(), поскольку время будет уникальным для каждого запроса.

$increment_id = time(); 
+0

'time()' не будет уникальным для каждого запроса, если не будет гарантировано не более 1 запроса в секунду, чего не будет. Даже более высокие функции времени разрешения не будут использоваться, поскольку спецификация заявляет, что значение не может быть основано на времени, как в моем сообщении. – emorris

-1

Если приложение один сервер вы можете попытаться сохранить инкрементный идентификатор в APC с помощью:

$key = 'soap_service_name'; 
if (!apc_exists($key)) { 
    apc_store($key, 0); 
} 
$id = apc_inc($key); 

Вы должны проверить, если ключ существует в кэше APC и установите 0, в противном случае apc_inc терпит неудачу и возвращаешь false

Если у вас есть приложение многосерверные вы можете хранить инкрементный идентификатор в Memcache/Redis (что необходимо для запуска дополнительных услуг):

$key = 'soap_service_name'; 
$memcache = memcache_connect('memcache_host', 11211); 
if (!empty(memcache_exists($memcache, $key))) { 
    memcache_set($memcache, 0); 
} 
$id = memcache_increment($memcache, $key); 

В той же ситуации, что и APC, если вы вызываете memcache_increment, это не удастся, если ключ еще не существует.

Если этот инкрементный идентификатор должен храниться постоянно, Redis был бы более полезным, потому что у него есть запись на диске всех данных. Это своего рода Memcache с записью диска.

+0

Похоже, что APC может быть путем! Я полагаю, что их небольшое условие гонки между проверкой ключа существует и устанавливается на ноль, если нет, однако это, вероятно, крайне маловероятно в моем случае. – emorris

0

Если вы счастливы использовать поплавок как уникальное использование значения:

$unique_id = microtime(true); 

Если вы хотите, чтобы просто увеличивать, вы можете сделать это с помощью сеанса вар:

/** 
* Get session increment. 
* 
* @param string $id 
* @param int $default 
* @return int 
*/ 
function get_increment($id, $default = 0) 
{ 
    if (array_key_exists($id, $_SESSION)) $_SESSION[$id] += 1; 

    else $_SESSION[$id] = $default; 

    return $_SESSION[$id]; 
} 

var_dump(get_increment('unique_id')); 
Смежные вопросы