Короче, с горем пополам проблему решил.
Проблема оказалась, как я и думал, в
неправильном сжатии: php-memcached сжимает данные как deflate, а nginx признает только gzip и, кстати, тут последний прав - gzip, в отличие от deflate, грубо говоря, "более однозначный" и работает даже с самыми глючными браузерами.
Писал разрабам php-memcached с предложением добавить сжатие gzip, но те, судя по всему, консерваторы и ничего менять не хотят (как чувствовал подвох, когда смотрел на
дату последней версии). Самое забавное, что добавить поддержку gzip там проще простого -
работы на 20 минут максимум, исходники
простые даже для меня, далёкого от C. Сначала думал самому предложить им изменения, но да ну их... Расширение снёс. Сделал через сокеты, как оказалось работать с memcached напрямую
не так уж и сложно.
$key = 'key';
$flags = 1;
$expire = 0;
$value = gzencode('value', 6, FORCE_GZIP);
$length = strlen($value);
if (!fwrite($memcached, "set {$key} {$flags} {$expire} {$length}\r\n{$value}\r\n")) {
throw new Exception('Memcached write error.');
}
$flags - битовые флаги. Устанавливаю эту переменную равным 1, если $value сжато, иначе 0.
В конфиге nginx соответственно memcached_gzip_flag устанавливаем в 1.
Итого работает это так: сжатие $value экономит место в оперативке. nginx если видит флаг 1, то отдаёт в заголовке ответ "Content-Encoding: gzip", повторно не сжимая, таким образом ещё и процессорное время экономим. Если браузер не поддерживает gzip, то nginx декодирует $value и отдаст без сжатия.