DBP2P es una base de datos NoSQL descentralizada que permite sincronizar datos entre múltiples nodos de forma automática. Este documento explica cómo funciona la sincronización y cómo utilizarla.
La sincronización en DBP2P utiliza el protocolo libp2p para comunicarse entre nodos y mantener los datos consistentes. Cuando se realiza una operación CRUD (Crear, Leer, Actualizar, Eliminar) en un nodo, esta operación se propaga automáticamente a todos los demás nodos conectados a la red P2P.
- Sincronización Automática: Todas las operaciones CRUD se sincronizan automáticamente.
- Descubrimiento de Nodos: Los nodos se descubren automáticamente mediante mDNS (en redes locales) y DHT (en Internet).
- Resolución de Conflictos: En caso de conflictos, se utiliza una estrategia de "último en escribir gana".
- Sincronización Completa: Es posible sincronizar manualmente todos los documentos con el comando
sync.
La sincronización está habilitada por defecto. Puedes configurarla en el archivo config.yaml:
network:
libp2p:
listen_addresses:
- "/ip4/0.0.0.0/tcp/4001"
- "/ip4/0.0.0.0/udp/4001/quic"
bootstrap_peers:
- "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
mdns:
enabled: true
service_name: "dbp2p"
interval: 10
dht:
enabled: true
mode: "server"
bootstrap_interval: 300- listen_addresses: Direcciones en las que el nodo escucha conexiones entrantes.
- bootstrap_peers: Nodos de arranque para conectarse a la red P2P.
- mdns.enabled: Habilita o deshabilita el descubrimiento de nodos mediante mDNS (para redes locales).
- mdns.service_name: Nombre del servicio mDNS.
- mdns.interval: Intervalo de anuncio mDNS en segundos.
- dht.enabled: Habilita o deshabilita el DHT (Distributed Hash Table) para descubrimiento de nodos en Internet.
- dht.mode: Modo de operación del DHT ("server" o "client").
- dht.bootstrap_interval: Intervalo de conexión a nodos de arranque en segundos.
La sincronización automática está habilitada por defecto. Cuando creas, actualizas o eliminas un documento, la operación se propaga automáticamente a todos los nodos conectados.
Puedes sincronizar manualmente todos los documentos con el comando sync en la interfaz de línea de comandos:
> sync
Sincronizando todos los documentos...
Sincronización completada
Para verificar los nodos conectados, puedes usar la API REST:
GET /api/network/peers
Respuesta:
{
"peers": [
"12D3KooWRzPQ8NFTXzKAEH3fRmmBZGgbqxYRdKtxVCPnkd8sDMxH",
"12D3KooWMHVqLUNpqXvQMPvbQhS7uaiCyWsiKXMQNL4RdpgMKSJf"
],
"count": 2
}- Verificar conectividad P2P: Asegúrate de que los nodos estén conectados entre sí. Puedes verificar los nodos conectados con la API REST.
- Verificar configuración de red: Asegúrate de que mDNS y/o DHT estén habilitados y configurados correctamente.
- Verificar firewalls: Asegúrate de que los puertos necesarios (por defecto, 4001) estén abiertos en tu firewall.
- Sincronización manual: Intenta sincronizar manualmente con el comando
sync.
En caso de conflictos (cuando dos nodos modifican el mismo documento), DBP2P utiliza una estrategia de "último en escribir gana". Esto significa que la última modificación recibida será la que prevalezca.
-
Inicia el primer nodo:
./dbp2p.exe -
Inicia el segundo nodo en otra máquina:
./dbp2p.exe -
Los nodos se descubrirán automáticamente mediante mDNS y comenzarán a sincronizar datos.
-
Configura los nodos con los mismos nodos de arranque en
config.yaml:network: libp2p: bootstrap_peers: - "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
-
Inicia los nodos:
./dbp2p.exe -
Los nodos se conectarán a los nodos de arranque y se descubrirán entre sí a través del DHT.
- La sincronización requiere que los nodos estén conectados a la red P2P.
- En redes con NAT, es posible que necesites configurar el reenvío de puertos para permitir conexiones entrantes.
- La estrategia de resolución de conflictos "último en escribir gana" puede no ser adecuada para todos los casos de uso.
classDiagram
class Main {
+main()
+runCLI()
}
class Config {
+API.Port int
+WebSocket.Port int
+Network libp2p config
+Auth.JWT.Secret string
+LoadConfig(path) *Config
+GetConfig() *Config
}
class Document {
-id string
-collection string
-data map
-version int
+NewDocument(collection, data) *Document
+Update(data)
+ToJSON() []byte
+MatchesQuery(query) bool
}
class Database {
-documents map[string]*Document
-persistence *PersistenceManager
-sync *DBSync
-anonymizer *Anonymizer
+CreateDocument(collection, data) *Document
+GetDocument(id) *Document
+UpdateDocument(id, data) *Document
+DeleteDocument(id) error
+QueryDocuments(collection, query) []*Document
+GetAllDocuments(collection) []*Document
+CreateBackup() string
+RestoreFromBackup(name) error
}
class PersistenceManager {
-dataDir string
-encryptionKey string
+SaveDocument(doc) error
+UpdateDocument(doc) error
+DeleteDocument(collection, id) error
+LoadAllDocuments() map[string]*Document
+CreateBackup() string
+RestoreFromBackup(name) error
}
class DBSync {
-pubSub *pubsub.PubSub
+PublishCreate(doc) error
+PublishUpdate(doc) error
+PublishDelete(docID) error
+SyncAllDocuments() error
+listenForUpdates()
}
class TransactionLogger {
+LogOperation(op, docID, doc) error
+ReadTransactions() []Transaction
}
class AuthManager {
-users map[string]*User
-roles map[string]*Role
-keyManager *KeyManager
+CreateUser(opts) *User
+GetUserByUsername(name) *User
+CreateAPIKey(userID, name, days) SecureAPIKey
+CheckUserPermission(userID, resource, action) bool
}
class KeyManager {
-encryptionKey []byte
+GenerateSecureAPIKey(name, days, perms) SecureAPIKey
+EncryptToken(token) string
+DecryptToken(encrypted) string
}
class User {
+ID string
+Username string
+PasswordHash string
+Roles []string
+GenerateAPIKey(name, days) APIKey
+VerifyAPIKey(token) bool
}
class APIServer {
-database *Database
-authManager *AuthManager
-binaryManager *BinaryManager
-auditLogger *AuditLogger
+Start(port) error
+setupRoutes()
+authMiddleware() Handler
+rateLimitMiddleware() Handler
}
class WSServer {
-database *Database
-authManager *AuthManager
-binaryManager *BinaryManager
-clients map[string]*Client
+ServeWS(port) error
+PublishEvent(event, collection, docID, doc)
}
class Client {
-conn *websocket.Conn
-user *User
+readPump()
+writePump()
+handleQuery(payload)
+handleCreate(payload)
+handleUpdate(payload)
+handleDelete(payload)
+handleBinaryUpload(data)
}
class Node {
-host host.Host
-dht *DHTService
-mdns *MDNSService
-sync *DBSync
+NewNode(ctx) *Node
+GetPeers() []string
+SetDatabase(db) error
}
class BinaryManager {
+StoreBinary(id, data) error
+GetBinary(id) []byte
+DeleteBinary(id) error
}
class Anonymizer {
+AnonymizeDocumentData(data, rules)
}
class RateLimiter {
+AllowRequest(key) bool
}
class SecureConfigManager {
+EncryptValue(plaintext) string
+DecryptValue(encrypted) string
}
class SecureBackup {
+SetSecureBackupKey(key)
+EncryptBackup(data) []byte
+DecryptBackup(data) []byte
}
class AuditLogger {
+LogLogin(username, success)
+LogSystemEvent(event, details)
+LogDocumentAccess(user, docID, action)
}
class SanitizeUtil {
+SanitizeCollectionName(name) string$
+SanitizeID(id) string$
}
%% Relationships
Main --> Config : carga
Main --> APIServer : inicia
Main --> WSServer : inicia
Main --> Node : inicia
Main --> Database : crea
Database --> Document : gestiona *
Database --> PersistenceManager : persiste
Database --> DBSync : sincroniza
Database --> TransactionLogger : registra
Database --> Anonymizer : anonimiza
Node --> DBSync : contiene
Node ..> MDNSService : inicia
Node ..> DHTService : inicia
APIServer --> Database : consulta
APIServer --> AuthManager : autentica
APIServer --> BinaryManager : archivos
APIServer --> AuditLogger : audita
APIServer --> RateLimiter : limita
WSServer --> Database : consulta
WSServer --> AuthManager : autentica
WSServer --> BinaryManager : archivos
WSServer --> Client : maneja *
Client ..> BinaryManager : sube/baja
AuthManager --> KeyManager : encripta
AuthManager --> User : gestiona *
AuthManager --> Role : gestiona *
Database --> SecureBackup : encripta backups
SecureConfigManager ..> Config : encripta valores
SanitizeUtil ..> APIServer : sanitiza entrada
SanitizeUtil ..> WSServer : sanitiza entrada
note for APIServer "REST API :8090\nEndpoints: /api/auth, /api/collections, /api/users, /api/backups"
note for WSServer "WebSocket :8100\nEventos: create, update, delete, binary"
note for Node "P2P :9000 (TCP) + :9001 (WS)\nlibp2p + mDNS + DHT"
| Capa | Paquete | Propósito |
|---|---|---|
| 🖥️ Interfaz | pkg/api/, pkg/ws/ |
REST API + WebSocket — punto de entrada para clientes |
| 🗂️ Dominio | pkg/db/, pkg/auth/ |
Modelo de datos, autenticación, lógica de negocio |
| 🌐 Red | pkg/p2p/, pkg/db/sync.go |
Conexión P2P (libp2p), descubrimiento mDNS/DHT, sincronización |
| 🔒 Seguridad | pkg/config/, pkg/backup/, pkg/encryption/ |
Cifrado, backups, configuración segura |
| 🛠️ Utilidades | pkg/util/, pkg/ratelimit/, pkg/audit/, pkg/anonymization/, pkg/binary/ |
Sanitización, rate limiting, auditoría, anonimización, archivos binarios |
| 🌐 Frontend | index.html, tienda.html, dbp2p.js, binary_utils.js |
Clientes web que consumen API REST + WebSocket |
flowchart LR
subgraph Cliente
HTML[index.html / tienda.html]
JS[dbp2p.js]
end
subgraph Backend
API["API REST :8090<br/>pkg/api/"]
WS["WebSocket :8100<br/>pkg/ws/"]
DB[(Database<br/>pkg/db/)]
P2P["P2P :9000<br/>pkg/p2p/"]
end
subgraph Red
PEERS[Otros Nodos]
end
HTML -->|fetch /api/*| API
JS -->|WebSocket /ws| WS
API --> DB
WS --> DB
DB -->|pubsub sync| P2P
P2P <-->|libp2p| PEERS
style HTML fill:#e1f5fe
style JS fill:#e1f5fe
style API fill:#dcedc8
style WS fill:#dcedc8
style DB fill:#fff9c4
style P2P fill:#f8bbd0
style PEERS fill:#f8bbd0