Esta es una pregunta que me hicieron en una entrevista de trabajo, y no puedo encontrar la respuesta que estaban buscando, así que espero que alguien aquí tenga algunas ideas. El objetivo es escribir una función que garantice que nunca devolverá el mismo valor dos veces. Suponga que varias máquinas tienen acceso a esta función simultáneamente.
Mi idea era asignar a cada máquina una identificación única y pasar ese valor a la función de generador de valor único:
var i = 0;
function uniq(process_id, machine_id) {
return (i += 1).toString() + machine_id + "-" + process_id;
}
Esto evitaría las consecuencias de las condiciones de carrera, ya que incluso si dos o más procesos leen el mismo valor i
, cada valor de retorno está etiquetado como una combinación única de identificación de proceso e identificación de máquina. Sin embargo, a mi entrevistador no le gustó esta respuesta porque poner otra máquina en línea implica asignarle una identificación.
Entonces, ¿alguien puede pensar en otra forma de resolver esto que no implique configurar cada máquina para que tenga una identificación única? Me gustaría tener una respuesta en caso de que esta pregunta vuelva a surgir. Gracias.
fuente
Respuestas:
No se preocupe, simplemente arroje un contador simple (seguro) detrás de algún punto final de comunicación (WCF, servicio web, lo que sea):
Sí, eventualmente se desbordará. Sí, no maneja reinicios. Sí, no es al azar. Sí, alguien podría ejecutar esto en varios servidores.
Esto es lo más simple que satisface los requisitos prácticos. Luego, permítales que sean los que sigan con esos problemas (para asegurarse de que entiendan las limitaciones, ¿ realmente creen que necesita más de 2 ^ 64 identificadores), para que pueda preguntar qué compensaciones están bien. ¿Necesita sobrevivir a los reinicios? ¿Qué pasa con la falla del disco duro? ¿Qué hay de la guerra nuclear? ¿Tiene que ser al azar? ¿Qué tan aleatorio?
fuente
x
. Y creo que sin una explicación sobre el tipo de mecanismo de enclavamiento que tienes en mente, esta respuesta es bastante vaga.System.Threading.Interlocked
clase, que proporciona incrementos atómicos. Pero también podría leer esto como una especie de pseudocódigo.Si me hicieran esa pregunta, y dejaran en claro que tiene que ser única en los reinicios y en diferentes máquinas, les asignaría una función que invoca el mecanismo estándar para crear un nuevo GUID, sea lo que sea que esté en El lenguaje utilizado.
fuente
El entrevistador dijo que el método se llamará simultáneamente, no en paralelo; simplemente regrese la fecha / hora a tantos decimales como pueda.
¿Por qué todos piensan demasiado en esto? Estarás muerto mucho tiempo antes de que se gaste cualquier finitud y no tengas la posibilidad de una colisión.
Si le preocupa que regrese al mismo tiempo, agregue un retraso por la menor cantidad de tiempo medible.
Si le preocupa retrasar el reloj para el horario de verano (experimentar 1 vez dos veces), agregue una constante a la hora la segunda vez que lo experimente.
fuente
En primer lugar, querrá hacerle dos preguntas al entrevistador.
Pregunta 1.
si el entrevistador espera que se usen una o más "máquinas centrales" para asignar algunos números únicos o bloques de números únicos.
Pregunta 2.
Si el entrevistador espera un mecanismo para la detección de colisión, o si acepta el riesgo calculado de una posibilidad minúscula de colisión sin detectarlos explícitamente.
También existe el enfoque de defensa en profundidad, en el que uno incorpora alguna parte de la identificación de usuario en la aleatoriedad (por lo tanto, no completamente al azar). Por lo tanto, se reduce la posibilidad de que el mismo usuario encuentre una colisión dentro del contenido creado por ese mismo usuario.
Hay una pregunta implícita 3, ...
Pero es uno que tendrá que evaluar sin preguntar, porque es extremadamente descortés preguntarle a su entrevistador.
Si el entrevistador asume el conocimiento de probabilidad, riesgo y algunas técnicas simples empleadas en sistemas criptográficos y de seguridad de la información.
El primer tipo de conocimiento asegura que no está tratando de convencer a una persona no científica para que acepte un concepto científico que no aceptará.
El segundo tipo de conocimiento asegura que se aborden las preocupaciones que se suman a la mera probabilidad. En otras palabras, cómo defenderse de los "asaltantes" que desean romper intencionalmente su esquema de aleatorización, manipulando las máquinas o sus hosts virtuales para forzar a dos máquinas a generar el mismo valor.
Por qué preguntar.
La razón es que si el entrevistador lo espera de una forma u otra, tratar de responder con el enfoque opuesto nunca hará feliz al entrevistador.
La razón más profunda es que a algunas personas no les gusta la idea de decir, una
1.0e-20
posibilidad de fracasar. (Intentaré no despertar argumentos filosóficos o religiosos aquí).En primer lugar, el "espacio de nombres" de los números aleatorios se convierte en una jerarquía, con cierto número de bits asignados a una fuente de aleatorización, y el otro número de bits asignados a otras formas, etc.
El enfoque centralizado se basa en alguna autoridad central para asignar de forma exclusiva el primer nivel de bits. Luego, las otras máquinas pueden llenar el resto de los bits.
Existen varios enfoques descentralizados:
fuente
Entonces, teniendo en cuenta que esta es una pregunta de entrevista y no un escenario real de la vida real, creo que el enfoque correcto (y probablemente lo que el entrevistador está buscando) es hacer una pregunta aclaratoria o escribir "No puede ser hecho "y seguir adelante. Este es el por qué.
Lo que pide el entrevistador:
Lo que necesita el entrevistador:
Nunca asumas.
Cuando a un ingeniero se le entrega un requisito (a través de una SOW o una Especificación o algún otro documento de requisitos), algunos son evidentes y otros no son del todo claros. Este es un ejemplo perfecto de esto último. Como han mostrado las respuestas anteriores, no hay forma de responder a este requisito sin hacer varias suposiciones importantes, ya sea (a) en cuanto a la naturaleza de la pregunta o (b) en cuanto a la naturaleza del sistema, porque el requisito no puede cumplirse tal como está escrito (es imposible).
La mayoría de las respuestas hacen un intento u otro para resolver el problema a través de una serie de suposiciones. Uno recomienda específicamente hacerlo rápidamente y dejar que el cliente se preocupe si está mal.
Este es realmente un mal enfoque. Como cliente, si doy un requisito poco claro, y el ingeniero se va y me crea una solución que no funciona, me enojaría que se pusieran a trabajar y gastaran mi dinero sin molestarse en preguntarme primero. Ese tipo de toma de decisiones arrogante demuestra una falta de trabajo en equipo, incapacidad para pensar críticamente y falta de juicio. Puede conducir a cualquier tipo de consecuencias negativas, incluida la pérdida de vidas en un sistema crítico de seguridad.
¿Por qué hacer la pregunta?
El punto si este ejercicio es que es costoso y lleva mucho tiempo construir con requisitos ambiguos. En el caso del OP, se le ha asignado una tarea imposible. Su primera acción debería ser pedir una aclaración: ¿qué se requiere? ¿Qué grado de singularidad se necesita? ¿Qué sucede si un valor no es único? La respuesta a estas preguntas podría ser la diferencia entre varias semanas y unos minutos. En el mundo real, uno de los mayores factores de costo en los sistemas complejos (incluidos muchos sistemas de software) son los requisitos poco claros y poco conocidos. Esto conduce a errores costosos y que consumen mucho tiempo, rediseños, frustración de clientes y equipos, y una cobertura mediática vergonzosa si el proyecto es lo suficientemente grande.
¿Qué sucede cuando asumes?
Dado mi experiencia en la industria aeroespacial, y debido a la naturaleza altamente visible de las fallas aeroespaciales, me gusta presentar ejemplos de este dominio para ilustrar puntos importantes. Examinemos un par de misiones fallidas de Marte: Mars Climate Orbiter y Mars Polar Lander. Ambas misiones fallaron debido a problemas de software, porque los ingenieros hicieron suposiciones inválidas debido, en parte, a requisitos poco claros y mal comunicados.
Mars Climate Orbiter : este caso generalmente se cita como lo que sucede cuando la NASA intenta convertir el inglés a unidades métricas. Sin embargo, esa es una representación demasiado simplista y pobre de lo que realmente ocurrió. Es cierto que hubo un problema de conversión, pero se debió a requisitos mal comunicados en la fase de diseño y a un esquema de verificación / validación incorrecto. Además, cuando dos ingenieros diferentes notaron el problema porque era obvio a partir de los datos de la trayectoria de vuelo, no plantearon el problema al nivel adecuado porque asumieron que era un error de transmisión. Si el equipo de operaciones de la misión hubiera tenido conocimiento del problema, habría tiempo suficiente para corregirlo y salvar la misión. En este caso, había una condición lógica imposible que no se reconoció por lo que era, lo que condujo a un costoso fracaso de la misión.
Marte Polar Lander- este caso es un poco menos conocido, pero posiblemente más vergonzoso debido a su proximidad temporal a la falla del Mars Climate Orbiter. En esta misión, el software controlaba el descenso asistido por el propulsor del cohete hacia la superficie marciana. En un punto a 40 metros sobre la superficie, las patas del módulo de aterrizaje se desplegaron en preparación para aterrizar. También había un sensor en las piernas que detectaba movimiento (para indicar cuándo habían impactado) para indicarle al software que apague el motor. La mejor suposición de la NASA sobre lo que sucedió (porque hay múltiples fallas posibles y datos incompletos) es que las vibraciones aleatorias en las piernas debido a su despliegue simultáneo y dispararon incorrectamente el mecanismo de apagado a 40 metros de la superficie, lo que provocó el choque y la destrucción de los $ 110 M nave espacial. Esta posibilidad se planteó en el desarrollo, pero nunca fue abordado. En última instancia, el equipo de software hizo suposiciones inválidas sobre cómo este código debía ejecutarse (una de esas suposiciones es que una señal espuria sería demasiado corta para ser detectada, a pesar de las pruebas que muestran lo contrario), y esas suposiciones nunca fueron cuestionadas hasta después el hecho.
consideraciones adicionales
Entrevistar y evaluar a las personas es un asunto complicado. Hay varias dimensiones de un candidato que un entrevistador puede desear explorar, pero una de las más importantes es la capacidad de un individuo para pensar críticamente. Por una variedad de razones, una de las cuales es que el pensamiento crítico está mal definido, nos resulta muy difícil evaluar las habilidades de pensamiento crítico.
Como instructor de ingeniería, una de mis formas favoritas de evaluar la capacidad de un estudiante para pensar críticamente era hacer una pregunta algo ambigua. Los estudiantes más agudos captarían la premisa defectuosa de la pregunta, la notarían y responderían dada la premisa o rechazarían responder por completo. Por lo general, haría una pregunta similar a la siguiente:
(Por cierto, te sorprendería la frecuencia con la que aparece una especificación tan pobre en el lugar de trabajo).
Espero que los estudiantes reconozcan que no es posible crear una característica perfecta y que lo declararán en su respuesta. Por lo general, otorgaría un punto de bonificación si dicen que volverán al diseñador y pedirán una aclaración antes de hacer la parte. Si un estudiante procede a decirme cómo van a lograr una planaridad de .001 o algún otro valor inventado, otorgo cero puntos. Esto me ayuda a decirles a mis alumnos que necesitan pensar en el panorama general.
Línea de fondo
Si estoy entrevistando a un ingeniero (o una profesión similar), estoy buscando a alguien que pueda pensar críticamente y cuestionar lo que se le ha puesto delante. Quiero a alguien que haga la pregunta "¿Tiene sentido?" .
No tiene sentido pedir una parte perfectamente plana, porque no existe tal cosa como perfecta. No tiene sentido pedir una función que nunca devuelva un valor duplicado, porque es imposible hacer tal garantía. En la programación, a menudo escuchamos la frase "basura adentro, basura afuera". Si le entregan basura por requisitos, es su responsabilidad ética detenerse y hacer cualquier pregunta que lo ayude a obtener la verdadera intención. Si estoy entrevistando a un candidato y le doy un requisito poco claro, esperaré preguntas de aclaración.
fuente
Garantizar la unicidad es difícil porque las computadoras no tienen variables infinitamente grandes. Ninguna máquina de Turing del mundo real puede.
A mi modo de ver, hay dos problemas aquí, y ambos tienen soluciones bien establecidas.
Aquí está mi solución en Java:
BigInteger es un tipo entero de tamaño arbitrario. Puede crecer para mantener valores que son bastante grandes, incluso si no son infinitos. El bloqueo garantiza la concurrencia, por lo que el mismo valor no puede ser devuelto dos veces por dos solicitudes simultáneas atendidas por subprocesos separados.
fuente
Expondría la función a través de un puerto en el servidor; Para llamar a la función, la máquina solicitante solicita una conexión y se le concede una, al tiempo que se le asigna un código de identificación (número secuencial para simplificar). Cada vez que se envía un mensaje al puerto solicitando el valor único, el valor se genera concatenando el hash MD5 de la fecha y hora actual con el hash MD5 del código de identificación.
Si quieren una solución más a prueba de balas, tendrían que especificar sus requisitos reales en lugar de ser tan vagos sobre las cosas.
fuente
De la manera anterior, podemos asegurarnos de que el valor de retorno sea diferente incluso si se reinicia o incluso si se llama simultáneamente desde diferentes máquinas.
fuente