Mô hình mạng phủ của hệ thống khảo duyệt mà chúng tôi đƣa ra là sự kết hợp của hai mạng phủ mà chúng tôi đặt tên là D-Chord. Hai mạng phủ này đƣợc định nghĩa giống nhƣ mạng phủ Chord có cùng không gian khóa. Mạng phủ đầu tiên đƣợc gọi là L-Chord (Locality Chord) và mạng phủ thứ hai đƣợc gọi là V- Chord (Virtual Chord).
Chúng tôi phát triển mạng phủ L-Chord dựa trên mô hình mạng phủ LDHT(đƣợc thể hiện trong chƣơng 3), qua đó tận dụng đƣợc những ƣu điểm của mạng phủ LDHT nhƣ phản ánh đƣợc cấu trúc mạng vật lý, từ đó cung cấp sự tính toán tính liền kề tuyệt đối. Chúng tôi sử dụng mạng phủ L-Chord để thực hiện tất cả các chức năng lookup của hệ thống khảo duyệt web, ngoài ra còn sử dụng để tìm kiếm nút tốt nhất để khảo duyệt một tên miền nào đó.
Mạng phủ V-Chord, đúng nhƣ tên gọi, là một không gian khóa ảo và không có bất cứ kết nối gì giữa các nút trên mạng phủ này. V-Chord đóng vai trò đảm bảo tính cân bằng tải của hệ thống, và bất kì thuật toán băm nào đảm bảo tính cân bằng tải đều có thể áp dụng cho vòng V-Chord. Về mặt thiết kế, hệ thống khảo duyệt web của chúng tôi hoạt động nhƣ một framework cho bất kì thuật toán nảo đảm bảo tính cân bằng tải áp dụng cho V-Chord, mà không ảnh hƣởng đến tính chất liền kề tuyệt đối của vòng L-Chord. Với phƣơng thức nhƣ vậy, chúng tôi đã tạo ra sự kết hợp tốt nhất giữa việc khai thác cấu trúc mạng vật lý với việc cân bằng tải.
Hình 14. Mô hình mạng phủ D-Chord
4.1.1 Thông tin lƣu trữ tại mỗi nút
Mô hình mạng phủ bao gồm 2 vòng L-Chord và V-Chord. Mạng phủ L- Chord bản chất là một mạng phủ Chord điển hình với thuật toán băm đặc biệt, nên mỗi nút chứa đầy đủ các thông tin định tuyến nhƣ đã đề cập trong phần giới thiệu mạng Chord. Mạng phủ V-Chord , nhƣ đã nói phía trên, không chứa bất kì kết nối gì giữa các nút, tất cả các thao tác tìm kiếm đều thông qua mạng phủ L-Chord, sau đó ánh xạ vào mạng phủ V-Chord. Do đó mỗi nút P trên vòng L-Chord sẽ chứa danh sách các nút trên vòng V-Chord có vị trí trên vòng V-Chord tƣơng ứng với vùng chịu trách nhiệm của nút P trên vòng L-Chord, chúng tôi gọi đây là danh sách ánh xạ của nút P (mapping list). Thông tin mỗi nút đƣợc lƣu trong danh sách ánh xạ của nút P bao gồm IP và vị trí của nút trên V-Chord và các nút đƣợc sắp xếp theo thứ tự chiều kim đồng hồ.
Để minh họa cụ thể hơn, chúng tôi sẽ đƣa ra danh sách ánh xạ của từng nút trong hình 15.
Hình 15. Ví dụ về danh sách ánh xạ của từng nút
Nhƣ vậy, mỗi nút trong mạng phủ sẽ chứa các thông tin đƣợc mô tả trong bảng 4. Các phần in đậm là các phần thêm vào so với vòng Chord điển hình.
Ký hiệu Chú giải
finger[k].start n + 2^(k - 1) mod 2^m, 1 <= k <= m, n là khóa định danh trên vòng L-Chord
finger[k].interval (finger[k].start, finger[k + 1].start)
finger[k].node Nút đầu tiên trên vòng L-Chord có giá trị định danh >= finger[k].start
successor Node tiếp theo trên vòng L-Chord, tƣơng đƣơng với
finger[k].node
predecessor Node ngay phía trƣớc trên vòng L-Chord
mapping_list[i].id Danh sách khóa định danh trên vòng V-Chord của các nút trong danh sách nút ánh xạ
mapping_list[i].node Danh sách nút trong danh sách nút ánh xạ
Bảng 4. Bảng chứa thông tin định tuyến trong D-Chord 4.1.2 Tìm kiếm trong vòng L-Chord
Do L-Chord là vòng Chord điển hình nên quá trình tìm kiếm trong vòng L- Chord tƣơng tự nhƣ quá trình tìm kiếm trên vòng Chord. Khi một nút n cần tìm kiếm một khóa có định danh id, nút n sẽ tìm nút chịu trách nhiệm lƣu giữ id đó.
Nếu nút n ở xa so với vị trí của nút lƣu giữ id, n có thể nhờ vào thông tin trong bảng Finger Table để định tuyến đến các nút xa hơn, từ đó dần dần tìm ra nút chịu trách nhiệm lƣu giữ id.
Thuật toán tìm kiếm trong vòng L-Chord đƣợc mô tả sau đây
// Tìm nút n để tìm kiếm nút chịu trách nhiệm khóa định danh id
n.L_find_successor(id)
n’ = L_find_predecessor(id); return n’.successor;
// Tìm nút n để tìm kiếm nút ngay phía sau khóa định danh id
n.L_find_predecessor(id)
n’ = n;
while (id not in (n’, n’.successsor))
n’ = n’.L_closest_preceding_finger(id); return n’; // Tìm nút gần nhất n. L_closest_preceding_finger(id) for i = m downto 1 if (finger[i].node in (n, id)) return finger[i].node; return n;
Các thuật toán trên là các thuật toán của vòng Chord điển hình. Chúng tôi chỉ đổi tên để thể hiện các thuật toán này đƣợc sử dụng trên vòng L-Chord.
Sau đây, chúng tôi xin đƣa ra một ví dụ mô tả quá trình tìm kiếm trên vòng L-Chord. Chúng tôi sử dụng ví dụ đã đề cập từ trƣớc. Do quá trìnhnày chỉ diễn ra trên vòng L-Chord nên chúng tôi bỏ qua vòng V-Chord trên hình vẽ 15.
Giả sử nút A tìm kiếm quá trị id = 15, các bƣớc tìm kiếm sẽ nhƣ sau
Quá trình tìm kiếm xuất phát từ nút A. Đầu tiên, nút A gọi phƣơng thức L_find_successor(15), trong phƣơng thức này, nút A sẽ gọi tiếp L_find_predecessor(15).
Trong hàm L_find_predecessor, nút A gọi hàm L_closest_preceding_finger(15), giá trị trả về sẽ là nút tại ví trí cuối cùng trên bảng finger là nút D.
Tiếp tục theo thuật toán, nút D tìm kiếm giá trị 15. Sau khi kiểm tra bảng finger, khi kiểm tra đến vị trí thứ 2 trên bảng finger, nút D sẽ tìm thấy nút thỏa mãn điều kiện, đó là nút E. Nút E này sẽ đƣợc trả về từ lời gọi hàm
L_find_predecessor(15). Cuối cùng, quá trình tìm kiếm A.L_find_successor(15) sẽ trả về nút tiếp theo của E là nút A.
Hình 16. Quá trình tìm kiếm trên vòng L-Chord. Nút tìm kiếm là nút A, id = 15
Nhƣ vậy, với nút tìm kiếm là nút A và giá trị cần tìm kiếm là id=15, thì quá trình tìm kiếm trên vòng L-Chord cho ra kết quả là nút A là nút chịu trách nhiệm với giá trị khóa 15.
4.1.3 Tìm kiếm trong vòng V-Chord
Do vòng V-Chord là một vòng ảo, không hề có bất cứ liên kết gì giữa các nút trong vòng V-Chord nên quá trình tìm kiếm trong vòng V-Chord sẽ dựa vào các kết nối của vòng L-Chord. Thuật toán tìm kiếm trên vòng V-Chord sẽ đƣợc mô tả sau đây
n.V_find_successor(id)
n’ = n.L_find_successor(id)
return n’.V_find_mapped_node(id)
n. V_find_mapped_node(id)
for i = n.mapping_list.length downto 1 if (id <= n.mapping_list[i].id)
return n.mapping_list[i].node return nil;
Khi một nút n cần tìm kiếm một khóa có định danh id trên vòng V-Chord, Nút P sẽ sử dụng hàm V_find_successor(id). Trƣớc hết, nút n sẽ tìm trên vòng L-
Chord nút n’ chịu trách nhiệm với định danh id trên vòng L-Chord, quá trình này đƣợc thể hiện qua lời gọi hàm n’=L_find_successor(id). Sau đó, dựa vào danh sách ánh xạ trên nút n’, nút n sẽ tìm đƣợc nút chịu trách nhiệm quản lý định danh id trên vòng V-Chord, thuật toán tìm kiếm trên danh sách ánh xạ đƣợc thể hiện trong hàm V_find_mapped_node(id).
Xét ví dụ trên, Giả sử, nút A muốn tìm kiếm khóa có định danh id = 12. Nút A trƣớc hết tìm trên vòng L-Chord nút chịu trách nhiệm với định danh 12, sử dụng cơ chế lookup của Chord, nút A sẽ tìm đƣợc nút E là nút chịu trách nhiệm giá trị 12 trên vòng L-Chord. Sử dụng danh sách ánh xạ của nút E, ta sẽ tìm thấy nút D là nút đầu tiên có giá trị khóa lớn hơn hoặc bằng giá trị 12. Từ đó ta xác định nút D là nút chịu trách nhiệm quản lý định danh id=12.
Sau đây, chúng tôi xin đƣa ra một ví dụ mô tả quá trình tìm kiếm trên vòng V-Chord. Chúng tôi sử dụng ví dụ đã đề cập từ trƣớc.
Hình 17. Quá trình tìm kiếm trên vòng V-Chord. Nút tìm kiếm là nút A, id = 7
Giả sử nút A tìm kiếm quá trị id = 7, các bƣớc tìm kiếm sẽ nhƣ sau
Trƣớc hết, nút A gọi phƣơng thức L_find_successor(7) để tìm nút chịu trách nhiệm với giá trị 7 trên vòng L-Chord. Kết quả trả về của phƣơng thức này là nút C có khóa định danh là 8.
Tiếp theo, nút C sẽ tìm trong bảng ánh xạ của mình nút trên vòng V-Chord chịu trách nhiệm với giá trị 7. Sử dụng phƣơng thức V_find_mapped_node(7), nút
C sẽ tìm đƣợc nút thỏa mãn yêu cầu có id >= 7 là nút đứng thứ 2 trong bảng ánh xạ, đấy là nút A.
Nhƣ vậy, với nút tìm kiếm là nút A và giá trị cần tìm kiếm là id=7, thì quá trình tìm kiếm trên vòng V-Chord cho ra kết quả là nút A là nút chịu trách nhiệm với giá trị khóa 7.
4.1.4 Nút tham gia vào hệ thống
Trong mạng động, các nút có thể tham gia bất kì lúc nào. Mục đích chính của quá trình tham gia là duy trì khả năng định vị mọi khóa trong mạng. Để thực hiện đƣợc mục đích này, mạng phủ Chord cần đảm bảo các yêu cầu sau:
- Nút tiếp theo của mỗi nút phải đƣợc duy trì đúng.
- Với mọi khóa k, nút chịu trách nhiệm với khóa k phải chịu trách nhiệm khóa k.
Với mô hình D-Chord, do có 2 vòng L-Chord và V-Chord, nên các yêu cầu cần đảm bảo sẽ bao gồm:
- Trong vòng L-Chord, nút tiếp theo của mỗi nút phải đƣợc duy trì đúng. - Trong vòng L-Chord, mỗi nút phải duy trì đúng danh sách ánh xạ của mình. - Trong cả hai vòng, với mọi khóa k, nút chịu trách nhiệm với khóa k phải
chịu trách nhiệm khóa k.
Trong phần này, tác giả mô tả quá trình một nút tham gia vào hệ thống mạng D-Chord. Do mạng D-Chord là một cải tiến của mạng Chord nên các thuật toán sử dụng trong quá trình một nút tham gia vào hệ thống mạng D-Chord sẽ sử dụng các thuật toán của mạng Chord.
Để đảm bao các yêu cầu trên, một nút tham gia vào mạng D-Chord phải thực hiện các thao tác sau
- Khởi tạo giá trị predecessor, bảng fingers và danh sách ánh xạ của nút n. Cập nhật lại danh sách ánh xạ của nút tiếp theo nút n trên vòng L-Chord.
- Cập nhật bảng finger và các giá trị predecessor của các nút khác.
- Thêm nút n vào danh sách ánh xạ của các nút trên vòng L-Chord nếu cần thiết.
Chúng tôi giả định rằng trong vòng có một nút đƣợc công khai ra ngoài, gọi là nút bootstrap, (ví dụ là nút đƣợc ánh xạ vào một Tên miền thông qua DNS) mỗi nút n muốn tham gia vào vòng D-Chord sẽ liên hệ với nút bootstrap này.
Sau đây là thuật toán để một nút mới tham gia vào mang D-Chord
#define successor finger*1+.node
// nút n tham gia vào mạng // nút n’ là nút bootstrap n.join(n’) if (n’) L_init_finger_table(n’); L_update_others(); update_other_mapping_list (); else for i = 1 to m finger[i].node = n; predecessor = n; mapping_list = [];
// khởi tạo bảng finger
// n’ là một nút bất kì trong mạng
n. L_init_finger_table(n’)
finger[1].node = n’.L_find_successor(finger[1].start); predecessor = successor. predecessor;
successor. predecessor = n;
n. mapping_list = successor. L_update_ mapping_list _table(n);
for i = 1 to m-1
if (finger[i + 1].start in (n, finger[i].node)) finger[i+1].node = finger[i].node;
else
finger[i+1].node = n’.
L_find_successor(finger[I + 1].start);
// chia bảng L_parent của nút n theo n’,
// sử dụng để tách một phần bảng L_parent khi có nút mới tham gia // n’ là nút mới tham gia
n.L_update_ mapping_list _table(n’)
var ret_table = []; var old_id = n’;
if ((mapping_list [i].id <= n’) or (n’ in (old_id, mapping_list [i].id)))
ret_table.add(mapping_list [i]); else
break;
old_id = mapping_list[i].id;
while mapping_list [1].id <= n’
mapping_list.remove(mapping_list [1]); return ret_table;
// cập nhật bảng finger của các nút liên quan
n.L_update_others() for i = 1 to m p = L_find_predecessor(n – 2^(i-1)); p.L_update_finger_table(n, i); n. L_update_finger_table(s, i) if (s in (n, finger[i].node)) finger[i].node = s;
predecessor. L_update_finger_table(s, i);
// v_id khóa định danh của n trên vòng V-Chord
n.update_other_mapping_list()
p = L_find_ successor(v_id); p.V_ mapping_list _add(v_id, n);
// Thêm một nút n’ vào danh sách mapping_list của nút n // v_id là khóa định danh của n’ trên vòng V-Chord // n.l_id là khóa định danh của nút n trên vòng L-Chord
n.V_mapping_list_add(v_id, n’)
for i = mapping_list.size downto 1 if (mapping_list[i].id < v_id) if (mapping_list[i].id < n.l_id) V_mapping_list_insert(i, v_id, n’); V_mapping_list_standard(); return; V_mapping_list_insert(1, v_id, n’); V_mapping_list_standard(); predecessor. V_mapping_list_add(v_id, n’);
// chuẩn hóa lại danh sách ánh xạ của nút n
n.V_mapping_list_standard()
while (mapping_list[mapping_list.size - 1] >= n._l_id) mapping_list.del(mapping_list[mapping_list.size]);
for i = mapping_list downto pos
mapping_list[i + 1].id = mapping_list[i].id; mapping_list[i + 1].node = mapping_list[i].node; mapping_list[pos].id = v_id;
mapping_list[pos].node = n’;
Khi nút n tham gia vào hệ thống mạng D-Chord, trƣớc hết nút n sẽ tìm nút n’ là nút bootstrap đã có sẵn trong mạng, nút n sẽ gọi hàm join(n’). Trƣớc hết nút n sẽ kiểm tra n’ có tồn tại hay không, nếu n’ không tồn tại thì nút n sẽ thiết lập hệ thống mạng chỉ có một nút n. Nếu nút n’ tồn tại, nút n bắt đầu các phƣơng thức tham gia vào mạng D-Chord.
Trƣớc hết nút n sẽ cập nhật bảng finger và bảng danh sách ánh xạ (mapping_list) bằng cách gọi phƣơng thức L_init_finger_table(n’). Phƣơng thức này tƣơng tự với phƣơng thức có sẵn của vòng Chord, chúng tôi chỉ thêm phần cập nhật bảng danh sách ánh xạ bằng cách gọi câu lệnh L_update_ mapping_list _table(n) của nút successor và gán kết quả trả về vào danh sách ánh xạ của mình. Khi gọi hàm L_update_ mapping_list _table của nút succesor, nút successor sẽ lấy từ trong danh sách ánh xạ của mình ra các nút thuộc vùng chịu trách nhiệm của n và trả về cho nút n, sau đó nút successor sẽ loại bỏ các nút không còn trong vùng chịu trách nhiệm của mình.
Sau khi cập nhật bảng finger và danh sách ánh xạ thành công, nút n sẽ gọi phƣơng thức L_update_others(); để update bảng finger của các nút ảnh hƣởng. Quá trình này đƣợc lấy từ giao thức Chord chuẩn và chỉ có tác dụng trong vòng L- Chord.
Sau khi các nút cập nhật bảng finger thành công, lúc này nút n đã thành công tham gia vào vòng L-Chord, để nút n hoàn thành quá trình tham gia vào vòng V- Chord thì các nút phải thêm nút n vào danh sách ánh xạ của mình nếu vùng chịu trách nhiệm của nút đó trên vòng L-Chord có phần chung với vùng chịu trách nhiệm của nút n trên vòng V-Chord. Do đó, nút n sẽ gọi phƣơng thức update_other_mapping_list() để thực hiện quá trình này. Đầu tiên, nút n sẽ tìm kiếm trên vòng L-Chord nút p chịu trách nhiệm với giá trị V-id, là khóa định danh của n trên vòng V-Chord. Nút p sẽ thêm nút n vào danh sách ánh xạ của mình với vị trí xác định nhằm đảm bảo các nút trong danh sách ánh xạ tăng dần theo id. Trong trƣờng hợp nút n nằm đầu trong danh sách ánh xạ của nút p, nút p sẽ gọi hàm V_mapping_list_add(v_id, n) của predecessor để nút liền trƣớc nút p trong vòng L- Chord thêm nút n vào danh sách ánh xạ.
Sau khi các nút cập nhật thành công danh sách ánh xạ của mình, nút n đã hoàn thành quá trình tham gia vào vòng V-Chord. Nhƣ vậy nút n đã hoàn thành
tham gia vào 2 vòng V-Chord và L-Chord, tức là đã hoàn thành quá trình tham gia vào mạng D-Chord.
Sau đây, chúng tôi xin đƣa ra một ví dụ mô tả quá trình một nút tham gia vào hệ thống mạng D-Chord trong hình 18. Chúng tôi sử dụng ví dụ đã đề cập từ trƣớc với trƣờng hợp nút D chƣa tham gia vào hệ thống.
Hình 18. Mạng D-Chord trong trƣờng hợp chƣa có nút D
Sau đây, chúng tôi sẽ mô tả từng bƣớc quá trình nút D tham gia vào hệ thống D- Chord để làm rõ hơn quá trình này. Nút D có giá trị khóa định danh trên vòng L- Chord là l_id=11 và trên vòng V-Chord là v_id=15.
Giả sử nút A là nút bootstrap, trƣớc hết nút D khởi tạo bảng fingers của mình nhƣ sau:
Start Interval Node
12 (12,13)
13 (13, 15)
15 (15,3)
3 (3,11)
Khởi tạo giá trị predecesor, bảng fingers và danh sách ánh xạ của nút D. Để