2014-09-02 14 views
5

Tôi đã triển khai một dịch vụ hazelcast lưu trữ dữ liệu của nó vào các bản đồ mapdb cục bộ thông qua MapStoreFactory và newMapLoader. Bằng cách này, các phím có thể được nạp nếu một cụm khởi động lại là cần thiết:Hazelcast và MapDB - triển khai một cơ sở dữ liệu phân tán đơn giản

public class HCMapStore<V> implements MapStore<String, V> { 

Map<String, V> map; 

/** specify the mapdb e.g. via 
    * DBMaker.newFileDB(new File("mapdb")).closeOnJvmShutdown().make() 
    */ 
public HCMapStore(DB db) { 
    this.db = db; 
    this.map = db.createHashMap("someMapName").<String, Object>makeOrGet(); 
} 

// some other store methods are omitted 
@Override 
public void delete(String k) { 
    logger.info("delete, " + k); 
    map.remove(k); 
    db.commit(); 
} 

// MapLoader methods 
@Override 
public V load(String key) { 
    logger.info("load, " + key); 
    return map.get(key); 
} 

@Override 
public Set<String> loadAllKeys() { 
    logger.info("loadAllKeys"); 
    return map.keySet(); 
} 

@Override 
public Map<String, V> loadAll(Collection<String> keys) { 
    logger.info("loadAll, " + keys); 
    Map<String, V> partialMap = new HashMap<>(); 
    for (String k : keys) { 
     partialMap.put(k, map.get(k)); 
    } 
    return partialMap; 
}} 

Vấn đề bây giờ tôi đang phải đối mặt là loadAllKeys phương pháp của giao diện MapLoader từ Hazelcast đòi hỏi trả lại toàn bộ chìa khóa của toàn bộ cụm NHƯNG mỗi cửa hàng nút CHỈ các đối tượng mà nó sở hữu.

Ví dụ: Tôi có hai nút và lưu trữ 8 đối tượng, sau đó ví dụ: 5 đối tượng được lưu trữ trong mapdb của node1 và 3 trong mapdb của node2. Đối tượng nào được sở hữu bởi nút nào do hazelcast quyết định. Bây giờ khi khởi động lại node1 sẽ trả về 5 khóa cho loadAllKeys và node2 sẽ trả về 3. Hazelcast quyết định bỏ qua 3 mục và dữ liệu bị 'mất'.

Điều gì có thể là một giải pháp tốt cho điều này?

Cập nhật cho tiền thưởng: Here Tôi hỏi này nằm trong danh sách hc gửi thư nhắc đến 2 lựa chọn (Tôi sẽ thêm 1 trở lên) và tôi muốn biết nếu có điều gì như thế này là đã có thể với Hazelcast 3.2 hoặc 3.3:

  1. Hiện tại giao diện MapStore chỉ nhận dữ liệu hoặc cập nhật từ nút cục bộ. Có thể thông báo cho giao diện MapStore của mọi hành động lưu trữ của toàn cụm sao? Hoặc có lẽ điều này là có thể với một số phép thuật người nghe? Có lẽ tôi có thể buộc hazelcast đặt tất cả các đối tượng vào một phân vùng và có 1 bản sao trên mỗi nút.

  2. Nếu tôi khởi động lại, ví dụ: 2 nút sau đó giao diện MapStore được gọi chính xác với cơ sở dữ liệu cục bộ của tôi cho node1 và sau đó cho node2. Nhưng khi cả hai nút tham gia dữ liệu của node2 sẽ bị xóa vì Hazelcast giả định rằng chỉ có nút chính mới có thể chính xác. Tôi có thể dạy cho hazelcast chấp nhận dữ liệu từ cả hai nút không?

Trả lời

0

Nó có vẻ là not easily possible: lớp

Các kiên trì cho Hazelcast đòi hỏi nó là một số loại lưu trữ trung ương. Giống như cơ sở dữ liệu hoặc tệp được chia sẻ.

hoặc xem here hoặc here. Sẽ xem xét OrientDB đang sử dụng Hazelcast và vẫn tồn tại trên đĩa.

1

Có lẽ hai tùy chọn:

1) Tìm hiểu cách phân vùng hoạt động trong Hazelcast. Tôi nghĩ rằng có thể có cách để có MapLoader mỗi phân vùng, và lực nút để tải chỉ phân vùng riêng của mình, điều này sẽ giải quyết xung đột.

2) khi nút quay lại trực tuyến, tương tác với cụm Hazelcast trước khi nút được thêm. Bạn có thể hợp nhất hai bộ một từ HZ thứ hai từ MapDB.

3) buộc Hazelcast lưu trữ tất cả dữ liệu trên mỗi nút. Đặt số phân vùng thành 1 hoặc một cái gì đó

+0

Cảm ơn - các tùy chọn là ý tưởng hay, nhưng tôi muốn biết tôi sẽ làm điều gì đó như thế và nếu điều đó có thể xảy ra. – Karussell

+0

Cũng thấy dự án của bạn :) https://github.com/jankotek/mapdb-hz-offheap – Karussell

2

Theo Hazelcast 3.3 tài liệu các MapLoader dòng khởi tạo như sau:

Khi GetMap() là lần đầu tiên gọi từ bất kỳ nút, khởi tạo sẽ bắt đầu tùy thuộc vào giá trị của InitialLoadMode. Nếu được đặt là EAGER, bắt đầu khởi động . Nếu nó được đặt là LAZY, khởi tạo thực sự không bắt đầu nhưng dữ liệu được tải mỗi lần tải phân vùng là hoàn thành.

  1. Hazelcast sẽ gọi MapLoader.loadAllKeys() để có được tất cả các phím của bạn trên mỗi nút
  2. Mỗi nút sẽ tìm ra danh sách các phím nó sở hữu
  3. Mỗi nút sẽ tải tất cả các phím thuộc sở hữu của mình bằng cách gọi MapLoader.loadAll (phím)
  4. Mỗi nút đặt mục thuộc sở hữu của mình vào bản đồ bằng cách gọi IMap.putTransient (key, giá trị)

Ở trên hàm ý rằng nếu các nút khởi động theo thứ tự khác thì các khóa cũng sẽ được phân phối khác nhau. Do đó, mỗi nút sẽ không tìm thấy tất cả/một số khóa được gán trong kho lưu trữ cục bộ của nó. Bạn sẽ có thể xác minh nó bằng cách thiết lập các điểm ngắt trong HCMapStore.loadAllKeys và HCMapStore.loadAll của bạn và so sánh các phím bạn sẽ nhận được với các phím đó.

Theo tôi, những gì bạn đang cố gắng để đạt được mâu thuẫn với khái niệm về bộ nhớ đệm được phân phối với các đặc điểm khả năng phục hồi như Hazelcast và do đó là không thể. I E. khi một nút biến mất (thất bại hoặc ngắt kết nối vì bất kỳ lý do gì) cụm sẽ cân bằng lại bằng cách di chuyển các phần dữ liệu xung quanh, quá trình tương tự sẽ xảy ra mỗi khi một nút tham gia một cụm. Vì vậy, trong trường hợp cluster thay đổi backstore cục bộ của node bị mất sẽ bị lỗi thời.

Cụm Hazelcast là động bởi bản chất, do đó nó không thể dựa vào backstore với cấu trúc liên kết phân tán tĩnh. Về cơ bản, bạn cần phải có một backstore chia sẻ để làm cho nó hoạt động với cụm hazelcast động. Cửa hàng sau cũng có thể được phân phối, ví dụ: cassandra, nhưng cấu trúc liên kết của nó phải độc lập với cấu trúc liên kết bộ nhớ cache cluster.

CẬP NHẬT: Dường như với tôi rằng những gì bạn đang cố gắng đạt được là hợp lý hơn dưới hình thức kho dữ liệu phân tán (trên cùng của MapDB) với bộ nhớ đệm cục bộ.

Tôi hy vọng điều này sẽ hữu ích.

1

Có thể tải dữ liệu được lưu trữ trên tất cả các nút nhưng tại thời điểm này, bạn phải thực hiện thủ công.

Trên mỗi nút:

HCMapStore store = createMapDbStore(); 
HazelcastInstance hz = createHz(store); // use store in MapStoreConfig as implementation 
IMap imap = hz.getMap("map"); 
Map diskMap = store.loadAll(store.loadAllKeys()); // load all entries on disk 
imap.putAll(diskMap); // put into distributed map 

Nhưng như đã đề cập trong danh sách gửi thư MapStore là không thực sự có ý định sẽ được sử dụng theo cách này. Cũng lưu ý rằng các bản sao lưu không được lưu vào đĩa theo cách này. Vì vậy, nếu bạn khởi động lại cụm của bạn và đĩa trên một nút chết, những mục đó sẽ bị mất.

+0

Cảm ơn! Điều này có nghĩa là có một khái niệm 'shard' được gọi là 'phân vùng', nhưng không có khái niệm bản sao? Nếu những mục đó sẽ bị mất, làm thế nào để HC đảm bảo rằng nó không bị mất dữ liệu nếu một nút bị chết? – Karussell

+0

@Karussell Mục được sao lưu trong bộ nhớ trên nhiều nút. Nếu một nút chết trong khi cụm đang chạy tốt. Nhưng với loại bản sao lưu cục bộ này không được lưu trữ trên đĩa. Vì vậy, nếu bạn tắt cụm của bạn, sau đó cố gắng để bắt đầu nó và một đĩa không bắt đầu bởi vì nó đã chết ... – Andrejs

+0

Tôi thấy và không có cách nào để truy cập sao lưu trong bộ nhớ này bằng cách nào đó? – Karussell

Các vấn đề liên quan