30 Ekim 2021 Cumartesi

FieldsQueryCursor Arayüzü - Thick Client

Giriş
Şu satırı dahil ederiz. QueryCursor arayüzünü gerçekleştirir
import org.apache.ignite.cache.query.FieldsQueryCursor;
getAll metodu
Örnek - Select
Şöyle yaparız
Ignite ignite = ...;
IgniteCache<PersonKey, Person> cache = ...;

List<List<?>> result = cache.query(
new SqlFieldsQuery("SELECT * FROM PERSON WHERE PERSONID = 9000")).getAll();
Örnek - Select
Şöyle yaparız
String sql   = "SELECT COUNT(*) AS NUM FROM " + cacheName + " " + sqlParam;
SqlFieldsQuery query = new SqlFieldsQuery(sql);
query.setArgs(args);

FieldsQueryCursor<List<?>> cursor = cache.query(query);
resultCount = cursor.getAll().get(0).get(0);
Örnek - Select
Şöyle yaparız
try (QueryCursor<List<?>> cur = cache2.query(new SqlFieldsQuery("select _key from table"))){
  for (List<?> r : cur) {
    Long key = (Long)r.get(0);
  }
}

26 Ekim 2021 Salı

IgniteSet Arayüzü - Thick Client In-Memory Data Grid

Giriş
Şu satırı dahil ederiz
import org.apache.ignite.IgniteSet;
Kalıtımı şöyledir
IgniteQueue<T> extends Set<T>
add metodu
Set'i yaratmak için name + CollectionConfiguration belirtilir

Örnek
Şöyle yaparız
IgniteSet<String> set = Ignition.ignite().set("setName", null);
for (int i = 0; i < 5; i++) {
  String item = UUID.randomUUID() + "_" + i;
  set.add(item);
}

for (String item : set)
  println("Set item: " + item);

println(set.contains("1"));
println("Set size: " + set.size());
println("Removed: " + set.remove("0"));

IgniteQueue Arayüzü - Thick Client In-Memory Data Grid

Giriş
Şu satırı dahil ederiz
import org.apache.ignite.IgniteQueue;
Kalıtımı şöyledir
IgniteQueue<T> extends BlockingQueue<T>
take metodu - Blocking
Kuyruğu yaratmak için queue name + capacity + CollectionConfiguration belirtilir

Örnek
Şöyle yaparız
IgniteQueue<String> queue = Ignition.ignite().queue("queueName", 0, null);
int TIMES = 10;
for (int i = 0; i < RETRIES; i++) {
  String item = UUID.randomUUID() + "_" + i;
  queue.put(item);
  println("Queue item has been added: " + item);
}

// IgniteQueue is fully compatible with Java library.
for (String item : queue)
  println("Queue item: " + item);

// Take items from queue head.
for (int i = 0; i < TIMES; i++)
  println("Queue item has been read from queue head: " + queue.take());

// Take items from queue head once again.
for (int i = 0; i < TIMES; i++)
  println("Queue item has been read from queue head: " + queue.poll());



CREATE TABLE WITH CACHE_NAME

Giriş
Açıklaması şöyle
When the CREATE TABLE command is executed, the name of the cache is generated with the following format- SQL_{SCHEMA_NAME}_{TABLE}. Use the CACHE_NAME parameter to override the default name.
Örnek
Şöyle yaparız. Burada CACHE_NAME olarak TradeStatsCache belirtiliyor
CREATE TABLE IF NOT EXISTS PRODSCHEMA.TRADESTATS 
(
    TRADERECORDCREATIONDATE VARCHAR(100),
    PRODUCTTYPE VARCHAR(100),
PRODUCTSUBTYPE VARCHAR(100),
TRADETYPE VARCHAR(100),
TOTALIMPACTEDTRADES BIGINT, TOTALTRADEOPENEXCEPTION BIGINT, TOTALTRADECOUNT BIGINT, UPDATEDAT TIMESTAMP, PRIMARY KEY (TRADERECORDCREATIONDATE,PRODUCTTYPE,PRODUCTSUBTYPE,TRADETYPE) ) WITH "template=outputDataCacheTemplate, CACHE_NAME=TradeStatsCache, AFFINITY_KEY=TRADERECORDCREATIONDATE, CACHE_GROUP=TRADE_METADATA_AGGREGATES, KEY_TYPE=com.abc.entities.trade.TradeStatsEntityKey, VALUE_TYPE=com.abc.entities.trade.TradeStatsEntity";

XML DataStorageConfiguration Bean

Giriş
Bu bean IgniteConfiguration bean'inin dataStorageProperty alanına denk gelir.

defaultDataRegionConfiguration Alanı
Örnek
Şöyle yaparız
<dataStorageConfiguration>
  <defaultDataRegionConfiguration
    name="Default_Region"
    initialSize="104857600"/> <!-- 100*1024*1024 -->

  <dataRegionConfigurations>
    <dataRegionConfiguration
      name="My_Region"
      initialSize="104857600"
      persistenceEnabled="true" 
      metricsEnabled="true" />
    </dataRegionConfigurations>
</dataStorageConfiguration>
defaultDataRegionConfiguration Alanı
Ne kadar bellek kullanacağını ve persistence kullanılıp kullanılmayacağını belirtiriz.
Örnek
Şöyle yaparız
<!-- Memory configuration. -->
<property name="dataStorageConfiguration">
  <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
    <property name="defaultDataRegionConfiguration">
      <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
        <!-- max RAM size -->
	<property name="maxSize" value="#{150 * 1024 * 1024}"/>

	<!-- memory metrics -->
	<property name="metricsEnabled" value="true"/>

	<!-- Enabling persistence. -->
	<property name="persistenceEnabled" value="true"/>
      </bean>
    </property>

    <!-- persistence metrics -->
    <property name="metricsEnabled" value="true"/>
  </bean>
</property>
wal Ayarları
  • walMode 
  • walSegmentSize
  • writeThrottlingEnabled
  • walPath
  • walArchivePath
gibi bir sürü ayar yapılabilir.

walMode Alanı
FSYNC değeri alabilir
Örnek
Şöyle yaparız
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
  <property name="metricsEnabled" value="true"/>
  <property name="walMode" value="FSYNC"/>
  <property name="defaultDataRegionConfiguration">
    <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
      <property name="persistenceEnabled" value="true"/>
      <property name="metricsEnabled" value="true"/>
    </bean>
  </property>

  <property name="walPath" value="/gridgain-dev/wal"/>
  <property name="walArchivePath" value="/gridgain-dev/walarchive"/>
</bean>
walSegmentSize Alanı
Örnek
Şöyle yaparız
<property name="dataStorageConfiguration">
  <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
    <!-- set the size of wal segments to 128MB -->
    <property name="walSegmentSize" value="#{128 * 1024 * 1024}"/>
    <property name="writeThrottlingEnabled" value="true"/>
    <!-- Set the page size to 8 KB -->
    <property name="pageSize" value="#{8 * 1024}"/>
    <property name="defaultDataRegionConfiguration">
      <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
        <property name="name" value="Default_Region"/>
	<!-- Memory region of 20 MB initial size. -->
	<property name="initialSize" value="#{20 * 1024 * 1024}"/>
	<!-- Memory region of 8 GB max size. -->
	<property name="maxSize" value="#{8L * 1024 * 1024 * 1024}"/>
	<!-- Enabling eviction for this memory region. -->
	<property name="pageEvictionMode" value="RANDOM_2_LRU"/>
	<property name="persistenceEnabled" value="true"/>
	<!-- Increasing the buffer size to 1 GB. -->
	<property name="checkpointPageBufferSize" value="#{1024L * 1024 * 1024}"/>
      </bean>
   </property>
   <property name="walPath" value="/gridgain/wal"/>
   <property name="walArchivePath" value="/gridgain/walarchive"/>
  </bean>
</property>

25 Ekim 2021 Pazartesi

JDBC Connection String

Giriş
jdbc ile bağlanmak istersek şöyle yaparız
jdbc:ignite:thin://localhost:10800
JdbcThinConnection nesnesi yaratır. Bu sınıf şöyle yani TCP ile bağlantı kuruyor
public class JdbcThinConnection implements Connection {
  ...
  private volatile JdbcThinTcpIo singleIo;
  ...
}
Schema
Başka scheme' ya bağlanmak istersek şöyle yaparız
jdbc:ignite:thin://localhost:10800/MY_SCHEMA
Hangi schema' ya bağlandıysak CREATE TABLE cümlesi o schema altında tablo yaratır.
Schema ile ilgili açıklama şöyle
Here are a few options to connect to a specific schema in Ignite:

  jdbc:ignite:thin://172.16.0.5/mySchema - will connect to "MYSCHEMA" (case insensitive)
  jdbc:ignite:thin://172.16.0.5/"mySchema" - will connect to "mySchema" (case sensitive)
Transaction
JDBC ile transaction yapılabilir. Konuyla ilgili bir soru burada.

Transaction Isolation Level
Grig Gain 8.8.9 ile denediğimde şu sonucu aldım
Connection conn = ...;
DatabaseMetaData dbmd = conn.getMetaData();
int defaultTransactionIsolation = dbmd.getDefaultTransactionIsolation();
//4 yani Connection.TRANSACTION_REPEATABLE_READ
Şu kod işe yaramaz
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Desteklenen Isolation Level'ları şöyle deneyebiliriz
DatabaseMetaData dbmd = conn.getMetaData();
if (dbmd.supportsTransactionIsolationLevel(Connection.TRANSACTION_REPEATABLE_READ)) {
  System.out.println("Supports TRANSACTION_REPEATABLE_READ");
}
if (dbmd.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE)) {
  System.out.println("Supports TRANSACTION_SERIALIZABLE");
}
ResultSet Tipleri
Grig Gain 8.8.9 ile denediğimde şu kod exception fırlattı.
Connection connection = ...;
PreparedStatement statement = connection.prepareStatement("...",
  ResultSet.TYPE_SCROLL_SENSITIVE, 
  ResultSet.CONCUR_UPDATABLE);
Exception şöyle
Invalid result set type (only forward is supported).
INSERT Cümlesi
Elimizde şöyle bir SQL olsun.
CREATE TABLE IF NOT EXISTS MYUSER (
  ID NUMBER(10,0),
  NAME VARCHAR2(100),
  PRIMARY KEY (ID)
) WITH "ATOMICITY=TRANSACTIONAL";
Ama aslında dokümantasyon şöyle. Aslında SQL Transaction ile TRANSACTIONAL_SNAPSHOT kullan diyor ancak bu cümle sanırım JDBC'yi kapsamıyor.
Enables fully ACID-compliant transactional cache behavior for the key-value API.
Note! In this mode, transactional consistency is guaranteed for key-value API operations only. To enable ACID capabilities for SQL transactions, use the TRANSACTIONAL_SNAPSHOT mode.

Note! This atomicity mode is not compatible with the other modes within the same transaction. if a transaction is executed over multiple caches, all caches must have the same atomicity mode, either TRANSACTIONAL_SNAPSHOT or TRANSACTIONAL.
Ancak benim denemelerimde bu tabloya şöyle yaptım ve sorun olmadan çalışıyor. Burada tablonun TRANSACTIONAL olmasında bir problem yok. Bunu denememim sebebi TRANSACTIONAL_SNAPSHOT kullandığımda MVCC'nin devreye girmesi. Ben de bunu istemiyorum
Connection connection = ...;

int id = ...;
String name = ...;
String SQL_INSERT = "INSERT INTO MYUSER(ID,NAME) VALUES(?,?)";
try (PreparedStatement insertStatement = connection.prepareStatement(SQL_INSERT)) {

  insertStatement.setLong(1, id);
  insertStatement.setString(2, name);

   updateStatement.executeUpdate();
} catch (Exception exception) {
 ...
}
Aynı şeyi tabloyu şöyle yaratarak denedim yine sorun çıkmadı
CREATE TABLE IF NOT EXISTS MYUSER (
  ID NUMBER(10,0),
  NAME VARCHAR2(100),
  PRIMARY KEY (ID)
) WITH "ATOMICITY=ATOMIC";
SELECT FOR UPDATE Cümlesi
Elimizde şöyle bir SQL olsun.
CREATE TABLE IF NOT EXISTS MYSEQUENCE (
  SEQ_NAME VARCHAR2(100),
  SEQ_VALUE NUMBER(10,0),
  PRIMARY KEY (SEQ_NAME)
) WITH "ATOMICITY=TRANSACTIONAL_SNAPSHOT";

INSERT INTO MYSEQUENCE(SEQ_NAME, SEQ_VALUE) VALUES ('SEQ1', 1);
Bu tabloda TRANSACTIONAL_SNAPSHOT kullanıldığı için SELECT FOR UPDATE yapılabilir. Şöyle yaparız
String SQL_QUERY = "SELECT SEQ_NAME, SEQ_VALUE FROM MYSEQUENCE WHERE SEQ_NAME = ? FOR UPDATE ";
try (PreparedStatement selectStatement = conn.prepareStatement(SQL_QUERY)) {
  ...
}
Eğer tabloyu TRANSACTIONAL_SNAPSHOT olarak yaratmazsak exception alırız. Exception şöyle
SELECT FOR UPDATE query requires transactional cache with MVCC enabled.
SELECT FOR UPDATE ile bir başka transaction bizim kaydımızı halen okuyabiliyor ancak güncelleyemez.


 


TcpDiscoveryVmIpFinder Sınfı

Giriş
Şu satırı dahil ederiz
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
setAddresses metodu
Örnek
Şöyle yaparız
TcpDiscoverySpi localDiscovery() {
  TcpDiscoverySpi discoverySpi = new TcpDiscoverySpi();
  discoverySpi.setLocalPort(48500);

  TcpDiscoveryVmIpFinder firstIpFinder = new TcpDiscoveryVmIpFinder();
  firstIpFinder.setAddresses(Collections.singletonList("127.0.0.1:48500..48520"));
  discoverySpi.setIpFinder(firstIpFinder);
  return discoverySpi;
}


Ignite Transaction Kullanımı

Giriş Bir tablo 3 tane atomicity değerinden birisine sahip olabilir. 1. ATOMIC 2. TRANSACTIONAL 3. TRANSACTIONAL_SNAPSHOT ATOMIC Açıklaması ...