Mondi su mondi, sistemi di sistemi.

Skype, le mode e la reinvenzione della ruota

Thursday, August 19th, 2010

Non è un mistero che mi piac­ciano le solu­zioni inu­suali, l’ho scritto in pas­sato: a pro­po­sito dell’intervista ad Avy Briant1, lo ripeto ora dopo aver visto que­sta pre­sen­ta­zione dell’architetto soft­ware di Skype2, sem­pre su InfoQ.

Avevo già letto l’articolo3 ma, anche se è stata una delle cose più inte­res­santi degli ultimi mesi, non mi era pro­prio venuta in mente l’intervista, né tan­to­meno que­sto mio post di due anni fa in cui avevo segna­lato que­sta descri­zione sull’architettura di Skype, che è basata su PostgreSQL.4.

Qual è il nesso?

D’accordo, ammesso che in comune ci sia la capa­cità di tro­vare solu­zioni senza affi­darsi a pre­con­cetti, in un modo che potremmo defi­nire con­text dri­ven5, cos’ha di così par­ti­co­lare l’architettura di Skype? Per capirlo, dob­biamo fare mente locale sul con­te­sto attuale.

L’ascesa del NoSQL

In que­sto periodo, diciamo negli ultimi due anni, si è fatta strada l’idea secondo cui non puoi sca­lare vera­mente un’architettura se ti affidi ai data­base SQL, soprat­tutto se par­liamo di sca­la­bi­lità oriz­zon­tale6. Questo è uno degli assunti, forse il prin­ci­pale, che ha por­tato alla ribalta il cosi­detto movi­mento NoSQL7.

Non c’è dub­bio che ci pos­sano essere pro­blemi a sca­lare i data­base “tra­di­zio­nali”, né che siano adatti a qual­siasi uso e nem­meno che ci sia ancora molto da fare per ren­derli più adatti al modo di lavo­rare attuale8 9.

Naturalmente i data­base SQL sono ancora usa­tis­simi ma non mi aspet­tavo di vedere la pre­sen­ta­zione di uno che lavora esclu­si­va­mente con le sto­red pro­ce­du­res10. Ecco per­ché un’architettura come quella di Skype sem­bra così par­ti­co­lare rispetto a quello che oggi fa ten­denza ed ecco per­ché è così impor­tante tenerla presente.

Reinventare la ruota, ogni volta

Siamo sem­pre attratti dall’adottare quello che ha fun­zio­nato l’ultima volta o quello che sem­bra fun­zio­nare per tutti gli altri. A volte è la cosa giu­sta da fare, a volte no, ognuno sba­glia a modo proprio.

Forse è uno scherzo della memo­ria ma credo di ricor­dare che in un’intervista gli svi­lup­pa­tori della Bungie (quelli di Halo, poi com­prata da Microsoft) dice­vano che uno degli obiet­tivi che si pone­vano era pro­prio quello di rein­ven­tare la ruota, per fare piazza pulita delle cose supe­rate. Sembra che abbia fun­zio­nato! 11

  1. Outside the box.
  2. Learning from Five Years as a Skype Architect Andres Kutt discus­ses his expe­rience as archi­tect at Skype for five years, sha­ring some of the les­sons lear­ned: rules of thumb do not always apply, func­tio­na­lity is impor­tant, use sim­ple solu­tions, buz­z­words are dan­ge­rous, the archi­tec­ture needs to fit into the orga­ni­za­tion, and com­mu­ni­ca­tion is impor­tant.
  3. Learnings from Five Years as a Skype Architect: Too often in our work as archi­tects and desi­gners we focus on the task at hand, sel­dom reflec­ting on the past. We should really know bet­ter, how else do you improve? This arti­cle sum­ma­ri­zes six lear­nings from 55 mon­ths as an archi­tec­ture team lead at Skype.
  4. PostgreSQL: ana­lisi dell’architettura di Skype
  5. Context dri­ven testing. Non fatevi ingan­nare dal fatto che si parla di testing, sono con­si­de­ra­zioni di vali­dità gene­rale.
  6. Da Wikipedia: To scale hori­zon­tally (or scale out) means to add more nodes to a system, such as adding a new com­pu­ter to a distri­bu­ted soft­ware appli­ca­tion. An exam­ple might be sca­ling out from one web ser­ver system to three.
  7. Da Wikipedia: In com­pu­ting, NoSQL is a term used to desi­gnate data­ba­ses which dif­fer from clas­sic rela­tio­nal data­ba­ses in some way. These data sto­res may not require fixed table sche­mas, and usually avoid join ope­ra­tions and typi­cally scale hori­zon­tally. Academics and papers typi­cally refer to these data­ba­ses as struc­tu­red sto­rage, a term which would include clas­sic rela­tio­nal data­ba­ses as a sub­set.
    Notable pro­duc­tion imple­men­ta­tions include Google’s BigTable and Amazon’s Dynamo.
  8. I refac­to­ring che coin­vol­gono il data­base riman­gono ancora troppo mac­chi­nosi. In parte è un pro­blema di stru­menti, in parte è un pro­blema di metodo di lavoro per­ché, forse più che in altri con­te­sti, le ope­ra­zioni da fare sul data­base sono molto spe­ci­fi­che.
  9. Bisogna anche far notare che sotto l’ombrello della defi­ni­zione NoSQL ci sono realtà molto diverse, alcune sono pen­sate per la sca­la­bi­lità (Cassandra, ad esem­pio), altre per modelli di dati che non sono facil­mente ridu­ci­bili all’SQL come i graph data­base.
  10. Anche se, a onor del vero, la pre­sen­ta­zione non riguarda PostgreSQL ma quello che que­sta per­sona ha impa­rato lavo­rando per cin­que anni a Skype
  11. La ten­sione fra riscrit­tura da zero e refac­to­ring è uno dei temi che ricor­rono in que­sto blog, non c’è niente da fare… Dovrò fare una rac­colta dei vari post, un giorno o l’altro.

PostgreSQL 9: le novità

Monday, May 17th, 2010

Sta per arri­vare la nuova ver­sione di PostgreSQL, la 9 1. Come in pas­sato, anche se più sin­te­ti­ca­mente, fac­cio una car­rel­lata delle prin­ci­pali novità.

Binary repli­ca­tion

La novità più impor­tante è l’aggiunta di una solu­zione di replica uti­liz­za­bile da subito, senza com­po­nenti aggiun­tive. La ver­sione “di sistema” offre la pos­si­bi­lità di repli­care attra­verso l’invio del WAL 2 ai nodi secon­dari, che pos­sono essere con­fi­gu­rati in moda­lità Hot 3 o Warm 4 Standby.

Nel caso del Warm Standby il nodo prin­ci­pale spe­di­sce ai secon­dari un intero seg­mento di WAL alla volta, men­tre nel caso dell’Hot Standby la gra­nu­la­rità dell’invio scende al livello del record, ridu­cendo ulte­rior­mente la fine­stra di scopertura.

Funzioni, pro­gram­ma­zione

È stato aggiunto il sup­porto per le fun­zioni ano­nime. Non c’è molto da aggiun­gere in que­sto caso, per­ché l’uso è vera­mente sem­plice5.

È pos­si­bile usare i nomi dei para­me­tri delle fun­zioni anche nell’invocazione, ren­dendo più chiaro il codice nel caso in cui ce ne siano molti 6.

Dettaglio carino e utile: adesso è pos­si­bile set­tare la varia­bile application_name.

SQL

Ora pos­siamo restrin­gere l’esecuzione dei trig­ger a una sin­gola colonna. 7. Inoltre, pos­siamo spe­ci­fi­care la clau­sola when per restrin­gere la loro atti­va­zione solo nei casi real­mente neces­sari 8.

Adesso è pos­si­bile creare dei con­straint che vadano al di là della sem­plice veri­fica di uni­cità, spe­ci­fi­cando l’operatore usato per il pre­di­cato di con­fronto fra due valori. L’esempio ripor­tato nella docu­men­ta­zione è quello che spe­ci­fica il divieto di avere due cir­con­fe­renze che si inter­se­cano 9. Sempre a pro­po­sito dei vin­coli di uni­cità, adesso pos­sono essere spe­ci­fi­cati come deferrable.

  1. Note di rila­scio
  2. Il Write Ahead Log
  3. Per Hot Standby si intende invece la pos­si­bi­lità di con­net­tersi a un nodo in moda­lità di ripri­stino e sot­to­met­tere delle query di sola let­tura, per poi pas­sare suc­ces­si­va­mente alla moda­lità nor­male in modo tra­spa­rente rispetto agli utenti con­nessi.
  4. Il Warm Standby, o log ship­ping, è defi­nito come la capa­cità di rag­giun­gere l’alta dispo­ni­bi­lità attra­verso l’uso di uno o più nodi in standby, pronti ad entrare in azione nel caso in cui il nodo pri­ma­rio sia disat­tivo.
  5. Do sta­te­ment
  6. Named para­me­ters
  7. per-column trig­gers. Questa pos­si­bi­lità è limita ai trig­ger in UPDATE.
  8. Conditional Triggers
  9. Exclusion Constraints

PostgreSQL: cursori e query dinamiche

Wednesday, February 4th, 2009

Con PostgreSQL, vista l’abbondanza di lin­guaggi che pos­sono essere usati per creare le fun­zioni, è spesso molto con­ve­niente spo­stare molta di quella logica che soli­ta­mente gira nell’application ser­ver diret­ta­mente nel database.

Tuttavia, uno dei limiti nell’usare le pro­ce­dure in PostgreSQL è che i vin­coli sui data­type resti­tuiti dalle fun­zioni sono piut­to­sto rigidi. In pra­tica, il sistema deve sapere al momento della com­pi­la­zione tutti i tipi di valori restituiti. Perciò, o dichia­riamo i para­me­tri OUT e nella clau­sola di return usiamo record, oppure, sem­pre nella clau­sola di return usiamo una tabella/view/tipo com­po­sito già pre­sente nel cata­logo. #

Di solito pre­fe­ri­sco la secondo solu­zione per­ché in que­sto modo si crea una dipen­denza espli­cita fra la fun­zione e la tabella/view/tipo com­po­sito restituito.

Questo però vuol dire che non pos­siamo scri­vere una fun­zione gene­rica che possa essere usata su più tabelle. Tuttavia, con i cur­sori pos­siamo otte­nere pra­ti­ca­mente la stessa cosa.

Ad es, basta una fun­zione come questa:

CREATE OR REPLACE FUNCTION get(IN table_name text) RETURNS refcursor AS $$
BEGIN
    OPEN c FOR EXECUTE 'SELECT * FROM ' || quote_ident($1);
    RETURN c;
END;
$$ language plpgsql;

 

per poi:

BEGIN;
SELECT get('table');
FETCH ALL FROM result;
COMMIT;

 

L’unico svan­tag­gio è il dover aprire sem­pre una tran­sa­zione ma mi sem­bra un prezzo ragionevole.

PostgreSQL: generare delle sequence senza salti

Sunday, August 3rd, 2008

Le sequence sono un sup­porto, for­nito dalla stra­grande mag­gio­ranza dei data­base, per gene­rare dei valori nume­rici uni­voci, che pos­sono poi essere usati per iden­ti­fi­care ogni sin­gola riga di una tabella. In PostgreSQL, la sequence risulta in pra­tica essere un numero intero sem­pre cre­scente e che non viene più riu­ti­liz­zato: se il numero n, che otte­niamo dal sistema, viene uti­liz­zato in una tran­sa­zione che poi sarà abor­tita, il pros­simo numero sarà comun­que almeno n+1.

Ci sono, però, situa­zioni in cui non è suf­fi­ciente che la nume­ra­zione sia sem­pre cre­scente ma che non pre­senti “buchi”; e que­sto non è pos­si­bile “right out of the box” con PostgreSQL.

Che fare?

In que­sto arti­colo, la solu­zione pro­po­sta con­si­ste nel creare una tabella di appog­gio, che una fun­zione si occu­perà di aggior­nare; que­sta fun­zione sarà quella usata come default per la tabella vera e pro­pria che, come è lecito aspet­tarsi, non con­sen­tirà cancellazioni.

I det­ta­gli sono nell’articolo e dovreb­bero essere piut­to­sto chiari; in casi di dubbi i com­menti sono a disposizione.

PostgreSQL: generare una sequence “al volo”

Monday, July 14th, 2008

A volte cápita di dover nume­rare i record durante la crea­zione di report. Una solu­zione abba­stanza nota è quella di tenere a dispo­si­zione una tabella (even­tual­mente tem­po­ra­nea) che non con­tiene altro che una sequenza di numeri a 1 a n.

Con PostgreSQL esi­ste una solu­zione più ele­gante: generate_series. Con que­sta fun­zione pos­siamo scri­vere una query come questa:

 

SELECT pdays.doy, SUM(o.order_total) As sales_total
FROM (SELECT CAST('2007-01-01' As date) + n As doy
		FROM generate_series(0,364) n ) pdays
			INNER JOIN orders o ON o.sale_date = pdays.doy;
GROUP BY pdays.doy
ORDER BY pdays.doy

 

dove pdays è la sequenza di tutti i giorni a par­tire a par­tire dal primo Gennaio 2007.

PostgreSQL: analisi dell’architettura di Skype

Monday, April 7th, 2008

Per gli afi­cio­na­dos di PostgreSQL c’è un arti­colo da non per­dere su High Scalability che ana­lizza l’archi­tet­tura adot­tata da Skype, basata appunto su pgSQL, che è data per sca­la­bile fino ad 1 miliardo di utenti.

Ci sono diversi aspetti rile­vanti, fra cui il fatto che l’accesso al data­base è com­ple­ta­mente incap­su­lato attra­verso le sto­red pro­ce­du­res. Nel mio pic­colo è un approc­cio che sto pro­vando anch’io con un pro­getto che ini­ziato qual­che mese fa e su cui posterò qual­che info più appro­fon­dita quando sarà andato tutto in porto (si spera!).

L’idea che mi attira di que­sto approc­cio è che l’interfaccia con il data­bae risulta dra­sti­ca­mente sem­pli­fi­cata: ci sono solo i para­me­tri d’ingresso e d’uscita. Senza con­tare i risparmi in ter­mini di prestazioni.

Ad oggi, il difetto fon­da­men­tale di que­sta solu­zione è che non può essere estesa anche alle select, dato che il plan­ner di PostgreSQL non è in grado di ana­liz­zare la query in modo otti­male per poter usare la stra­te­gia più per­for­mante ma qual­che miglio­ria è in arrivo con la ver­sione 8.4.

E pen­sare che una volta ero con­vinto che le sto­red pro­ce­du­res fos­sero l’incarnazione del male… :-D

Come verificare che l’autovacuum funzioni

Wednesday, February 14th, 2007

Le ultime ver­sioni di PostgreSQL pre­ve­dono la pos­si­bi­lità di effet­tuare auto­ma­ti­ca­mente il “vacuu­ming” delle tabelle. Questa ope­ra­zione serve per recla­mare lo spa­zio su disco non più uti­liz­zato, aggior­nare le sta­ti­sti­che e pre­ve­nire che gli ID delle tran­sa­zioni ripar­tano dall’inizio (quello che viene chia­mato tran­sac­tion ID wraparound).

Per veri­fi­care, da una ses­sione con psql, la situa­zione delle ope­ra­zioni di vacuum, si può usare un’interrogazione del tipo:

SELECT schemaname, relname, last_autovacuum, last_autoanalyze FROM pg_stat_all_tables;

Le righe vuote sono rela­tive alle tabelle poco uti­liz­zate e che quindi non hanno biso­gno di que­sto tipo manutenzione.

Invece, per veri­fi­care le impo­sta­zioni:

SELECT name, setting FROM pg_settings WHERE name LIKE '%autovacuum%';

Il risul­tato dovrebbe essere una cosa del tipo:

name | setting
---------------------------------+-----------
autovacuum | on
autovacuum_analyze_scale_factor | 0.1
autovacuum_analyze_threshold | 250
autovacuum_freeze_max_age | 200000000
autovacuum_naptime | 60
autovacuum_vacuum_cost_delay | -1
autovacuum_vacuum_cost_limit | -1
autovacuum_vacuum_scale_factor | 0.2
autovacuum_vacuum_threshold | 500