![]() |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Gerade viel mir ein, dass ich vor ca. 20 Jahren ein ähnliches Problem hatte.
Meine damalige Lösung: Sobald ein Datensatz gespeichert wird, wird die gesamte Liste aktualisiert und bearbeitete Datensätze hatten eine Markierung. Die Anwender konnten über einen Schalter auch die erledigten Datensätze ausblenden. Natürlich war der zuletzt bearbeitete Datensatz immer noch selektiert, damit man nicht wieder alles durchblättern musste. Der wesentliche Vorteil war, dass nach dem Refresh auf jeden Fall der aktuellste Stand verfügbar war und ein ständige Aktualisierung entfallen konnte. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Das ist ein "Pick from the Rest" Verfahren.
Gibt es bei Maschinenzuordnungen, wo sich n Maschinen aus einem Stückpool sich was zur Bearbeitung picken und die Restmenge angezeigt wird. Wie wäre es damit: Neue Transaktionstabelle erstellen. Inhalt: REC ID In Process by User Start Date/Time (zur Deadlock Erkennung) HeaderEintrag, z.B. mit RecID -1 für den letzten Änderungseintrag. Das kann man mit wenig Zeitaufwend sekündlich abfragen (select ProcessingUser from Picklist where TargetID = -1). Ändert sich der Wert, kann man die Liste neu abrufen. Bei neuem Änderungsdurchlauf alle Datensatz IDs in diese Tabelle laden. Einer der Mitarbeiter pickt sich was raus. Alle anderen sehen den Rest (select * from picklist where ProcessingUser = NIL) Ist die Bearbeitung abgeschlossen, wird der Eintag aus der Tabelle gelöscht. Dadurch wird die Liste immer kürzer und es muss immer weniger geprüft, übertrag, etc. werden. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
achtung, langer text, vorn ein paar Erfahrungen, weiter hinten ein paar konkrete Vorschläge
Basierend auf Erfahrungen von einem vor langer Zeit von uns erstellten Projekt für einen sehr großen Konzern, bei dem 6 s2m isdn Karten mit je 30 isdn Kanälen gesteuert werden mussten und die vorherige Lösung (die nicht von uns kam) eine komplette Fehlkonstruktion war: Es ging um die Umsetzung einer callbox, sozusagen ein Anrufbeantworter, nur umgekehrt, der nahm keine Anrufe an, sondern musste einen freien der 180 isdn Kanäle auswählen und diesem dann eine passende Sounddatei vorspielen. Im Protokoll sollte dann enthalten sein, ob der Angerufene abgehoben hat, wie lange der Call aktiv war und noch ein paar andere Metadaten. Wenn abgehoben, dann wird der nicht wieder angerufen. Wenn nicht wird es je nach Auftrag nach x Minuten noch mal versucht. Was war das Problem der vorherigen Lösung: Ein Programmierer des Konzerns hatte dafür eine C++-Anwendung geschrieben, die Daten aus einer Postgres-Datenbank bekam und sich dort per random einen Call aus der Call Tabelle holte, versuchte diesen zu sperren, diesen auf dem isdn kanal zu verarbeiten und dann nach Durchführung die Metadaten zurück in die Datenbank zu schreiben. Auch nicht erfolgreiche sperren wurden versucht, in die datenbank zu schreiben. Das ganze System sollte ausgelegt werden für 50000 ausgehende Anrufe pro Tag und als Zeitraum war nur zwischen 08:00 und 20:00 wochentags erlaubt, also ein halber Tag. Das der gesamte Tag 86400 Sekunden hat, wissen die meisten von uns, es bleiben also nur 43200 Sekunden für 50000 Anrufe, also weniger als eine Sekunde pro Anruf, die aber leider inkl. der tüdelüt Melodie am anfang und am ende alle zwischen 25 und 35 sekunden braucht. Typischer Inhalt: Wir haben ihren auftrag erhalten und bearbeiten den so schnell wie möglich, ... Die Auftragsdaten kamen in die Datenbank von einer Konzern SAP Schnittstelle, an die der Inhalt der o.a. Metadaten dann später auch zurückgehen sollte. Was war das Problem der gewählten Anwendung c++? Der client wurde auf dem master control server in der anzahl der verfügbaren kanäle gestartet, also liefen ca 180 parallel laufende executables auf einer linux maschine, die schon ziemlichen dampf hatte. Wenn die nix machen wäre das auch kein problem. Gleichzeitig lief dort aber auch die Postgres Datenbank, mit der sich alle clients verbunden haben. Wenn ein call rausging, sorgte die executable dafür, das der s2m controller server, auf dessen kanal der Client konfiguriert war, dieser das dann erledigen sollte. Die s2m hardware einsteckkarte war auch wohl high end, dir hatten davon eine im office, angeblicher wert ca 10000 € (wir hatten zwar keinen s2m anschluss, aber für die programmierung ging das mit der karte in einem Simulationsmodus ganz gut und beim endkunden hatten wir zugriff auf eine reale maschine mit realen s2m). Um nicht zu weit auszuholen: die vorherige Anwendung war nach dem Serverstart innerhalb von 30-45 minuten je nach anzahl der Aufträge als Datenbank nicht mehr erreichbar, weil alle clients wie bekloppt immer die gesamten auftragsmenge runtergeladen habe, sich im client per random einen ausgesucht haben und den dann versuchten zu sperren. Das führte bei der Konstellation beim vorherigen Entwickler mit 50 Aufträgen und gerade mal 10 aktiven isdn kanälen zu ganz guten ergebnissen im testbetrieb, so das man damit versuchte, das System scharf zu schalten. Der reale Dateneingang, der auch schon bescheiden programmiert war, sorgte aber mit allen aktiven 180 Kanal executables dafür, das nicht mal mehr simple sql befehle vom postgres server innerhalb akzeptabler zeit beantwortet wurden (auch nach 60 minuten kam das zeitweise keine antwort). Das System lief komplett amok und wurde dafür dann wohl sogar in der Presse bekannt, das es eine Arztpraxis 24 Stunden am Tag ca alle 3-5 Minuten angerufen hat und egal, ob die abgenommen haben oder nicht, danach wieder angerufen wurde. Das ging wohl mehrere Tage so, obwohl angeblich die Daten aus dem System entfernt wurden. Da es auch ncoh die Notrufnummer dieser Arztpraxis war, konnte man die auch nicht so einfach abschalten. Man entschied sich dann nach dem Prssebericht in dem Konzern, die Lösung komplett abzuschalten, weil die auch nach mehreren reboots aller beteiligten Systeme der unkontrollierbare Amoklauf erneut losging. Die Technik (serverhardware) war auf jeden fall nicht schuld und als wir dann mit dem damaligen Projektleiter, zu dem wir im Rahmen eines anderen Projekts schon einen sehr guten Kontakt hatten, zu einer gemeinsamen Analyse des vorhandenen Systems eingeladen wurden, konnte ich mir mehrfach das schmunzeln nicht verkneifen. Alle Clients holten sich im Sekundentakt immer alle Aufträge in den eigenen Speicher von der Datenbank, es gab ein optimistisches locking, d.h. ob ein auftrag evtl schon von jemand gesperrt war oder nicht war dem client nicht bekannt, er versuchte einfach einen lock auf einen auftrag mit einem update. wenn der klappt, legte der los usw. Wenn der aber nicht klappt weil schon von jemand anders gesperrt solte der client sich die auftragsliste noch mal neu und es ging von vorne los (ohne in irgnedeiner art einen timeout zu haben). Ihr ahnt es, wenn 10000 calls in der Auftragsliste sind, ist für alle genug frei, zufällig was zu erwischen, was frei ist. wenn aber nur 20 oder 30 calls drin sind, laufen ca 150 von 180 clients komplett amok und bringen jede datenbank an die Belastungsgrenze oder wie in diesem Fall deutlich darüber hinaus. Wir haben das dann so gemacht, das wir statt postgres firebird genommen haben, weil wir uns damit besser auskennen und direkt mit einem eintrag eines neuen callauftrags von der sap schnittstelle sorgte ein trigger auf dem server dafür, das dieser schon einem kanal zugeordnet wird, der den abarbeiten soll. python scripte auf den servern mit dem s2m karten, für die es dafür saubere apis gab, holten sich immer nur den jeweils obersten eintrag aus der firebird db aus seiner kanal queue, vermerkt diesen einen datensatz mit einem Insert in eine andere Tabelle als "in arbeit" (also kein update auf dem record selbst), arbeitet den ab und verschiebt den nach ausführung in eine andere tabelle und trägt die metadaten in der job ausführungstabelle per insert nach. Wenn nix in seiner queue ist macht der client auch nix und wartet 10 sekunden. Wenn was gerade abgearbeitet wurde, wartet der aber nicht, sondern holt sich den nächsten call sofort. Wenn keiner da ist, dann eben wieder warten. inserts sind immer pflegeleichter für multithreaded datenbanken, weil die nix sperren müssen im gegenatz zu updates. Eine Datensatzsperre muss nicht zwingend das sein, was die Datenbank dafür fordert (so was wie in firebird zB mit "select ... for update" oder direkter update), weil das hässliche nebeneffekte haben kann, wie zum Beispiel erforderliche langlaufende Transaktionen für die dauer der sperre. Eine extra lock tabelle, die von dir selber erstellt wird mit unique pk von der datentabelle und timestamp/user/ip/connection id/was auch immer kannst du auch extra selber erstellen und via trigger dafür sorgen, das echte updates auf der eigentlichen Tabelle nur dann erlaubt sind, wenn zu den metadaten vom aktuellen client die in der lock tabelle übereinstimmen. So kann ein Lock auch mal minuten, stunden oder sogar tage gültig sein, ohne irgendwas blockierendes machen zu müssen wie transaktionen lang offen halten. Und ganz nebenbei kannst du darüber dann auch gleich anzeigen, wer was gerade gelockt hat und seit wann und wenn das gewünscht ist kann ein andere client einen fremden lock übernehmen oder löschen. Wenn eine Queue größer wird und warum auch immer nicht sauber abgearbeitet wird (s2m server reboot oder kaputt zB) dann wird der inhalt von seiner queue von einem server prozess, der als sp implementiert war, auf andere aktive queues verschieben, sofern die noch keine exec job log eintrag haben. Die Architektur was also eigentlich zentral von der firebird db gesteuert und nicht zufallsbedingt von hunderten Clients, die sich alle gegenseitig dauernd blockieren. Mich erinnerte die Anforderung deines Kunden sehr stark an die Programmierung, die unser Vorgänger da verbrochen hat. Hundert Clients wühlen sich durch die Daten, sucht sich irgendwas nach Lust und Laune zufällig aus, sperren das dann mit updates usw. Die Realität selbst in sehr großen Callcentern, die sich solche Forderungen gerne mal ausdenken, kann man oft in entsprechende Bahnen lenken, in dem man ähnlich wie den o.a. isdn kanälen automatische serverbasierende regeln hinterlegt, weil es auch keinerlei sinn ergibt, das sich 100 call center agents auf dem Screen alle die ersten 50 aktiven datensätze anglotzen, um dann irgendwas anzuklicken, was jemand anders aber vielleicht auch schon gemacht hat. 50 records im sekundentakt sind im durchschnitt 20ms zeit pro record. Es wäre kompletter Unsinn, die Arbeitszeit da von hunderten Mitarbeitern zu verplempern, in dem hunderte den selben kram auf dem screen sehen, von denen mit sehr hoher wahrscheinlichkeit schon alles gesperrt ist, wenn das dann auch ncoh wild herumflackert wird es noch verrückter. Clientbasierte filter, die tausende records vom server holen und erst lokal ausfiltern sind da auch ein NoGo in Enterpriseumgebungen. Mein tip also: versuch erst mal dem Kunden die Probleme seiner Idee zu verdeutlichen und versuch es gar nicht erst, das mit hunderten client executables zu implementieren, die das selber unkoordiniert für sich entscheiden. In der Firebird Welt wäre in meiner Umsetzung ein zentrales Regelwerk für die Queue Zuordnung automatisiert per trigger o.ä. zuständig und wenn ein client dann was für ihn relevantes neues sehen soll, wird der per event alterter benachrichtigt (zB weil sein username als eventname benutzt wird) und nur der, für den es was relevantes neues gibt, holt sich dann die notwendigen daten neu (zB nur die sperrmerkmale infos der für ihn relvanten records mit pk der zugehörigen daten,wie zum Beispiel adressen). alle schon bekannte daten kann man lokal vorhalten und muss nicht jedes mal den gesamten kram neu laden. Lade die die anzuzeigenden Daten nur dann neu wenn das erforderlich ist und trenne das ganz sauber vom laden der statusinfos, um zu wissen welchen status 10000 records haben brauchst du nichts anderes als die pks der daten mit dem zugehörigen pk des zustands. wenn da ein pk kommt, den dein client noch nicht kennt kann der die details dazu ja noch mal extra holen. und ganz wichtig: wenn der client keine lebenszeichen vom anwender erkennt, weil weder mousemove noch keypress erkannt wurde, muss man auch nichts in echtzeit aktualisieren, dann reicht auch refresh im minutentakt. wenn man das gut designt bekommt man mit brauchbarer Firebird Server Hardware ziemlich problemlos 5000 sqls pro Sekunde vom server beantwortet, auch weil der meiste kram im Rahmen von readonly Transaktionen geholt werden kann. wenn das nicht reicht kann man das über replikation auf mehrere Server verteilen, die dann je 5000 sqls pro sekunde können. dafür einen chatserver oder ähnliches dazwischen zu packen wäre für mich keinesfalls ein vorteil, die machen oft am ende noch dinge, die du dann gar nicht mehr unter kontrolle hast. versuch die relevanten infos vom datenbankserver auf das minimum einzuschränken,also mit sqls das zu holen oder zu senden was notwendig ist. Verlass dich nicht auf Komponenten, das die schon nur das machen was notwendig ist, das ist keineswegs der Fall (beispiel dataset recordcount, db lookup comboboxen und fields usw). über umsetzungen auf basis von ado/datasource/dataset/dbgrid usw wird dir das Projekt unter vollast sicherlich früher als später um die Ohren fliegen. Da sorgt oft der client serveseitig für deutlich mehr last als man denkt. da macht das auch keine unterschied ob es mssql oder firebird ist. Vielleicht sind in meinem langen post aber ja schon ein paar Anregungen für dich dabei, wenn dir der ganze text nicht zu lang war. p.s.: in dem o.a. Projekt, bei dem eigentlich 50000 calls als maximum pro Tag vorgesehen waren, fanden wir ca. 9 monate, nachdem das projekt live ging, aufgrund eines Streiks der Konzernmitarbeiter an einem Tag sogar 500000 calls, die da erfolgreich abgewickelt wurden. Da war man auf beiden seiten sehr froh, das selbst damit das von uns implementierte Gesamtsystem nicht überfordert war. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Ich versuche mal eine kurze Zusammenfassung:
Stellen wir uns das mal praktisch vor: In einer Kiste liegen viele Teile, die ziemlich zügig und von vielen Mitarbeitern bearbeitet werden müssen. Ein Mitarbeiter nimmt sich ein Teil aus der Kiste um es zu bearbeiten. Und schon in diesem Augenblick muss feststehen (er sieht es ja auch), dass kein anderer Mitarbeiter dieses Teil in der Hand hat. Würde er es erst merken, wenn er das Teil in der Hand hält und müsste es dann zurücklegen, wäre wertvolle Arbeitszeit verschwendet worden. Daher müsste unsere Clientanwendung immer sehr zeitnah über Sperrungen informiert werden. Und das habe ich euch verschwiegen: Unsere Datenbanken laufen auf SQL-Servern, auf denen noch zahlreiche andere Datenbanken der Kunden laufen. Wenn jede Clientanwendung 1 x pro Sekunde die Sperr-Procedure abfragen würde, wären das locker 100 Abfragen pro Sekunden oder 6.000 pro Minute. Selbst wenn das hyper-performant wäre, würde der SQL-Admin schon bei der kleinsten Störung irgendeiner DB bei mir anrufen, weil auf unserer DB so viel Betrieb ist. Daher hatte mir die UDP-Broadcast-Idee ziemlich gut gefallen - wenn sie denn zuverlässig funktionieren würde. Damit gäbe es dann eine aktive Sperrbenachrichtigung und im Netzwerk würde sich nur etwas tun, wenn jemand tatsächlich arbeitet. Ansonsten wäre Funkstelle. Sieht so aus, als müsste man dann doch einen separaten TCP-Server oder so basteln, an dem sich alle Clients anmelden und aktiv über die Sperrungen benachrichtigt werden. Das scheint mir dann aber doch etwas zu aufwändig für so verrückte Kundenideen. Nochmals vielen Dank für eure Vorschläge. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
Wir machen es jetzt mal ganz anders, ist schnell gesagt.. Vielleicht sollte der Auftraggeber sich das noch mal in der Praxis vorstellen, bevor es ein teures Experiment wird. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Mal so als Vorschlag ein Kompromiss:
Jeder Mitarbeiter bekommt eine eingeschränkte Zahl an Datensätzen angezeigt, die für ihn reserviert werden. Aus denen sucht er sich einen aus und in diesem Moment werden die restlichen wieder freigegeben. Ist er fertig, bekommt er wieder welche zur Auswahl. Das würde den Kundenwunsch berücksichtigen, verschwendet aber nicht so viel Arbeitszeit und Ressourcen, weil er nur z.B. 10 statt 10.000 Datensätzen zur Auswahl hat und ist technisch einfacher umzusetzen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz