пятница, 6 июля 2012 г.

VmWare Player could not open /dev/vmmon

Сегодня моргнул свет и девелоперская машина перезагрузилась. После этого VmWare Player перестал запускать виртуальную машину с svn, выдавая следующее сообщение:

Could not open /dev/vmmon: No such file or directory.
Помогла перекомпиляция модулей.

sudo rm /lib/modules/2.6.32-41-generic-pae/misc/*
sudo vmware-modconfig –console –install-all --appname="VMware Player" --icon="vmware-player"

четверг, 5 июля 2012 г.

VmWare Server умер...

Наверное, вчера был последний день, когда я использовал VmWare сервер. Он долго крутился, до тех пор пока после очередного обновления Ubuntu 10.04 до ядра 2.6.32-41 Web Access перестал запускаться. Все попытки реанимировать этого динозавра ни к чему не привели.
   С одной стороны обидно, что он умер на практически ровном месте, а с другой стороны столько долго работать с софтом, который уже несколько лет не поддерживается производителем - моветон.
  Радует хоть то, что почти все важные сервисы я давно перевел с vmware виртуалок в Xen, поэтому непредвиденной срочной миграции делать не пришлось.  Оперативно перетаскивать пришлось только один сервис, который раздавал файлы кроссдомена пользователям сайта.
   Из важного же остался svn, да девелоперские базы данных, но они, в принципе, смогут временно покрутиться и в VmWare Player на девелоперской машине, пока не перенесу их в другое место.
 
 Зато теперь столько оперативки освободится!

среда, 4 июля 2012 г.

Bash и кавычки

Довольно редко приходится писать что-то с использованием bash, но вот вчера возникла такая необходимость. И оказалось, что в bash совсем нетривиально передать в командную строку символ двойных кавычек ". Как ни пробовал (с экскейп-символами, с заворачиванием строку в одинарные кавычки и т. д.) - никак не получалось, только один способ помог:

agent="my user agent"
cmd="wget http://mysite.com -U $agent"
eval $cmd

вторник, 19 июня 2012 г.

МТС коннект

Зарекался я никогда не связываться с МТС, потому что хуже оператора по отношению к клиентам не найти... А тут пришлось покупать 3G модем, чтобы мониторить работоспособность сервисов, будучи за городом. Так как у Мегафона карта покрытия 3G вообще на сайте не отображается (сервер не работает) и это уже не в первый раз, а у МТС на карте как раз покрывается регион, куда я еду, то я решил взять модем МТСа.  Почему Билайн не стал смотреть - не знаю, наверное потому что мне сказали, что у МТС там все работает нормально.

Купил модем и в очередной раз убеждаюсь, что лучше бы с этим говнооператором не связывался.
Во-первых, модем у меня так и не запустился на линуксовом нетбуке с Ubuntu 10.04. Если не смогу настроить за сегодня, то придется с собой тащить здоровый виндовый ноут, чего бы делать не хотелось....
Во-вторых, на винде, установка прошла тоже не гладко, установщик повесил мне намертво какую-то системную программу и при этом завис сам. Но после все же установился.

Но самое главное, я купил модем на 14 мегабит, замерил скорость и оказалось, что до города, где я живу скорость скачки 1.5Мбит/с, а до Москвы - 2 Мбит/сек. И это при том, что я нахожусь в том месте, где покрытие 3G очень плотное. Какого хрена эти мудаки продают продукт, со свойствами в 10 раз хуже обещанных???

А ведь еще, в качестве опции, можно было доплатить 350 рублей и радоваться скоростью в полтора мегабита на модеме 21.6!

суббота, 16 июня 2012 г.

Redis в жизни

Итак, первый, а точнее второй пост (первый был про то, как я все это ненавижу) будет о редисе. Нет, не о том редисе, который выращивают бабушки на грядках своих полуразрушенных дачных участков и продают потом нам у метро, а о современной NoSQL базе данных, которая помогает обеспечить быстрый доступ до часто изменяемых/требуемых данных. 

Для тех кто не знает, Redis позволяет легко организовать out of process memory cache и, помимо этого, имеет возможность сохранять данные на жесткий носитель, что превращает его из обычного кэша в полноценную базу данных. Так как у редиса достойная производительность, то для своего проекта, где требуется хранить миллионы key-value записей я выбрал его. Я не админ, поэтому если мне хочется поставить какой-либо софт, то чтобы он сразу работал и забыть про него насовсем. И вроде бы redis это позволяет сделать: легко устанавливается, в процессе работы не  падает, но... как всегда есть свои тонкости, которые не дают спокойно жить.

У редиса есть три возможности работать с данными: in-memory, когда на диск ничего не созраняется, rdb - когда раз в x секунд вызывается функция сохранения всех данных на диск и aof - когда измененные данные постоянно дописываются в журнал на диск в режиме append, а потом проигрываются по журналу, в случае, например, сбоя.

Я выбрал режим rdb - просто потому что он был проще в понимании и, к тому же, в документации не было сносок, как про aof, что в некоторых случаях все может накрыться.

Выбрал и выбрал. Настроил чтобы раз в 5 минут база пересохранялась (мне не сильно страшно, если 5 минут последних изменений пропадут в случае каких-либо проблем типа отключения питания), сделал регулярные бэкапы rdb файла на другую машинку ну и вроде можно забыть... но оказалось, что нет!

Итак, проблема номер 1. База постоянно растет в размере (что ожидаемо), скорость роста базы не сильно высока и ожидать заполнения 8-ми гигов оперативной  памяти базой следует месяцов эдак через 6. Вроде все время можно отдыхать, пока не будем подходить к верхней планке, но не тут было!
На машине 8GB, текущий размер базы стал примерно 3.7GB. Посмотреть размер базы можно с помощью команды INFO в клиенте редиса redis-cli. Там выводятся следующие параметры:

used_memory - сколько памяти редис навыделял для базы
used_memory_rss - сколько редис отъедает памяти у OS (эта цифра больше, из-за фрагментации памяти)
used_memory_peak - хрен бы знал что это значит, потому что цифра всегда меньше, чем used_memory
Так вот, как только редис отожрал примерно половину памяти операционки он перестал сохранять данные на диск. Заметил я это не сразу, а через пару дней, когда машина перезагрузилась из-за проблем с электричеством. Офигенно! Естественно, все бэкапы никак помочь не могли, потому что в них просто не было данных, которые остались в оперативке.

В общем, стал разбираться, и выяснилось следующее. Redis использует fork() в операционной системе, для того, чтобы сделать полную копию текущего процесса и в бэкграунде сохранить данные. А fork работает хитрым образом, допустим есть 4GB данных - он не копирует полностью страницы памяти в новые, а просто оставляет ссылки, и новые страницы памяти выделяет только в том случае, если в родительском или порожденном процессе с этими страницами произошли какие-то изменения. Так как редис второй процесс использует для чтения данных, то речь идет об измененных данных в родительском процессе. Получается, дополнительная память расходуется только в том случае, когда клиенты редиса меняют значения ключей в процессе сохранения на диск.

Но у меня-то данных меняется не так-то уж и много за то время, пока файл сохранялся, памяти должно хватать, а редис настойчиво пишет "could not allocate memory" в логах. Почему?

Стал смотреть дальше, оказывается, OS тоже не проста и очень интересно работает с fork(). Вот пример: база данных 4.1GB, в процессе сохранения изменяется 10MB даных, соответсвенно пик использования памяти во время fork() должен быть 4.11GB.  Хватит ли оперативной памяти размером
 8GB?  При дефолтных настройках получается, что не хватит. А все потому, что OS до начала fork не знает, сколько реально памяти потребуется процессам, и предполагает самый худший вариант, когда все страницы придется продублировать. Ну а так как 8.2 GB уже не помещаются в оперативку, то операционка отказывается начинать делать fork() c out of memory.

К счастью, тут OS удается обмануть. Есть две настройки: vm.overcommit_memory и vm.overcommit_ratio. Посмотреть текущие значения можно либо командой
sysctl vm.overcommit_ratio
либо
cat /proc/sys/vm/overcommit_ratio

Эти настройки позволяют затюнить OS так, чтобы она не отказывала в выделении памяти, даже если ее реально нет. Для это значение overcommit_memory должно быть установлено в 2. Тогда, OS будет считать, что количество памяти зависит от overcommit_ratio. Вот формула, по которой высчитывается доступная память в зависимости от overcommit_ratio:
 
allocatable memory=(swap size + (RAM size * overcommit ratio))

overcommit_ratio здесь указывается в процентах. 

Так как swap у меня небольшой по размеру, то я в overcommit_ratio указал значение 200, что увеличило доступную память чуть более чем в два раза.

сделать это можно либо командой sysctl, либо изменив /ect/sysctl.conf


sysctl -w vm.overcommit_memory=2
sysctl -w vm.overcommit_ratio=200

Но редис все равно приходится постоянно мониторить на предмет сохранения данных. Команда  
tail -f /var/log/redis_6379.log | grep save 
помогает в этом и если нет кучи записей с ошибками выделения памяти, то вроде все нормально.

Подробнее про настройки виртуальной памяти можно прочитать тут (с одной поправкой: в статье перепутали значения 1 и 2 для  vm.overcommit_memory)

Проблема номер 2. Я пока еще не оценил по достоинству данную проблему, но, думаю, в скором времени она доставит много неприятностей. Дело в том, что Redis очень медленно делает fork, когда работает под Xen! При сохранении 7-гигового сета время форка занимает около секунды. (Узнать время, которое тратится на fork() можно воспользовавшись командой Redis INFO и смотреть параметр latest_fork_usec - показывает время форка в микросекундах).  А это может создать очень много неприятностей, так как в течении форка редис блокируется и становится недоступным для клиентов. Представьте, когда в высоконагруженной среде с тысячами одновременно работающих клиентов в течении секунды нельзя обратиться к кэшу.  Как пишут разработчики redis, это проблема Xen, так как нигде больше не наблюдается.

Может спросить, почему на Xen свет клином сошелся? Да хотя бы просто потому, что у меня на сервере стоит xen, под которым крутятся разные виртуалки,  а кроме того почти все облака так или иначе построены на технологии Xen.