php crash apc spinlock high-load

php - ¿User-Cache de APC es adecuado para entornos de alta carga?



crash spinlock (2)

Intentamos implementar el caché de usuario de APC en un entorno de alta carga como caché de segundo nivel local en cada servidor para nuestro servicio de caché central (redis), para el almacenamiento en caché de las consultas de la base de datos con resultados poco cambiantes y la configuración. Básicamente miramos lo que Facebook hizo (hace años):

http://www.slideshare.net/guoqing75/4069180-caching-performance-lessons-from-facebook http://www.slideshare.net/shire/php-tek-2007-apc-facebook

Funciona bastante bien durante un tiempo, pero después de algunas horas bajo mucha carga, APC tiene problemas, por lo que toda mod_php ya no ejecuta ningún PHP. Incluso un simple script PHP con solo no responde más, mientras que los recursos estáticos aún son entregados por Apache. Realmente no falla, no hay segfault. Probamos la última versión beta estable y última de APC, probamos pthreads, bloqueos por giro, siempre el mismo problema. Proporcionamos a APC mucha más memoria que jamás pueda consumir, 1 minuto antes de un bloqueo tenemos una fragmentación del 2% y aproximadamente el 90% de la memoria es gratuita. Cuando "falla" no encontramos nada en los registros de errores, solo reiniciar Apache ayuda. Solo con bloqueos giratorios obtenemos un error php que es:

PHP Fatal error: Desconocido: Stuck spinlock (0x7fcbae9fe068) detectado en Desconocido en la línea 0

Esto parece ser un tipo de tiempo de espera, que no ocurre con pthreads, porque esos no usan tiempos de espera.

Lo que está sucediendo es probablemente algo así: http://notmysock.org/blog/php/user-cache-timebomb.html

Algunos números: un servidor tiene aproximadamente 400 accesos de caché de usuario de APC por segundo y cerca de 30 insertos por segundo (lo cual es mucho, creo), una solicitud tiene entre 20 y 100 solicitudes de caché de usuario. Hay aproximadamente 300,000 variables en el caché del usuario, todas con ttl (almacenamos sin ttl solo en nuestro redis central).

Nuestras configuraciones de APC son:

apc.shm_segments=1 apc.shm_size=4096M apc.num_files_hint=1000 apc.user_entries_hint=500000 apc.max_file_size=2M apc.stat=0

Actualmente estamos usando la versión 3.1.13-beta compilada con bloqueos por giro, usada con un antiguo PHP 5.2.6 (es una aplicación heredada, ¿escuché que esta versión de PHP podría ser un problema también?), Linux 64 bits.

Es realmente difícil de depurar, hemos escrito guiones de monitoreo que recopilan la mayor cantidad de datos que podemos obtener de la APC, el sistema, etc., pero no podemos ver nada poco común, incluso 1 minuto antes de un bloqueo.

He visto muchos problemas similares aquí, pero por ahora no hemos podido encontrar una solución que resuelva nuestro problema todavía. Y cuando leo algo así:

http://webadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan

No estoy seguro si ir con APC para un caché de usuario local es la mejor idea en entornos de carga elevada. Ya trabajamos con memcached aquí, pero APC es mucho más rápido. Pero, ¿cómo hacerlo estable?

mis mejores deseos, Andreas


A menos que se encuentre en un sistema operativo derivado de freebsd, no es una buena idea utilizar spinlocks, ya que son el peor tipo de sincronización en la faz de la tierra. La única razón por la que debe usarlos en freebsd es porque el implementador se negó a incluir el soporte de PTHREAD_PROCESS_SHARED para mutex y rwlocks, por lo que no tiene más remedio que usar el bloqueo de giro inspirado en pg-sql en ese caso.


Lección 1: https://www.kernel.org/doc/Documentation/spinlocks.txt

Las primitivas simples de bloqueo de giro anteriores no son las únicas. Son los más seguros, y los que funcionan bajo todas las circunstancias, pero en parte porque son seguros también son bastante lentos. Son más lentos de lo que deberían ser, porque tienen que deshabilitar las interrupciones (que es solo una instrucción en un x86, pero es muy costosa, y en otras arquitecturas puede ser peor).

Eso está escrito por Linus ...

Los bloqueos de giro son lentos; esa afirmación no se basa en algún artículo que leí en línea por Facebook, sino en los hechos reales del asunto.

También es un hecho incidental que los spinlocks se despliegan en niveles más altos que el núcleo debido a los mismos problemas de los que hablas; puntos muertos imposibles de rastrear debido a una mala implementación.

El kernel los usa de manera eficiente, porque es allí donde fueron diseñados para ser utilizados , bloqueando diminutas secciones minúsculas, sin sentarse y esperando que copie sus respuestas de jabón amazónico en una APC y retroceda mil millones de veces por segundo.

El tipo de bloqueo más adecuado (para la web, no para el kernel) disponible en APC es definitivamente rwlocks, tiene que habilitar rwlocks con una opción de configuración en APC heredado y es el predeterminado en APCu.

El mejor consejo que se puede dar, y ya lo di, es que no uses spinlocks, si mutex están causando que tu pila se estanque, entonces prueba rwlocks.

Antes de continuar, tu principal problema es que estás usando una versión de PHP desde antigüedad, que nadie recuerda cómo admitir , en general debes buscar actualizar, soy consciente de las limitaciones del OP, pero sería irresponsable negarse a mencionar que este es un problema real, no desea implementar en un software no compatible. Además, APC está casi sin mantenimiento, está destinado a morir. O + y APCu son su reemplazo en las versiones modernas de PHP.

De todos modos, estoy divagando ...

La sincronización es un dolor de cabeza cuando se programa en el nivel del kernel, con spinlocks, o lo que sea. Cuando se eliminan varias capas del kernel, cuando confía en 6 o 7 bits de software complicado debajo de usted sincronizándose correctamente para que su código pueda sincronizarse correctamente, la sincronización se convierte, no solo en un dolor de cabeza para el programador, sino también para el ejecutor; puede convertirse fácilmente en el cuello de botella de su brillante aplicación web, incluso si no hay errores en su implementación.

Afortunadamente, este es el año 2013, y Yahoo no es la única persona capaz de implementar cachés de usuario en PHP :)

http://pecl.php.net/package/yac

Esta es una caché extremadamente segura y sin cerraduras para PHP de usuario, está marcada como experimental, pero una vez que hayas terminado, juega con ella, quizás en otros 7 años no pensaremos en problemas de sincronización :)

Espero que llegues al fondo :)