O armazenamento de dados real e o cache devem ser sincronizados usando a terceira abordagem que você já descreveu em sua pergunta.
À medida que você adiciona dados ao seu armazenamento definitivo (ou seja, seu banco de dados SQL), você precisa enfileirar esses dados em algum barramento de serviço ou fila de mensagens e deixar algum serviço assíncrono fazer toda a sincronização usando algum tipo de processo em segundo plano.
Você não quer entrar nestes casos (quando não estiver usando um barramento de serviço e serviço assíncrono):
- Deixe suas solicitações ou processos mais lentos porque o usuário precisa esperar até que os dados sejam armazenados no banco de dados e no cache.
- Correr o risco de falhar durante o processo de armazenamento em cache e não poder ter uma política de repetição (que geralmente é um recurso interno em um barramento de serviço ou em algumas filas de mensagens). Além disso, essa falha pode resultar em uma corrupção parcial ou completa do cache e você não poderá agendar automaticamente e facilmente alguma tarefa para corrigir essa situação.
Sobre o uso da expiração da chave Redis, é uma boa ideia. Como o Redis pode expirar chaves usando seu mecanismo interno, você não deve implementar a expiração de chave de todo o processo em segundo plano. Se existe uma chave é porque ainda é válida.
BTW, você não estará sempre neste caso (se uma chave não expirou, significa que ela não deve ser substituída). Pode depender do seu domínio real.