Powiedziałbym, że jest to związane z wygaśnięciem ważności klucza.
Magazyny klucz/wartość, takie jak Redis lub memcached, nie mogą sobie pozwolić na zdefiniowanie fizycznego licznika czasu dla obiektu, który ma wygasnąć. Byłoby ich za dużo. Zamiast tego definiują strukturę danych, aby łatwo śledzić elementy, które mają wygasnąć, i multipleksują wszystkie zdarzenia wygaśnięcia do jednego fizycznego timera. Mają również tendencję do wdrażania leniwej strategii radzenia sobie z tymi wydarzeniami.
Dzięki Redis, gdy element wygaśnie, nic się nie dzieje. Jednak przed każdym dostępem do pozycji przeprowadzana jest systematyczna kontrola, aby uniknąć zwracania przeterminowanych pozycji i potencjalnie usuwać pozycję. Oprócz tej leniwej strategii, co 100 ms uruchamiany jest algorytm oczyszczania, który fizycznie wygasa pewną liczbę pozycji (tj. usuwa je z głównego słownika). Liczba branych pod uwagę kluczy w każdej iteracji zależy od obciążenia wygaśnięcia (algorytm jest adaptacyjny).
Konsekwencją jest to, że Redis może mieć zaległości z elementami do wygaśnięcia w danym momencie, gdy masz stały przepływ zdarzeń wygaśnięcia.
Wracając do pytania, polecenie DBSIZE po prostu zwraca rozmiar głównego słownika, więc zawiera pozycje wygasłe, które nie zostały jeszcze usunięte. Polecenie KLUCZE przechodzi przez cały słownik, uzyskując dostęp do poszczególnych kluczy, więc wyklucza wszystkie wygasłe elementy. W związku z tym liczba elementów może się nie zgadzać.