Кеширане на изображенията на броячите в паметта
Близо една пета от изображенията на броячи, които тази услуга рисува, вече не променят нищо. Скрипт за проследяване на мишката от предишното поколение презарежда изображението при всяко движение и откакто тези заявки спряха да увеличават каквото и да е, две поредни от тях дават една и съща картинка, байт по байт.
Очевиден кандидат за кеш. Интересните решения бяха къде да бъде той и по какво да се образува ключът.
Не на диска
Всичко това работи на малък сървър, а дискът е SD карта. Кеширането на нарисуваните изображения върху нея би означавало около 70 MB записи на ден, в замяна на измерена икономия от 1,6 минути процесорно време на ден.
Това е лоша сделка. SD картите се повреждат от записване, а купуваното е грешка от закръгляне на машина, която не е ограничена от процесора. Затова кешът се намира в /dev/shm, което е tmpfs, тоест RAM. Измерено там: 0,027 ms за четене, 0,036 ms за запис, 1,9 GB свободни.
При рестартиране всичко изчезва. За кеш това не е загуба, а нормалният случай.
На същата машина работи Redis. Той не беше използван по причина, която няма нищо общо с технологията: принадлежи на друго приложение и е защитен с парола за него. Споделянето на една инстанция би обвързало две несвързани услуги, така че лош ден за едната да стане лош ден и за другата.
Ключът съдържа числата
Обичайният ключ на кеша е идентичност плюс срок на валидност, а срокът е залог: че нищо важно не се е променило през последните пет минути. При брояча онова, което се променя, е точно онова, което се показва.
Затова показваните стойности отиват вътре в ключа. Ако някое число се промени, ключът е друг и изображението се рисува наново. Залогът изчезва, вместо да бъде правен внимателно. Всяко преброено посещение увеличава поне общата сума за цялото време, така че на нито едно преброено посещение не може да бъде сервирана остаряла картинка. Оставащият срок на валидност е само горна граница за стойностите, които не са в ключа — седмичните, месечните и годишните числа.
Какво трябваше да се провери първо
Кешът е безопасен само ако кешираното е функция на неговия ключ. Това е твърдение за всеки дизайн и то беше проверено, а не прието наготово:
- нито един дизайн не използва
rand(),mt_rand(),shuffle()илиuniqid() - нито един дизайн не чете часовника по-точно от час
- параметрите за проследяване от стария скрипт не се четат никъде в дървото на кода
Последната точка доведе до най-хубавия провал в цялото упражнение. Докато тези параметри още бяха част от ключа, всяка заявка носеше малко по-различни координати на мишката, така че всеки ключ беше уникален. Кешът работи цял ден и регистрира 13 попадения. Работеше перфектно и не правеше нищо, а това е най-трудно забележимият вид повреда.
А ако нещо тук се провали — нечетима директория, пълен диск, повреден запис — изображението просто се рисува по нормалния начин. Кешът никога не трябва да бъде причината един брояч да не се появи.