Si bien hay una respuesta aceptada, hay algunas soluciones simples, de cosecha propia que no tienen los errores como se describe anteriormente. La solución wget funciona bien para garantizar que un único servidor ejecute el código, pero agrega problemas de seguridad (debe proteger la URL con una clave de acceso privada compartida), y como @sourcedelica también señaló el problema de qué servidor debería invocar realmente la tarea cron.
Tiendo a ir por la solución que funciona independientemente de la cantidad de sistemas que tenga, y también no requiere configuraciones cron diferentes para diferentes sistemas.
Se supone que, en el futuro, puede agregar máquinas nuevas y su servidor primario (el configurado para ejecutar su tarea cron, por ejemplo) puede morir o terminar.
Una solución que he desarrollado utiliza bloqueos de base de datos de clúster que se puede hacer con un dos tablas simples:
CREATE TABLE `Server` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uname` varchar(32) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`alive` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `Lock` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`code` varchar(128) NOT NULL,
`pid` int(10) unsigned DEFAULT NULL,
`server` int(10) unsigned DEFAULT NULL,
`locked` timestamp NULL DEFAULT NULL,
`used` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
);
Cada sistema tiene una única uname
, y registra un registro si no existe; actualizando alive
cada vez.
Para adquirir un bloqueo:
SELECT * FROM Lock WHERE code='cron-cluster';
Si no existe,
INSERT INTO `Lock` ...
vez que tenga su Lock
con id
de 32. Si server
y pid
son ambas NULL, los puso a mi servidor id
y la identificación del proceso actual, usando la naturaleza atómica de la base de datos para asegurar solo una.
UPDATE Lock SET server=1,pid=4233 WHERE id=32 AND server IS NULL and pid IS NULL;
Entonces usted un selecto de nuevo para ver si realmente lo adquirió (suponiendo que n diferentes máquinas están tratando de adquirir el bloqueo al mismo tiempo):
SELECT COUNT(id) FROM Lock WHERE code='cron-cluster' AND server=1 AND pid=4233;
Si el resultado es 1 , has adquirido el bloqueo, 0 significa que otro proceso lo hizo.
Lo último que se necesita es que cada servidor limpie bloqueos muertos y servidores muertos; cada servidor es responsable de comprobar que se está ejecutando un proceso activo para cada Lock
bloqueado, y cuando un Server
no se actualiza como alive
después de un tiempo de espera determinado, elimine todos los bloqueos asociados con ese servidor y su registro Server
.
añadí otras propiedades del servidor a la mesa Server
para permitir el monitoreo de espacio en disco, CPU, etc.
Aunque no es tan poderoso como el cuarzo agrupación, que resuelve su problema.
Además, acaba de encontrar rcron que también puede resolverlo: https://code.google.com/p/rcron/ – razzed