Patrón de diseño (2): revisión del diseño del sistema de fondo de MI

  • Diagrama de flujo de planificación
  • Cómo garantizar la entrega confiable de mensajes del sistema de chat (sin perder mensajes)
  • Cómo garantizar el servicio de mensajes fuera de línea y el alto rendimiento del sistema de mensajería instantánea
  • Explicación detallada del esquema de almacenamiento de datos de mensajes de chat históricos masivos
  • Cómo elegir razonablemente la estructura de datos de Redis para almacenar mensajes sin conexión
  • Explicación detallada de la difusión de lectura y la difusión de escritura del mecanismo de envío y recepción de datos de chat grupal
  • Garantice la consistencia de los mensajes no leídos basados ​​en el script Lua
  • Análisis de Dificultades en el Diseño de Sistema de Chat de Miles de Personas
  • Análisis de las dificultades en el diseño de millones de escenas interactivas en vivo en línea
  • El mecanismo de limitación de corriente del fusible garantiza la alta disponibilidad del enlace central de envío y recepción de mensajes.
  • Diseño del sistema de mensajes Big V

Diagrama de flujo de planificación

inserte la descripción de la imagen aquí

Cómo garantizar la entrega confiable de mensajes del sistema de chat (sin perder mensajes)

  1. Si el cliente de MI envía un mensaje y necesita volver a enviarlo si se agota el tiempo o falla, el cliente debe generar una identificación para cada mensaje al enviar el mensaje, y el servidor de MI implementará un mecanismo de deduplicación basado en esta identificación.
  2. Para garantizar que el mensaje del servidor no se pierda, podemos usar el mecanismo de mensajes confiable de RocketMQ para garantizarhttps://blog.csdn.net/menxu_work/article/details/125290929
  3. El mecanismo de confirmación de recepción de mensajes a través del ACK del cliente asegura que no se pierda ningún mensaje

Cómo garantizar el servicio de mensajes fuera de línea y el alto rendimiento del sistema de mensajería instantánea

  1. Los mensajes sin conexión son mensajes enviados por otros cuando el usuario no está en línea. Estos mensajes deben recibirse cuando el usuario se conecta, ya que el cierre de sesión del usuario puede ser una operación muy frecuente. Generalmente, cuando el usuario se conecta, el servidor extraer activamente los mensajes fuera de línea Si lo extrae directamente de la base de datos, ejercerá mucha presión sobre la base de datos, por lo que generalmente elegimos algunos cachés de alto rendimiento para almacenar mensajes fuera de línea, como Redis, que puede resistir un alto acceso simultáneo. presión
  2. Por supuesto, Redis debe ser una arquitectura de clúster y, al mismo tiempo, establecer algunas políticas de almacenamiento, por ejemplo, limitar el almacenamiento de datos en la última semana o mes, y luego agregar un límite en la cantidad de mensajes almacenados. los mensajes fuera de línea de un usuario pueden almacenar hasta la última tira de 1000. O todo según el límite del número de almacenamiento.
  3. Debido a que el usuario rara vez lee todos los mensajes sin conexión en el historial después de revisar los mensajes sin conexión, mostraremos algunos mensajes sin conexión recientes. Si el usuario continúa desplazándose hacia arriba en los mensajes sin conexión, los mensajes posteriores se pueden consultar desde la base de datos. No hay problema. para que la base de datos resista la operación de pequeña probabilidad

Explicación detallada del esquema de almacenamiento de datos de mensajes de chat históricos masivos

  1. Diseño de estructura de tabla de base de datos de referencia de estructura de almacenamiento de mensajes

  2. Enviar procesamiento de mensajes
    El usuario 1 envía un mensaje al usuario 2

    • Almacenar un registro en la tabla de contenido del mensaje
    • La tabla de índice de mensajes del buzón del usuario almacena dos registros, uno es la bandeja de salida del usuario 1 y el otro es la bandeja de entrada del usuario 2, por qué se almacenan dos registros, porque habrá casos en los que el remitente y el receptor del mensaje eliminen el registro respectivamente
  3. Procesamiento de mensajes de chat de consulta Verifique los registros de chat del usuario 1 y el usuario 2

    • Consulte la identificación del índice de mensajes de chat por página
      select mid,box_type from im_user_msg_box t where t.owner_uid = 1 and t.other_uid = 2 order by mid;
      (tenga en cuenta que debe consultar por página) y luego use el bucle for para verificar el contenido de cada mensaje en la tabla im_msg_content
    • Esquema de sub-base de datos y sub-tabla
      • im_user_msg_box se divide de acuerdo con Owner_uid, la consulta de registro de chat normal no necesita una consulta de tabla cruzada
      • im_msg_content se divide de acuerdo con mid, y los mensajes de consulta se verifican básicamente de acuerdo con la clave principal de la identificación del mensaje, con un rendimiento muy alto
    • El ID del mensaje del cliente no se almacena en la base de datos, se coloca en Redis para agregar un período de validez y no se permite la duplicación dentro del período de validez.
  4. Explicación sobre el diseño de la mesa.

    • ¿Por qué dividir los mensajes enviados y recibidos en dos tablas, la tabla de índice de mensajes del buzón de correo del usuario y la tabla de contenido de mensajes para el almacenamiento?
      • Solo necesitamos leer la relación entre enviar y recibir algunos mensajes, y cuando no prestamos atención al contenido del mensaje, solo necesitamos consultar la tabla de índice de mensajes del buzón del usuario, en lugar de consultar la tabla de datos grandes del contenido del mensaje, lo que mejorará el rendimiento hasta cierto punto.
    • ¿Por qué almacenar dos índices de mensajes?
      • Las partes que envían y reciben pueden tener su propia eliminación de mensajes.
      • El índice del mensaje y el contenido del mensaje se almacenan por separado, por lo que no hará que los datos grandes, como el contenido del mensaje, se almacenen en varias copias.

Cómo elegir razonablemente la estructura de datos de Redis para almacenar mensajes sin conexión

  1. Agregar mensaje:zadd offline_msg_#{receiverId} #{mid} #{msg} //score就存储消息的id
redis.localhost.com:6379[1]> ZADD offline_msg_1 13 pqr
(integer) 1
  1. Mensaje de consulta:zrevrange offline_msg_#{receiverId} 0 9 WITHSCORES //按消息id从大到小排序取最新的十条消息,上拉刷新继续查
redis.localhost.com:6379[1]> ZREVRANGE offline_msg_1 0 9 WITHSCORES
 1) "pqr"
 2) "13"
 3) "opq"
 4) "12"
 5) "nop"
 6) "11"
 7) "mno"
 8) "10"
 9) "lmn"
10) "9"
11) "ilm"
12) "8"
13) "gil"
14) "7"
15) "fgi"
16) "6"
17) "efg"
18) "5"
19) "def"
20) "4"
  1. borrar mensaje:zremrangebyscore offline_msg_#{receiverId} min_mid max_mid //删除客户端已读取过的介于最小的消息id和最大的消息id之间的所有消息
redis.localhost.com:6379[1]> ZREMRANGEBYSCORE offline_msg_1 12 13
(integer) 2
  1. Si el almacenamiento de un solo mensaje clave es demasiado grande, puede considerar crear varios segmentos clave para el mismo ID de receptor semanal o mensualmente para almacenar

Explicación detallada de la difusión de lectura y la difusión de escritura del mecanismo de envío y recepción de datos de chat grupal

  1. Mecanismo de difusión de lectura: cuando un usuario envía un mensaje en el grupo, solo se almacena un dato y todos en el grupo leen los mismos datos del mensaje.

    • ventajas: sencillo
    • Desventajas: La lista de usuarios leídos en los mensajes de chat grupales no es muy amigable
  2. Mecanismo de difusión de escritura: cuando un usuario envía un mensaje en el grupo, se almacenará un índice de mensajes para cada usuario en el grupo, y luego el contenido del mensaje se almacenará por separado.

    • Ventajas: Es conveniente realizar la lista de usuarios de lectura de mensajes de chat grupales
    • Desventajas: la cantidad de personas en el grupo no puede ser demasiado grande, de lo contrario, el rendimiento será problemático y habrá mucho desperdicio de almacenamiento, como chatear con miles de personas, si usa la difusión de escritura, cada usuario envía un mensaje , y es necesario almacenar decenas de miles de índices

Garantice la consistencia de los mensajes no leídos basados ​​en el script Lua

  • El recuento no leído de una sesión de mensajes con alguien: por ejemplo, Zhang San envía un mensaje a Wang Wu, y se deben mantener dos claves redis, una es la clave no leída de Wang Wu más 1 y la otra es la clave no leída de Zhang San_Wang Wu más 1. La operación de sumar 1 a estas dos claves, necesitamos asegurar su atomicidad tanto como sea posible, lo cual puede ser realizado por lua script
  • Recuento total de mensajes no leídos: Menos usuarios (sumando los recuentos de mensajes no leídos de todas las sesiones de mensajes), muchos usuarios (recuento total de mensajes no leídos de dimensiones individuales)
  1. Cuando el cliente lee el mensaje, envía un mensaje al servidor y el servidor actualiza el recuento no leído después de recibirlo. En términos generales, los datos no leídos son mantenidos por el propio cliente, y los datos no leídos en el servidor son más para la sincronización de datos de terminales múltiples para el cliente.
  2. Para los conteos no leídos de los chats grupales, generalmente es posible mantener una clave de conteo no leído para cada persona en el grupo, como usar una estructura hash para almacenar los conteos no leídos de todos los usuarios en un grupo puede usar una:hincrby msg:noreadcount:gid uid 1 (gid为群id,uid为用户id)

Análisis de Dificultades en el Diseño de Sistema de Chat de Miles de Personas

  1. Problema de alta concurrencia de actualización de conteo no leído, para decenas de miles de personas chateando:

    • 1 mensaje enviado por un usuario puede activar la actualización de los recuentos no leídos de todos los usuarios del grupo, lo que equivale a actualizar los recuentos no leídos en redis 20 000 veces
    • Si este grupo es relativamente activo, asumiendo que 100 personas envían mensajes por segundo, y cada persona envía 1 mensaje, significa que este grupo solo operará redis 2 millones de veces por segundo.

    方案--定时批量更新: Debido a que los datos no leídos son mantenidos principalmente por el propio cliente, y el mantenimiento del servidor es principalmente para la sincronización de múltiples terminales, por lo que no podemos actualizar los datos no leídos en el servidor en tiempo real, sino actualizarlos en lotes a intervalos regulares.

    • Por ejemplo, los datos no leídos en redis se actualizan cada 5 segundos o más. La actualización de datos no leídos dentro de estos 5 segundos se puede actualizar en la memoria del servicio de datos no leídos. Cuando llegue a los 5 segundos, se actualizará en redis una vez.
    • Cuando el otro extremo quiere sincronizar, puede desencadenar una operación de actualización de redis con memoria sin leer y luego sincronizar nuevamente
    • Por supuesto, puede haber un tiempo de inactividad del servicio no leído en el medio, lo que resulta en la pérdida de algunos datos no leídos.
  2. El chat de decenas de miles de personas también tiene un problema de alta concurrencia:

    • 1 usuario envía 1 mensaje y reenvía el mensaje a 10 000 usuarios del grupo, lo que significa consultar la información de enrutamiento del servicio de red en redis 10 000 veces por segundo. Si este grupo es relativamente activo, 100 personas envían mensajes por segundo. Cada persona envía 1 mensaje por segundo, lo que significa que se necesitan 1 millón de consultas redis en 1 segundo. Esto es solo un grupo. Si hay miles de grupos, también causará una gran presión en redis. Este problema está relacionado con The Million-person online live La sala de transmisión de la que hablaré más adelante es muy similar, y todas tienen problemas de alta concurrencia.

Análisis de las dificultades en el diseño de millones de escenas interactivas en vivo en línea

  1. El segundo problema mencionado anteriormente de decenas de miles de personas chateando, en este tipo de sala de transmisión en vivo con millones de personas en línea, el problema será más serio. Imagínese, asumiendo que esta sala de transmisión en vivo tiene 100 personas enviando mensajes por segundo. , y cada persona envía 1 mensaje por segundo. Esto significa que se requieren 100 millones de consultas de redis por segundo. No importa cuántas máquinas haya en el clúster de redis, no podrá soportar esta presión. Entonces nuestra solución anterior definitivamente requieren Hacer optimización.
  2. En este caso, podemos entregar el mensaje a todos los servidores de red directamente sin pasar por redis. Supongamos que hay 20 servidores de red. Para una sala de transmisión en vivo con millones de personas, cada servidor de red debe tener alrededor de 50,000 conexiones de usuarios de sala en vivo. puede permitir que cada servicio de red envíe directamente el mensaje a los usuarios de la sala en vivo conectados correspondientes en su propio servidor. Por supuesto, este tipo de conexión de usuario es una situación ideal. A veces, algunos servidores de red pueden no tener casi ninguna conexión de usuario en la sala de transmisión en vivo. Entonces estos servidores de red pueden simplemente descartar el mensaje después de recibir el mensaje, y no se desperdiciarán recursos del sistema. . Por supuesto, en este caso, todos los servidores netty pueden escuchar mensajes mq.
  3. El servidor netty puede mantener un caché de la lista de usuarios conectados al servidor en la sala de transmisión en vivo o en el chat grupal, de modo que siempre que reciba el mensaje de la sala en vivo o el chat grupal, puede encontrar directamente la conexión de usuario correspondiente. mensaje de canal de acuerdo con el número de sala en vivo o la identificación de chat grupal.

El mecanismo de limitación de corriente del fusible garantiza la alta disponibilidad del enlace central de envío y recepción de mensajes.

Medidas de limitación actuales: los eventos candentes y las transmisiones en vivo de grandes V provocarán un aumento en el volumen de mensajes

  • Suelte algunos mensajes para garantizar la estabilidad de todo el sistema.
  • Si se envía una gran cantidad de mensajes al cliente cada segundo, es posible que el cliente no pueda procesarlos a tiempo. Generalmente, el cliente recibe docenas de mensajes por segundo en la sala de transmisión en vivo, que ya está llegando a su límite.

Diseño del sistema de mensajes Big V

  • Use la difusión de escritura con una pequeña cantidad de fanáticos
  • Big V requiere una combinación de difusión de lectura y escritura
    • Uso de usuario activo: Difusión de escritura
    • Uso de usuarios en línea: Difusión de escritura
    • Uso de usuarios sin conexión: difusión de lectura

Supongo que te gusta

Origin blog.csdn.net/menxu_work/article/details/128639419
Recomendado
Clasificación