Triển khai Nebula Console (Trình quản trị web)
Chúng ta sẽ triển khai Nebula Console bằng Docker để có giao diện quản lý trực quan. Console cần giao tiếp với Graph Service đã được cài đặt ở phần trước.
Tạo thư mục làm việc và tải Dockerfile cần thiết từ kho chứa chính thức của Nebula Graph.
mkdir -p /opt/nebula/console
cd /opt/nebula/console
curl -O https://raw.githubusercontent.com/vesoft/nebula-console/master/Dockerfile
File Dockerfile đã được tải về. Tiếp theo, chúng ta cần khởi tạo container với các biến môi trường chỉ định địa chỉ Graph Service.
docker run -d \
--name nebula-console \
-p 8080:8080 \
-e GRAPH_HOST=127.0.0.1 \
-e GRAPH_PORT=9669 \
-e USER=root \
-e PASSWORD=nebula \
-v /opt/nebula/console/data:/data \
vesoft/nebula-console:latest
Container Nebula Console đã chạy và lắng nghe cổng 8080. Biến GRAPH_HOST và GRAPH_PORT trỏ về Graph Service nội bộ.
Verify kết quả
Kiểm tra trạng thái container và truy cập giao diện web để đảm bảo kết nối thành công.
docker ps | grep nebula-console
curl -I http://localhost:8080
Trạng thái container là "Up" và lệnh curl trả về mã trạng thái 200 OK. Bạn có thể mở trình duyệt và truy cập http://IP_SERVER:8080 để thấy giao diện đăng nhập.
Cấu hình tài khoản Admin và quyền truy cập (RBAC)
Nebula Graph sử dụng mô hình RBAC (Role-Based Access Control). Mặc định có user "root" với quyền tối cao. Chúng ta sẽ tạo user quản trị viên mới và phân quyền cụ thể để đảm bảo bảo mật.
Tạo Role và User mới
Truy cập Console bằng tài khoản root (mật khẩu: nebula) hoặc dùng nGQL CLI để tạo cấu hình quyền.
CREATE ROLE dba_role;
GRANT ALL ON GRAPHSPACE test_graph TO dba_role;
CREATE USER 'admin_user' IDENTIFIED BY 'SecurePass123!';
GRANT ROLE dba_role TO admin_user;
Văn bản nGQL đã thực thi thành công. Role "dba_role" được tạo và cấp toàn quyền cho graphspace "test_graph", sau đó gán cho user "admin_user".
Cấu hình quyền cho GraphSpace cụ thể
Để giới hạn quyền truy cập chỉ vào một graphspace cụ thể thay vì toàn bộ cụm, sử dụng lệnh GRANT chi tiết.
CREATE ROLE read_only_role;
GRANT READ ON GRAPHSPACE test_graph TO read_only_role;
CREATE USER 'viewer' IDENTIFIED BY 'ViewerPass456';
GRANT ROLE read_only_role TO viewer;
User "viewer" hiện chỉ có quyền đọc (SELECT) trên graphspace "test_graph" và không thể thực hiện lệnh viết (INSERT, DELETE, UPDATE).
Verify kết quả
Thử đăng nhập bằng tài khoản mới vào Console để xác nhận quyền hạn.
SHOW USERS;
SHOW ROLES;
Danh sách user và role hiện ra bao gồm cả "admin_user" và "viewer". Khi đăng nhập bằng "viewer" trên Console, các menu quản trị (CREATE, DROP) sẽ bị ẩn hoặc báo lỗi "Permission denied".
Kết nối từ máy khách qua trình duyệt Console
Khi máy khách (Client) nằm trên mạng khác, cần cấu hình firewall và Graph Service để chấp nhận kết nối từ xa. Nebula Console chạy trên máy chủ sẽ đóng vai trò proxy kết nối.
Cấu hình Firewall (UFW)
Mở cổng 8080 cho giao diện web và cổng 9669 (hoặc 9669-9671) cho giao tiếp nGQL nếu kết nối trực tiếp.
sudo ufw allow 8080/tcp
sudo ufw allow 9669/tcp
sudo ufw reload
Cổng 8080 và 9669 đã được mở. Lệnh reload áp dụng ngay lập tức các quy tắc mới.
Cấu hình Graph Service chấp nhận kết nối từ xa
File cấu hình của Graph Service (nebula-graphd.conf) cần được chỉnh sửa để lắng nghe trên tất cả các giao diện mạng (0.0.0.0).
Chỉnh sửa file cấu hình tại /etc/nebula/nebula-graphd.conf (đường dẫn có thể khác tùy phiên bản cài đặt, kiểm tra trong phần 3).
sudo nano /etc/nebula/nebula-graphd.conf
Sửa dòng listen_addr thành 0.0.0.0 trong file cấu hình.
listen_addr = "0.0.0.0"
Tiếp theo, khởi động lại dịch vụ Graph để áp dụng thay đổi.
sudo systemctl restart nebula-graphd
Dịch vụ Graph đã khởi động lại và lắng nghe trên tất cả các IP của máy chủ.
Verify kết quả
Từ máy khách khác, mở trình duyệt và truy cập http://IP_SERVER:8080. Đăng nhập bằng tài khoản "admin_user".
curl -v http://IP_SERVER:8080
Nếu thấy kết nối thành công và tải được trang đăng nhập, cấu hình kết nối từ xa đã hoàn tất.
Sử dụng nGQL CLI để tạo Schema (Tag, Edge, Index)
Chúng ta sẽ sử dụng giao diện dòng lệnh nGQL (có thể chạy trên Console hoặc CLI riêng) để định nghĩa cấu trúc dữ liệu. Đây là bước chuẩn bị cho việc lưu trữ dữ liệu thực tế.
Kết nối nGQL CLI
Chạy nGQL CLI để kết nối trực tiếp với Graph Service.
nebula-console -u root -p nebula -a 127.0.0.1 -P 9669
Console nGQL mở ra với prompt: (nebula) [(nebula)]> hoặc tương tự, sẵn sàng nhận lệnh.
Tạo Tag (Node Schema)
Định nghĩa một loại Node (Vertex) gọi là "player" với các thuộc tính như id, name, age.
USE test_graph;
CREATE TAG player (
id INT64,
name STRING,
age INT32,
position STRING
);
Tag "player" đã được tạo thành công. Schema này sẽ được lưu trữ trong Meta Service và phân phối đến các Storage Service.
Tạo Edge (Relationship Schema)
Định nghĩa một loại quan hệ (Edge) gọi là "team" để liên kết các player với nhau, bao gồm các thuộc tính về năm tham gia.
CREATE EDGE team (
joined_year INT32,
role STRING
);
Edge "team" đã được tạo. Bây giờ bạn có thể tạo các quan hệ có hướng giữa các node player.
Tạo Index (Chỉ mục)
Tạo index để tối ưu hóa tốc độ tìm kiếm dựa trên thuộc tính "name" của tag "player".
CREATE INDEX player_name ON player(name(20));
Index "player_name" đã được tạo. Tham số (20) giới hạn độ dài chuỗi index hóa, giúp tiết kiệm không gian lưu trữ.
Verify kết quả
Liệt kê toàn bộ schema đã tạo để xác nhận cấu hình.
SHOW TAGS;
SHOW EDGES;
SHOW INDEXES;
Danh sách trả về bao gồm "player", "team" và index "player_name". Nếu không có lỗi, schema đã sẵn sàng cho dữ liệu.
Thực hiện các truy vấn cơ bản để kiểm tra tính nhất quán
Thử nghiệm luồng dữ liệu hoàn chỉnh: Chèn dữ liệu (Insert), Truy vấn (Select) và Xóa (Delete) để đảm bảo Graph Service và Storage Service hoạt động đồng bộ.
Chèn dữ liệu mẫu (Insert Vertex & Edge)
Chèn hai node player và tạo một quan hệ team giữa họ.
INSERT VERTEX player(id, name, age, position) VALUES
1001 ("LeBron James", 39, "Forward"),
1002 ("Stephen Curry", 35, "Guard");
INSERT EDGE team(joined_year, role) VALUES
1001 -> 1002 (2019, "Teammate");
Dữ liệu đã được ghi vào Storage Service. Lệnh trả về số lượng node và edge đã chèn thành công (ví dụ: 2 vertices, 1 edge).
Truy vấn dữ liệu (Match & Select)
Sử dụng nGQL (tương tự Cypher) để tìm kiếm các node và quan hệ vừa tạo.
MATCH (p:player) WHERE p.id == 1001 RETURN p;
MATCH (p1:player)-[r:team]->(p2:player) RETURN p1, r, p2;
Kết quả trả về chi tiết thuộc tính của node LeBron James và quan hệ giữa LeBron James với Stephen Curry.
Xóa dữ liệu (Delete)
Xóa một node và quan hệ để kiểm tra tính nhất quán của dữ liệu (cascade delete hoặc manual delete).
DELETE EDGE 1001 -> 1002 ON team;
DELETE VERTEX 1002 ON player;
Quan hệ và node đã được xóa. Lưu ý: Nebula Graph không tự động xóa edge khi xóa vertex nguồn nếu không cấu hình cascade, nhưng edge sẽ trở thành "orphan" (cô lập).
Verify kết quả
Truy vấn lại để xác nhận dữ liệu đã bị xóa hoàn toàn.
MATCH (p:player) WHERE p.id == 1002 RETURN p;
MATCH (p1:player)-[r:team]->(p2:player) RETURN p1, r, p2;
Kết quả trả về là tập rỗng (empty set), xác nhận rằng các thao tác xóa đã thành công và dữ liệu không còn tồn tại trong hệ thống.
Điều hướng series:
Mục lục: Series: Triển khai Database Graph phân tán với Nebula Graph trên Ubuntu 24.04
« Phần 3: Triển khai Graph Service và Storage Service cho cụm phân tán
Phần 5: Tối ưu hóa hiệu năng và cân bằng tải cho dữ liệu lớn »