Welcome to Sign in | Help
in Search

Solutia optima pentru aplicatie distribuita.

Last post 10-29-2008, 2:24 PM by fgbogdan. 24 replies.
Page 2 of 2 (25 items)   < Previous 1 2
Sort Posts: Previous Next
  •  10-06-2008, 1:46 PM 5738 in reply to 5736

    Re: Solutia optima pentru aplicatie distribuita.

    5-95 ... mda ... in momentul in care se mareste numarul de servere raportul se va modifica prin mecanismul pe care il propun.

    Stiu ca este complicat (altfel ... fara suparare) era un simplu addon la sql server si nu ne mai bateam niciunul capul.
    Sunt convins ca nu o sa pot sa ajung la o solutie in care sa pot pune oricate servere ... dar daca ajung sa fac o implementare cu 3 in inel ... m-am scos.

    Cand o sa mai am timp de "experimentari" o sa definitivez si partea de offline si o sa va prezint solutia completa.


    conditia aia de while ... mi-a furat-o clipboardul ... care nu vrea sa scrie (mai mic)(egal)(coada de maimuta)LastColumnID
    www.fagadar.ro
  •  10-06-2008, 3:13 PM 5747 in reply to 5738

    Re: Solutia optima pentru aplicatie distribuita.

    Nu cred ca am inteles care sint avantajele sa pui serverele in inel. Potzi sa le explici?

    http://rusanu.com
  •  10-06-2008, 4:44 PM 5752 in reply to 5747

    Re: Solutia optima pentru aplicatie distribuita.

    pai ... decat sa se sincronizeze fiecare cu fiecare, asa o sa fie o directie de sincronizare. Ceea ce ziceam si la inceputul postului. Din punct de vedere al numarului de operatii e acelasi lucru in online dar in offline se complica treaba.
    www.fagadar.ro
  •  10-06-2008, 5:53 PM 5753 in reply to 5752

    Re: Solutia optima pentru aplicatie distribuita.

    Dar in felul asta introduci artificial puncte de failure. Daca in 'mesh' un nod e cazut, el numai primeste updaturile pina nu revine online. In cerc, daca un nod e cazut blocheaza pe toata lumea eventual (toate updaturile se opresc la el).

    Ca sa intzeleg mai bine, ceea ce propui tu este asa: S1 primeste un update. In trigger el se conecteaza la un linked server S2, promoveaza tranzactia locala in DTC, apoi updateaza remote S2. Batch-ul din S1 este blocat asteptind rezultatul de la linked server. S2 face update, apoi ruleaza trigger-ul sau. In trigger se conecteaza la linked server S3, adauga si pe S3 la DTC-ul care-l are cu S1 face update-ul pe S3. Batchul de pe S1 este acum blocat asteptind batch-ul de pe S2 care este acuma blocat asteptind batch-ul de pe S3. Si asa mai departe. Sn in trigger-ul detecteaza ca update-ul vine de la S1 si numai apeleaza S1 . Asta pentru, dupa cum sper ca stii, daca Sn se conecteaza la S1 va incerca sa enroleze o noua sesiune in tranzactia existenta, rezultind in eroarea 3910 "Transaction context in use by another session".
    Deci toate serverele, de la S1 la Sn sin acuma enrolate intr-o tranzactie distribuita coordonata de MSDTC de pe S1 (care a inceput-o). Fiecare server este blocat asteptind-ul pe urmatorul sa termine batch-ul. Sn ruleaza trigger-ul de update (fara sa se conecteze la S1, am explicat de ce), apoi Sn-1 poate continua si tot asa pina controlul se intoarce la S1. Acuma S1 poate termina trigger-ul, statement-ul care a facut update-ul in sfirsit poate sa se termine, si eventula tranzactia sa comita. S1 cere DTC-ului sa  comita, DTC-ul face magia in doi pasi si toate serverele comit.



    http://rusanu.com
  •  10-06-2008, 6:37 PM 5754 in reply to 5753

    Re: Solutia optima pentru aplicatie distribuita.

    toate sunt after (update, insert, delete) ... ca sa nu fie blocaje. Daca reuseste sa faca update pe serverul urmator bine - daca nu logheaza si o sa faca cand o sa fie online (cu un job probabil). NU asteapta unii dupa altii ca atunci ajung la blocaje.
    www.fagadar.ro
  •  10-06-2008, 6:44 PM 5755 in reply to 5754

    Re: Solutia optima pentru aplicatie distribuita.

    fgbogdan:
    toate sunt after (update, insert, delete) ... ca sa nu fie blocaje. Daca reuseste sa faca update pe serverul urmator bine - daca nu logheaza si o sa faca cand o sa fie online (cu un job probabil). NU asteapta unii dupa altii ca atunci ajung la blocaje.


    Am priceput, deci S1 face un update, triggerul lui S1 updateaze pe S2 dar face disable la trigger-ul de pe S2 innainte de update asa incit trigger-ul lui S2 nu se activeaza. Acuma update-ul a ajuns la S2. Cum ajunge update-ul lui S1 la S3?

    Ignoram pentru moment faptul ca ALTER TABLE cere un lock Sch-M pe tabela, blocind toate operatziile care cer Sch-S (cum ar fi SELECT).

    http://rusanu.com
  •  10-06-2008, 8:40 PM 5756 in reply to 5755

    Re: Solutia optima pentru aplicatie distribuita.

    nuuuu, nu face disable, ca altfel nu poate sa mearga mai departe. Trebuie sa il lase sa "fire"-uie, Exemplul trimis de mine ste numai pentru 2 servere. Pentru varianta de "inel" trebuie sa gasesc o metoda de oprire - pe care inca nu o stiu. Eventual sa determin care e serverul pe care trebuie sa se opreasca triggerul meu (adica daca plec de pe S(N) ... triggerul sa numai "fire"-uie pe S(N-1).
    www.fagadar.ro
  •  10-06-2008, 9:14 PM 5757 in reply to 5756

    Re: Solutia optima pentru aplicatie distribuita.

    Hai sa mai facem un pic de matematica.

    Sa consideram ca un update se executa intr-un timp T, sa zicem intr-o suta de milisecunde. Cind faci un update pe S1, batch-ul executa update apoi asteapta executia trigger-ului. Pe S2 se executa din nou in T, apoi S2 asteapta se se execute pe S3 s.a.m.d. Pe Sn dureaza 100 ms apoi se intoarce. Deci Sn a asteptat 100ms, Sn-1 200ms, pe Sn-2 300 ms s.a.m.d. Timpul total de consumat in sistem de executarea update-ului este suma acestor timpuri, deci N(N+1)/2 * T. A nu se confunda cu durata de executie al update-ului, care este evident T*N.

    In SQL Server exista o resursa foarte bine definita, anume numarul de 'worker threads'. Fiecare worker thread poate executa la un moment dat un singur batch (=request). Un worker nu poate abandona un batch pina ce nu il termina. Un bath care asteapta un raspuns de la un linked server este blocat, nu terminat, si consuma un worker. Numarul de worker threads este limitat. Hai sa consideram numarul implicit, 256 de worker threads. Cu acest numar putem determina limita absoluta, ideala, care ne spune cite write-uri putem face in sistem.
    Cu 3 noduri ai la dispozitie 3*256 workere, care pot executa 7680 de taskuri de cite 100 ms fiecare. Un update in topologia 'inel' consuma 6 astfel de quate de cite 100 ms (1 pe S3, 2 pe S2 si 3 pe S1). Deci in conditzii ideale potzi sa obtzii 7680/6 = 1280 update-uri in sistem intr-o secunda. Cu 5 noduri, ai la dispozitzie 12800 de 'quante' si fiecare update consuma 15, deci potzi spera la 853 de scrieri pe secunda. Cu 20 de noduri ai nevoie de 210 'quante' pentru un update, rezultind un throughput de ~244 operatii pe secunda.

    Hai sa consideram topologia mesh, fiecare se conecteaza la fiecare. Un update in aceasta topologie consuma T pe S1, apoi S1 updateaza S2 (=T), apoi updateaza S3 (=T) s.am.d. Timpul total consumat pe toate nodurile este 2N-1 (S1 consuma T*N pentru ca sta sa updateze S2...SN si la asta se adauga N-1 pentru fiecare timp T consumat de S2...S3). Pe 3 noduri un update consuma 5 'quante' (3 pe S1, 1 pe S2, 1 pe S3). Deci potzi scrie 7680/5=1536 operatii, o imbunatarire cu 120% fata de topologia 'inel'.  Cu 5 noduri ai nevoie de 9 'quante' si obtii 1422 operatii pe secunda, cu 166% mai bine decit in inel. Cu 20 de noduri ai nevoie de 39 de 'quante' si potzi obtzine un throughput 1313 operatii, care este cu doar 538% mai bine decit in topologia 'inel'.

    Se vede de fapt ca numarul de 'worker' threads ales si durata unui update (T) sint irelevante, diferenta vine din formula de timp linear pentru mesh (2N-1) fata de timp patratic ( N(N+1)/2 ) pentru 'inel'. Asta in ciuda faptului ca timpul de 'raspuns' al fiecarui update este identic in ambele topologii (T*N). Dar intr-una din topologii (mesh) exista un singur nod care astepta pe celelate, in timp ce in 'inel' toate nodurile astepta nodurile 'de la dreapta', cu exceptia ultimului.

    Asa ca revin la intrebarea originala: care exact sint avantajele toplogiei in inel?


    http://rusanu.com
  •  10-07-2008, 8:37 AM 5761 in reply to 5757

    Re: Solutia optima pentru aplicatie distribuita.

    intradevar - pus pe hartie e mai avantajos cu mesh - insa ma gandeam ca conditia de oprire ar fi mai simplu de implementat la inel. (folosind eventual o coloana in tabela in care sa fie id-ul sau numele serverului care face update-ul original).
    Ca si la retele ... topologia in inel nu e mai avantajoasa - ci poate doar mai simpla pentru intelegerea umana. Vreau sa incerc inainte - si apoi o sa vad practic care imi este mai buna.
    www.fagadar.ro
  •  10-29-2008, 2:24 PM 5972 in reply to 5761

    Varianta revizuita - cu stop (un fel de ...)

    CREATE TRIGGER [TRIGGER_NAME] ON [dbo].[TBL_NAME]
    FOR INSERT, UPDATE, DELETE
    AS

    DECLARE @strAction AS VARCHAR(10)
    DECLARE @STRTABLENAME AS VARCHAR (100)
    DECLARE @STRCMD AS NVARCHAR (1000), @STRCMD1 AS NVARCHAR (1000)
    DECLARE @Column_Name AS VARCHAR (50), @Type_Name AS VARCHAR (50)
    DECLARE @DeletedRows AS INT
    DECLARE @InsertedRows AS INT
    DECLARE @nIndex AS INT
    DECLARE @bContinue AS bit
    SET @bContinue = 0

    SELECT * INTO #inserted FROM inserted
    SET @InsertedRows = @@rowcount


    SELECT * INTO #deleted FROM deleted
    SET @DeletedRows = @@rowcount

    IF @InsertedRows > 0
    BEGIN
    IF @DeletedRows > 0
    SET @strAction = 'UPDATE'
    ELSE
    SET @strAction = 'INSERT'
    END
    ELSE
    BEGIN
    SET @strAction = 'DELETE'
    END

    -- DELETE
    IF 'DELETE' = @strAction
    BEGIN
    -- daca nu a mai fost apelat
    IF ( (SELECT trigger_nestlevel(object_ID('TRIGGER_NAME')) )
    BEGIN
    SET @STRCMD = ' delete from SRVREPL_NAME.DBREPL_NAME.dbo.TBL_NAME where ID_NAME in (select ID_NAME from #deleted)'
    EXECUTE(@STRCMD)
    END
    END

    -- daca este insert sau update ... determin daca sa merg mai departe ...
    -- si prelucrez
    IF 'INSERT' = @strAction OR 'UPDATE' = @strAction
    BEGIN

    -- daca este insert sau update - determin care este valoarea lui SINCFIELD
    DECLARE @SERVERNAME AS VARCHAR(20)
    SELECT @SERVERNAME = SINCFIELD FROM #inserted

    -- daca serverul din campul SINCFIELD este SRVREPL_NAME nu fac nimic
    -- daca este NULL inseamna ca este prima data
    -- daca e alt server ... merg mai departe
    IF '['+@SERVERNAME+']' <> 'SRVREPL_NAME' OR @SERVERNAME IS NULL
    BEGIN

    -- setez ca o sa fac insert sau update
    SET @bContinue = 1
    -- daca este null ... il initializez cu numele serverului meu
    IF @SERVERNAME IS NULL
    BEGIN
    UPDATE #inserted SET SINCFIELD = @@servername
    END
    END
    -- daca SINCFIELD nu e NULL
    IF NOT @SERVERNAME IS NULL
    BEGIN
    -- setez in tabela locala campul SINCFIELD pe null
    UPDATE TBL_NAME SET SINCFIELD = NULL FROM TBL_NAME, #inserted WHERE TBL_NAME.ID_NAME = #inserted.ID_NAME
    END

    END


    -- INSERT
    IF 'INSERT' = @strAction AND @bContinue = 1
    BEGIN
    -- inserez
    SET @STRCMD = ' INSERT INTO SRVREPL_NAME.DBREPL_NAME.dbo.TBL_NAME select FIELDS_LIST from #inserted '
    EXECUTE(@STRCMD)
    END

    -- UPDATE
    IF 'UPDATE' = @strAction AND @bContinue = 1
    BEGIN

    DECLARE @ColumnID int, @Columns nvarchar(4000), @ObjectID int, @LastColumnID int

    SET @ObjectID=(SELECT id FROM sysobjects WHERE name='TBL_NAME')
    SET @LastColumnID=(SELECT MAX(colid) FROM syscolumns WHERE id=@ObjectID)
    SET @ColumnID=1
    WHILE @ColumnID
    IF (SUBSTRING(COLUMNS_UPDATED(),(@ColumnID - 1) / 8 + 1, 1)) &
    POWER(2, (@ColumnID - 1) % 8) = POWER(2, (@ColumnID - 1) % 8)
    SET @Columns = ISNULL(@Columns+',','') + COL_NAME(@ObjectID,@ColumnID) + ' = #inserted.' + COL_NAME(@ObjectID,@ColumnID) + ' '
    SET @ColumnID=@ColumnID+1
    END

    -- trebuie sa trimit mai departe si SINCFIELD
    SET @Columns = @Columns + ', SINCFIELD=#inserted.SINCFIELD '
    -- trebuie sa inlocuiesc IN tabela tinta ... coloana @Column_Name
    SET @STRCMD = 'UPDATE SRVREPL_NAME.DBREPL_NAME.dbo.TBL_NAME SET ' + @Columns + ' FROM SRVREPL_NAME.DBREPL_NAME.dbo.TBL_NAME C, #inserted WHERE C.ID_NAME = #inserted.ID_NAME'
    EXECUTE(@STRCMD)


    END

    -- curatenie
    DROP TABLE #inserted
    DROP TABLE #DELETED




    conditii ... fiecare tabela trebuie sa aiba campul SINCFIELD care sa accepte NULL si sa nu fie modificat din aplicatie.


    ideea e ca la primul apel ea vine null si apoi trece la urmatoarele servere cu numele serverului care a initiat actiunea.

    oricum pana la varianta finala care sa contina si offline mai e muuuuuuuuuuuuult ...
    www.fagadar.ro
Page 2 of 2 (25 items)   < Previous 1 2
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems