Panduan Pantas untuk Apache Geode

1. Gambaran keseluruhan

Apache Geode adalah grid data dalam memori yang diedarkan yang menyokong caching dan pengiraan data.

Dalam tutorial ini, kita akan membahas konsep utama Geode dan menjalankan beberapa contoh kod menggunakan klien Java-nya.

2. Persediaan

Pertama, kita perlu memuat turun dan memasang Apache Geode dan menetapkan persekitaran gfsh . Untuk melakukan ini, kita boleh mengikuti arahan dalam panduan rasmi Geode.

Dan kedua, tutorial ini akan membuat beberapa artifak sistem fail. Oleh itu, kita dapat mengasingkannya dengan membuat direktori sementara dan melancarkan perkara dari sana.

2.1. Pemasangan dan Konfigurasi

Dari direktori sementara kami, kami perlu memulakan contoh Locator :

gfsh> start locator --name=locator --bind-address=localhost

Pencari bertanggungjawab untuk penyelarasan antara ahli-ahli yang berbeza dari Geode Cluster , yang dapat kami tadbir lebih jauh melalui JMX.

Seterusnya, mari kita memulakan Server contoh kepada salah satu pihak atau lebih data Rantau s:

gfsh> start server --name=server1 --server-port=0

Kami menetapkan pilihan –server-port ke 0 sehingga Geode akan memilih port yang tersedia. Walaupun begitu, jika kita meninggalkan ia keluar, pelayan akan menggunakan port 40404. lalai server A adalah ahli dikonfigurasikan daripada Kluster yang berjalan sebagai satu proses jangka hidup dan bertanggungjawab untuk menguruskan data Kawasan .

Dan akhirnya, kita memerlukan Wilayah :

gfsh> create region --name=baeldung --type=REPLICATE

The Region akhirnya di mana kita akan menyimpan data kami.

2.2. Pengesahan

Mari kita pastikan bahawa kita mempunyai segala-galanya sebelum kita melangkah lebih jauh.

Pertama, mari kita periksa sama ada kita mempunyai Pelayan dan Pencari kita :

gfsh> list members Name | Id ------- | ---------------------------------------------------------- server1 | 192.168.0.105(server1:6119):1024 locator | 127.0.0.1(locator:5996:locator):1024 [Coordinator]

Dan seterusnya, bahawa kita mempunyai Wilayah kita :

gfsh> describe region --name=baeldung .......................................................... Name : baeldung Data Policy : replicate Hosting Members : server1 Non-Default Attributes Shared By Hosting Members Type | Name | Value ------ | ----------- | --------------- Region | data-policy | REPLICATE | size | 0 | scope | distributed-ack

Kita juga harus mempunyai beberapa direktori pada sistem fail di bawah direktori sementara kita yang disebut "locator" dan "server1".

Dengan keluaran ini, kita tahu bahawa kita sudah bersedia untuk terus maju.

3. Ketergantungan Maven

Sekarang kita mempunyai Geode yang sedang berjalan, mari kita mulai melihat kod pelanggan.

Untuk bekerja dengan Geode dalam kod Java kami, kami perlu menambahkan pustaka klien Apache Geode Java ke pom kami :

 org.apache.geode geode-core 1.6.0 

Mari mulakan dengan hanya menyimpan dan mengambil beberapa data di beberapa wilayah.

4. Penyimpanan dan Pengambilan Sederhana

Mari tunjukkan cara menyimpan nilai tunggal, kumpulan nilai serta objek tersuai.

Untuk mula menyimpan data di wilayah "baeldung" kami, mari kita sambungkan dengan menggunakan pencari:

@Before public void connect() { this.cache = new ClientCacheFactory() .addPoolLocator("localhost", 10334) .create(); this.region = cache. createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY) .create("baeldung"); }

4.1. Menyimpan Nilai Tunggal

Sekarang, kita boleh menyimpan dan mengambil data di rantau kita:

@Test public void whenSendMessageToRegion_thenMessageSavedSuccessfully() { this.region.put("A", "Hello"); this.region.put("B", "Baeldung"); assertEquals("Hello", region.get("A")); assertEquals("Baeldung", region.get("B")); }

4.2. Menyimpan Pelbagai Nilai sekaligus

Kami juga dapat menyimpan beberapa nilai sekaligus, katakan ketika berusaha mengurangkan kependaman rangkaian:

@Test public void whenPutMultipleValuesAtOnce_thenValuesSavedSuccessfully() { Supplier
    
      keys = () -> Stream.of("A", "B", "C", "D", "E"); Map values = keys.get() .collect(Collectors.toMap(Function.identity(), String::toLowerCase)); this.region.putAll(values); keys.get() .forEach(k -> assertEquals(k.toLowerCase(), this.region.get(k))); }
    

4.3. Menyimpan Objek Tersuai

String berguna, tetapi lebih cepat daripada lambat kita perlu menyimpan objek tersuai.

Mari kita bayangkan bahawa kita mempunyai rekod pelanggan yang ingin kita simpan menggunakan jenis kunci berikut:

public class CustomerKey implements Serializable { private long id; private String country; // getters and setters // equals and hashcode }

Dan jenis nilai berikut:

public class Customer implements Serializable { private CustomerKey key; private String firstName; private String lastName; private Integer age; // getters and setters }

Terdapat beberapa langkah tambahan untuk menyimpannya:

First, they should implement Serializable. While this isn't a strict requirement, by making them Serializable, Geode can store them more robustly.

Second, they need to be on our application's classpath as well as the classpath of our Geode Server.

To get them to the server's classpath, let's package them up, say using mvn clean package.

And then we can reference the resulting jar in a new start server command:

gfsh> stop server --name=server1 gfsh> start server --name=server1 --classpath=../lib/apache-geode-1.0-SNAPSHOT.jar --server-port=0

Again, we have to run these commands from the temporary directory.

Finally, let's create a new Region named “baeldung-customers” on the Server using the same command we used for creating the “baeldung” region:

gfsh> create region --name=baeldung-customers --type=REPLICATE

In the code, we'll reach out to the locator as before, specifying the custom type:

@Before public void connect() { // ... connect through the locator this.customerRegion = this.cache. createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY) .create("baeldung-customers"); }

And, then, we can store our customer as before:

@Test public void whenPutCustomKey_thenValuesSavedSuccessfully() { CustomerKey key = new CustomerKey(123); Customer customer = new Customer(key, "William", "Russell", 35); this.customerRegion.put(key, customer); Customer storedCustomer = this.customerRegion.get(key); assertEquals("William", storedCustomer.getFirstName()); assertEquals("Russell", storedCustomer.getLastName()); }

5. Region Types

For most environments, we'll have more than one copy or more than one partition of our region, depending on our read and write throughput requirements.

So far, we've used in-memory replicated regions. Let's take a closer look.

5.1. Replicated Region

As the name suggests, a Replicated Region maintains copies of its data on more than one Server. Let's test this.

From the gfsh console in the working directory, let's add one more Server named server2 to the cluster:

gfsh> start server --name=server2 --classpath=../lib/apache-geode-1.0-SNAPSHOT.jar --server-port=0

Remember that when we made “baeldung”, we used –type=REPLICATE. Because of this, Geode will automatically replicate our data to the new server.

Let's verify this by stopping server1:

gfsh> stop server --name=server1

And, then let's execute a quick query on the “baeldung” region.

If the data was replicated successfully, we'll get results back:

gfsh> query --query='select e.key from /baeldung.entries e' Result : true Limit : 100 Rows : 5 Result ------ C B A E D

So, it looks like the replication succeeded!

Adding a replica to our region improves data availability. And, because more than one server can respond to queries, we'll get higher read throughput as well.

But, what if they both crash? Since these are in-memory regions, the data will be lost.For this, we can instead use –type=REPLICATE_PERSISTENT which also stores the data on disk while replicating.

5.2. Partitioned Region

With larger datasets, we can better scale the system by configuring Geode to split a region up into separate partitions, or buckets.

Let's create one partitioned Region named “baeldung-partitioned”:

gfsh> create region --name=baeldung-partitioned --type=PARTITION

Add some data:

gfsh> put --region=baeldung-partitioned --key="1" --value="one" gfsh> put --region=baeldung-partitioned --key="2" --value="two" gfsh> put --region=baeldung-partitioned --key="3" --value="three"

And quickly verify:

gfsh> query --query='select e.key, e.value from /baeldung-partitioned.entries e' Result : true Limit : 100 Rows : 3 key | value --- | ----- 2 | two 1 | one 3 | three

Then, to validate that the data got partitioned, let's stop server1 again and re-query:

gfsh> stop server --name=server1 gfsh> query --query='select e.key, e.value from /baeldung-partitioned.entries e' Result : true Limit : 100 Rows : 1 key | value --- | ----- 2 | two

We only got some of the data entries back this time because that server only has one partition of the data, so when server1 dropped, its data was lost.

But what if we need both partitioning and redundancy? Geode also supports a number of other types. The following three are handy:

  • PARTITION_REDUNDANT partitions and replicates our data across different members of the cluster
  • PARTITION_PERSISTENT partitions the data like PARTITION, but to disk, and
  • PARTITION_REDUNDANT_PERSISTENT gives us all three behaviors.

6. Object Query Language

Geode also supports Object Query Language, or OQL, which can be more powerful than a simple key lookup. It's a bit like SQL.

For this example, let's use the “baeldung-customer” region we built earlier.

If we add a couple more customers:

Map data = new HashMap(); data.put(new CustomerKey(1), new Customer("Gheorge", "Manuc", 36)); data.put(new CustomerKey(2), new Customer("Allan", "McDowell", 43)); this.customerRegion.putAll(data);

Then we can use QueryService to find customers whose first name is “Allan”:

QueryService queryService = this.cache.getQueryService(); String query = "select * from /baeldung-customers c where c.firstName = 'Allan'"; SelectResults results = (SelectResults) queryService.newQuery(query).execute(); assertEquals(1, results.size());

7. Function

One of the more powerful notions of in-memory data grids is the idea of “taking the computations to the data”.

Simply put, since Geode is pure Java, it's easy for us to not only send data but also logic to perform on that data.

This might remind us of the idea of SQL extensions like PL-SQL or Transact-SQL.

7.1. Defining a Function

To define a unit of work for Geode to do,we implement Geode's Function interface.

For example, let's imagine we need to change all the customer's names to upper case.

Instead of querying the data and having our application do the work, we can just implement Function:

public class UpperCaseNames implements Function { @Override public void execute(FunctionContext context) { RegionFunctionContext regionContext = (RegionFunctionContext) context; Region region = regionContext.getDataSet(); for ( Map.Entry entry : region.entrySet() ) { Customer customer = entry.getValue(); customer.setFirstName(customer.getFirstName().toUpperCase()); } context.getResultSender().lastResult(true); } @Override public String getId() { return getClass().getName(); } }

Note that getId must return a unique value, so the class name is typically a good pick.

The FunctionContext contains all our region data, and so we can do a more sophisticated query out of it, or, as we've done here, mutate it.

And Function has plenty more power than this, so check out the official manual, especially the getResultSender method.

7.2. Deploying Function

We need to make Geode aware of our function to be able to run it. Like we did with our custom data types, we'll package the jar.

But this time, we can just use the deploy command:

gfsh> deploy --jar=./lib/apache-geode-1.0-SNAPSHOT.jar

7.3. Executing Function

Now, we can execute the Function from the application using the FunctionService:

@Test public void whenExecuteUppercaseNames_thenCustomerNamesAreUppercased() { Execution execution = FunctionService.onRegion(this.customerRegion); execution.execute(UpperCaseNames.class.getName()); Customer customer = this.customerRegion.get(new CustomerKey(1)); assertEquals("GHEORGE", customer.getFirstName()); }

8. Kesimpulannya

Dalam artikel ini, kami mempelajari konsep asas ekosistem Apache Geode . Kami melihat mudah dan senang dengan tipe standard dan kustom, kawasan yang direplikasi dan dipartisi, serta oql dan fungsi sokongan.

Dan seperti biasa, semua sampel ini terdapat di GitHub.