serwer pocztowy oparty na bazie danych

daaawno temu zastanawiałem się ze znajomymi nad napisaniem serwera pocztowego który trzymałby wszystko – włącznie z mailami – w bazie danych.

mieliśmy kilka pomysłów, ale finalnie brak czasu projekt zabił na etapie gdy jeszcze nie było nawet linijki kodu.

dziś przeczytałem o projekcie archiveopteryx.

jest to rozwiązanie służące zasadniczo do tego co my chcieliśmy. ale z kilkoma rozwiązaniami zaczerpniętymi z gmaila (labele).

co większe feature'y:

  • zaprojektowany tak by nie wprowadzać żadnych sztucznych ograniczeń na maile
  • skalowalny. w tym – obsługujący jakąś (nie testowałem jeszcze więc nie znam szczegółów) formę clustrowania
  • maile (i załączniki jak rozumiem) są przechowywane w mocno znormalizowanej postaci dla uniknięcia duplikatów (ma znaczenie przy oparciu o to np. list mailingowych)
  • obsługa folderów pocztowych
  • obsługa folderów “wirtualnych" – zapisanych reguł filtrowania maili. przykładowo:
    • wszystkie maile do/od pana x
    • wszystkie listy z listy mailingowej y
    • nowe maile do mnie
  • pojedynczy mail może należeć do wielu folderów
  • obsługuje praktycznie wszystkie istotne standardy: smtp, imap, pop3, sasl, tls, sieve, lmtp
  • przezroczysta obsługa funkcji “undelete"

standardowa instalacja obejmuje jakiś front-endowy serwer pocztowy zajmujący się np. tagowaniem spamu, relayowaniem czy odsiewaniem wirusów. dopiero potem, maile lokalne, trafiają do archiveopteryxa.

system jest zaprojektowany pod długotrwałą archiwizację.

całość działa na postgresie (stąd się o tym dowiedziałem) i podobno jest bardzo sympatyczne – aczkolwiek posługuję się tu opiniami osób trzecich – sam nie miałem okazji potestować.

wykonywanie automatycznych zadań w postgresie

do całkiem niedawna jedyną metodą wykonywania okresowych, automatycznych zadań w postgresie było użycie crona.

teraz sytuacja się zmieniła. pojawił się pakiet pgagent. a dokładniej nie tyle pakiet, co rozwiązanie. gdyż pgagent jest częścią pgadmina.

pgagent jest daemonem działającym “obok" bazy danych, który przechowuje w bazie informacje co i kiedy i jak należy wykonać. i wykonuje.

każde zadanie może składać się z wielu “kroków", gdzie krokiem może być zarówno zapytanie sql jak i np. wykonanie skryptu shellowego.

soft wygląda interesująco i na pewno znajdzie sporo zwolenników. mnie aktualnie boli w nim jednakże kilka rzeczy:

  1. silne powiązanie z pgadminem. pgadmina nie używam i niespecjalnie lubię. jestem miłośnikiem psql'a i nakładki graficzne traktuję jako “dziwne pomysły".
  2. wszystko jest odpalane z konta superusera. co oznacza, że jeśli np. z agenta tworzymy tabelkę (np. comiesięczna archiwizacja) to potem musimy pamiętać oodpowiednich grantach albo alter table set owner'ach. niby niewielki problem, ale jednak
  3. powiązane z powyższym – sporo wszystko działa z konta superusera, to nie można dać prawa definiowania zadań zwykłym userom. bo to by była dziura bezpieczeństwa.

mimo tych wad, uważam, że jest to krok w dobrym kierunku i na pewno każdy admin doceni możliwość zgrania wszystkiego co tyczy się bazy danych poprzez jeden prosty dump.

nowy system replikacyjny do postgresa i nie tylko!

enterprisedb, firma której przedstawiać chyba nie muszę, od wczoraj oferuje swoje rozwiązanie replikacyjne: EnterpriseDB Replication Server.

co to i co potrafi?

na pierwszy rzut oka to co slony:

  • asynchronicznie
  • master + multi-slave

do tego niby jakieś narządka tylko replication console.

diabeł (a w tym przypadku raczej anioł) tkwi w szczegółach.

po pierwsze – do rzeczonego silnika replikacyjnego jest coś o nazwie: “Database Pooling Connection Framework". z tego co zrozumiałem z jednozdaniowego opisu, wynika, że zarządza to rozrzucaniem zapytań po bazach master/slave. i to w sposób w miarę inteligentny – wykrywając zapytania modyfikujące?!

po drugie – ten silnik replikacyjny pozwala replikować między postgresem i enterprisedb – co jest oczywiste, bo enterprisedb to też postgres. ale potrafi też replikować z/na oracle'a!

jest to o tyle dodatkowo ciekawe, że enterprisedb (firma) oferuje też pakiet do postgresa dla zachowania dużej kompatybilności zapytań. idea jest taka, że zapytania z oracle'a, działają na postgresie (a dokładniej na enterprisedb).

czyli całośc pozwala na zrobienie live migracji na postgresa a potem przepięcie aplikacji klienckich, albo ich część, na bazę która jest sporo tańsza!
całość pewnie będzie trochę kosztowała, ale może się okazać interesującą alternatywą dla slony'ego w zastosowaniach bardziej komercyjnych.

nowa zabawka – część trzecia, ostatnia

dostałem informację ile kosztowały te maszynki.

starsza, w/g ceny z 27 lipca 2005 – około $8300 (podaję ceny w dolarach, bo maszyny były kupowane w różnych krajach, od różnych dostawców).

nowa – (w/g ceny z 22 czerwca 2006) – około $55700.

czyli starsza jest 6.7 raza tańsza niż nowsza, a daje wydajność (w/g testów) na poziomie 6.1 raza wolniej niż nowsza.

czyli teoretycznie starsza jest lepsza.

ale z drugiej strony – są zadania których starsza w ogóle nie zrobi, gdyż ma tylko 4 giga ramu i mało dysków. za większe pieniądze dostaliśmy sporo szybszą maszynę, która potrafi robić też rzeczy które są fizycznie nieosiągalne dla tańszej (no chyba, żeby ją rozbudować, ale to też koszt).

reasumując – maszynka (nowa) jest w/g mnie całkowicie warta swojej ceny i mogę każdemu polecić taką konfigurację.

nowa zabawka – c.d.

tak jak obiecałem – zrobiłem mocniejsze testy.

najpierw tylko takie info – jak pamiętacie poprzednio robiłem pgbencha -s 750. i na ustawieniach praktycznie “defaultowych" robił maksymalnie 830 tps. po dokonfigurowaniu robił (przy 100 połączeniach jednocześnie, czyli wtedy gdy poprzedni config robił 780-790) w zależności od nie wiem czego od 960 do 1070 tps'ów. całkiem ładnie.

potem zrobiłem bazę ze skalą pgbencha 7500. wielkość bazy – 120 giga, czas robienia pgbench -i – 150 minut.

ponieważ każdy test (każde concurrency) robię na czystej bazie, stwierdziłem, że robienie za każdym razem inicjalizacji po 150 minut odpada.

skopiowałem więc cały katalog $PGDATA na bok, i robiłem testy kopiując co test czysty katalog na miejsce “zużytego".

skrypt testujący:

#!/bin/bash -x<br />
export TOTAL_TRANS=1000000<br />
for C in 1 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 150 155 160 165 170 175 180 185 190 195 200<br />
do<br />
rm logs/* -f<br />
pg_ctl -w -l logs/x.log start<br />
TRANS=$[ $TOTAL_TRANS / $C ]<br />
pgbench -s 750 -c $C -t $TRANS -U pgdba -d bench 2> /dev/null > /home/pgdba/bench-$C.std<br />
pg_ctl -m immediate stop<br />
killall -9 postgres<br />
killall -9 postmaster<br />
killall -9 postgres<br />
killall -9 postmaster<br />
rm -rf /mnt/postgres/pgdba/data<br />
cp -a /mnt/postgres/pgdba/data.back /mnt/postgres/pgdba/data<br />
done

proste i miłe 🙂

wyniki wyglądają tak:

7500-db7-opti.png

jest lepiej niż poprzednio – nie ma takiego spadku wydajności.

co interesujące – są skoki o amplitudzie około 50tps, ale wydaje mi się, że mogą one być spowodowane aktywnością poza-bazodanową (cron).
całość osięgnęła stabilną średnią około 640 tps. dla przypomnienia – przy wielkości bazy 4 razy większej niż ram. całkiem przyjemny wynik.

nowa “zabawka”

jeden z klientów eo, firmy gdzie pracuję, właśnie kupił nowy serwer pod bazy danych. ponieważ maszynkę trzeba przetestować, stwierdziłem, że przy okazji porównam sobie jej wydajność z innym serwerem – nieużywanym już starszym serwerem bazodanowym.

poprzednia maszynka:

  • 2 procesory amd opteron 250, 2.4ghz
  • 4 giga ramu
  • 4 dyski scsi, 15krpm, spięte sprzętowym raidem w dwie macierze raid1 po dwa dyski.
  • postawiona pod centosem z kernelem 2.6.9-22.ELsmp

czyli tak naprawdę bez przesadnych rewelacji.
testowałem przy pomocy takiego skryptu:

#!/bin/bash
export TOTAL_TRANS=1000000
for C in 1 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
do
pg_ctl -w -l logs/x.log start
dropdb bench
createdb bench
pgbench -i -s 750 -U pgdba -d bench
TRANS=$[ $TOTAL_TRANS / $C ]
pgbench -s 750 -c $C -t $TRANS -U pgdba -d bench 2> /dev/null > /home/pgdba/bench-$CC-$C.std
pg_ctl -m immediate stop
killall -9 postgres
killall -9 postmaster
killall -9 postgres
killall -9 postmaster
done

proste i konkretne. baza bench ma około 13 giga (aha. gdybyście chcieli powtórzyć test u siebie – pgbench się wywala na -s 750 (na niższych trochę pewnie też) i trzeba go zapatchować – w pgbench.c znaleźć polecenia tworzenia tabel i zastąpić inty bigintami.

postgresql'a użyłem 8.1.4, postgresql.conf zawierał wartości domyślne, zmieniłem jedynie 2 parametry:

max_connections = 110
shared_buffers = 65536
lc_messages = 'en_US.UTF-8'
lc_monetary = 'en_US.UTF-8'
lc_numeric = 'en_US.UTF-8'
lc_time = 'en_US.UTF-8'

czyli jak widać nic specjalnego – chodziło mi nie o tuning postgresa, tylko o sprawdzenie o ile mi mniej więcej przyspieszy system po zmianie sprzętu.

wyniki starszego serwera:

old.png

rzuca się w oczy stabilność wydajności przy przyroście jednocześnie połączonych klientów.

nowa maszynka:

  • 4 procesory amd opteron 875, 2.2ghz
  • 32 giga ramu
  • 2 dyski sas na system, 14 dysków w zewnętrzen macierzy scsi, 15krpm, spięte w jedną dużą macierz raid10
  • postawiona pod debinanem testing z kernelem 2.6.16-2-amd64-k8-smp

test i konfiguracja postgresa – identyczne.

wyniki:

new.png

tym razem rzuca się w oczy brak stabilności wyników przy większej ilości połączeń.

ale też liczby są sporo wyższe 🙂 ponad 6 krotnie wyższe.

zakładam, że brak stabilności może wynikać z tego, że dla tej maszyny ta baza była mała. tzn. baza mająca 13 giga dla maszyny z 4giga ramu to sporo. ale dla maszyny z 32 giga ramu, to drobiazg.

zrobię jeszcze jeden test (będzie dłuższy, więc wyniki pewnie dopiero w poniedziałek) – dokonfiguruję postgresa do końca, i zrobię test na bazie danych tak ze 110 – 120 giga. postaram się zrobić testy do większej ilości klientów.

może to wyjaśni przyczynę dziwnych wahań wyników.

aha – testy nie są idealne – pgbench ma swoje standardowe problemy. dodatkowo – ta maszyna, co prawda nie jest używana normalnie, ale chodzi na niej cron który np. w nocy włącza “updatedb" to pewnie trochę zaburza wyniki.

jeszcze tylko muszę się dowiedzieć ile te maszynki kosztowały aby móc porównać “bang-for-bucks" 🙂

pozytywne wiadomości dla fanów postgresql’a

możliwe, że kojarzycie firmę enterprisedb. firma ta sprzedaje “paczkowanego" postgresa z dodatkami – replikacją, debuggerem funkcji pl/*, narzędziami upraszczającymi migrację z oracle'a.

co istotne – enterprisedb bardzo aktywnie pomaga rozwijać opensource'owego postgresa – zatrudniając core-developerów, backportując swoje zmiany i ogólnie mocno się angażując.

ostatnio miały miejsce 2 sympatyczne wydarzenia związane z enterprisedb.

po pierwsze – 1 sierpnia poinformowali, że zakończyli drugą rundę zbierania finansów i mają teraz o 20 milionów dolarów więcej. kasa zostanie przeznaczona na merketing i poszerzanie rynków sprzedaży.

mimo, że pewnie wolałbym by wpakowali te 20 milionów w programistów o tyle widzę kolosalny sens tego co robią. jeśli faktycznie uda im się sprzedać więcej licencji, pakietów supportowych itd, to powstanie mocna grupa płacących użytkowników. a mając płacących uzytkowników będzie prościej o ludzi którzy będą mogli implementować nowe fajne rzeczy w postgresie – także tym open source'owym.

po drugie – sun microsystems (ta sama firma która ostatnio zwolniła 5000 ludzi), reklamował sie niedawno, że będzie oferował support do postgresa. teraz (informacja z wczoraj) okazało się, że support świadczyć będzie enterprisedb. po prostu sun podpisał z nimi umowę na świadczenie supportu w imieniu sun'a.

dzięki temu jawi się kilka rzeczy:

  • postgresql zyskuje realną, silną pomoc od suna
  • support świadczony przez suna będzie na wysokim poziomie – i nie dlatego, że sun na szybko kogoś wyszkoli, ale dlatego, że support będą świadczyli ludzie którzy na postgresie “zęby pozjadali"
  • enterprisedb na tym zarobi 🙂

to wszystko powoduje, że z coraz większym optymizmem patrzę na przyszłość swojej ulubionej bazy.

co nowego w postgresie 8.2 – ciąg dalszy

na listach postgresowych pojawiły się wątki tyczące tego, że ludzie (w tym np. ja) nie dostrzegli wszystkich zmian.

faktycznie tak jest – bazowałem na “todo", a okazuje się, że jest sporo fajnych zmian nie uwzględnionych w tym dokumencie.

podrzucam zatem drugą część zmian:

  • wartości wielorekordowe. używane np. przy insertach (insert into table (a,b,c) values (1,2,3), (4,5,6), …; – choć nie wiem czy taka dokładnie składnia będzie) – ale także wszędzie gdzie jest dopuszczalny (sub-)select.
  • pg_dump będzie obsługiwał wielokrotne -n oraz -t, oraz umożliwiał wybieranie obiektów do zdumpowania przy pomocy regexpa. dla mnie osobiście jest to wielki bonus, bo umożliwi mi wreszcie normalne dumpowanie baz replikowanych slony'ym.
  • agregaty wieloargumentowe – w tym agregaty statystyczne uwzględnione w standardzie sql2003
  • porównywanie zmiennych “rekordowych". np. możliwośc zrobienia w triggerze: if row(new.*) is distinct from row(old.*)
  • DROP … IF EXISTS
  • poprawki w tsearch2 – wydajność, ale także funkcjonalność – tezaurus!
  • nowy typ indeksów – gin. służy do indeksowania list odwrotnych – w szczególności powstał na potrzeby tsearch'a, ale można go używać niezależnie
  • GRANT CONNECT ON DATABASE – dla wielu ludzi będzie to zbawienie, bo przestaną się martiwć, że ktoś obcy zobaczy nazwy ich tabelek 🙂
  • funkcje w pl/pythonie obsługuja nazwane argumenty oraz mogą zwracać dane rekordowe.
  • stats_command_string – pokazywanie aktualnie wykonywanego zapytania przez backend – do wersji 8.1.x wiązała się z pewnym (czasem dosyć sporym) obciążeniem serwera. w 8.2 overhead tego został praktycznie wyeliminowany i funkcja te jest włączona domyślnie 🙂

dodatkowo, w kolejce są jeszcze pewne patche, które nie zostały jeszcze zaakceptowane, ale ponieważ zostały zgłoszone przed ogłoszeniem feature-freez'a to mają szanse na włączenie do 8.2. są to między innymi:

  • budowanie indeksów w locie, bez lockowania indeksowanej tablicy!
  • update'owalne widoki. tzn. funkcjonalność do tego była od dawna, ale teraz ma to działać automatycznie. przynajmniej w relatywnie prostych sytuacjach.
  • funkcjonalność INSERT/UPDATE RETURNING. czyli np. wydanie polecenia insert, tak aby został od razy zwrócony id nowo dodanego rekordu.

plus jeszcze jedna rzecz o której nie napisałem poprzednio (nie wiem czemu, wiedziałem, ale jakoś mi umknęło). w wersji 8.2 jest dużo poprawek tyczących się wydajności. naprawdę dużo. są ludzie którzy już teraz przesiadają się na 8.2 bo system “lata" zamiast “chodzić" czy “pełzać".

interesujący pomysł: typ danych z jednostkami

martijn van oosterhout zaimplementował interesujące rozszerzenie postgresa.

są to mianowicie typy danych z przechowywanymi w danych (i obsługiwanymi) jednostkami.

przykładem użycia może być typ danych do przechowywania kwot, wraz z walutą.

innym – wartości fizyczne wraz z jednostkami – np. ‘9.81 mps2′.

fajne w tym jest to, że te dane działają logicznie. to znaczy. mając typ finansowy, i wykonując dodawanie:

select '15 USD'::currency + ‘25.1 USD'::currency;

da oczekiwany, poprawny wynik. jednocześnie system jest na tyle sprytny, że przy próbie dodawania wartości z różnymi jednostkach zgłasza błąd.

oczywiście użyteczność tego sięga poza dodawanie 🙂

ogólnie – dzięki taggedtypes można sobie zdefiniować dowolne typy danych z dowolnymi tagami.

niestety – na chwilę obecną w systemie jest kilka ograniczeń. ale – dzięki temu, że całośc jest dostępna ze żródłami można sobie prosto dopisać dowolne dodatkowe funkcje. np. do typu walutowego przydatne byłoby automatyczne przeliczanie po aktualnym kursie by móc uzyskać np. coś takiego:

SELECT ‘1 PLN'::currency + ‘1 USD'::currency;

zwracające zsumowane kwoty “po kursie dnia".

albo po prostu tworzące wartość ‘1 PLN 1 USD' która nadal będzie prawidłowo działać 🙂

możliwości jest sporo. podwaliny już są. czy coś dalej z tego wyjdzie – to już zależy od użytkowników i zastosowań jakie sobie wymyślą 🙂

http://svana.org/kleptog/pgsql/taggedtypes.html

pervasive już nie supportuje postgresa

półtora roku temu (początek stycznia 2005) firma pervasive (znana jako producent komercyjnej bazy danych do zastosowań małych i średnich) ogłosiła, że będzie:

  • oferować komercyjne wsparcie do postgresa
  • oferować gotowy, “zabundlowany" pakiet – postgres (z ich łatkami) plus wsparcie
  • pomagać developerom w rozwijaniu kodu

tydzień temu, w otwartym liście do “postgresql community", prezes pervasiva stwierdził, że rezygnują z tego “projektu".

nie postgresa tylko wsparcia i całej otoczki.

podobno przyczynami jest to, że nie docenili ilości i jakości wsparcia jakie użytkownicy mają już teraz dostępne na internecie (listy mailingowe, kanały irc). jak dla mnie oznacza to to, że mieli za mało klientów na te usługi. może nawet wcale nie mieli?

john farr (prezes pervasiva) stwierdził, że oczywiście będą supportować aktualnych klientów, ale nowych umów zawierać już nie będą.

do tej informacji mam mieszane uczucia. z jednej strony – szkoda trochę, pervasive jest trochę znany więc udany mariaż dałby większe publicity postgresowi, z drugiej strony – nie kojarzę co takiego cudownego ludzie z pervasive'a zrobili dla postgresa. w/g farra dali kod do dtrace'a, ale on będzie użyteczny (o ile wiem) jedynie pod solarisem. a to nie jest zbyt popularny system.

z trzeciej strony – wolę by rozwijały się i zyskiwały klientów firmy stricte postgresowe – command prompt, sra, greenplum.

więc chyba ogólnie jestem raczej zadowolony z takiego obrotu zdarzeń.