Skip to content

Commit 6d7799f

Browse files
RELEASE 2021.1 hotfix patch 26.09
1 parent 9df4cbd commit 6d7799f

31 files changed

Lines changed: 673 additions & 281 deletions

README.md

Lines changed: 107 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,111 @@
1-
# interference
2-
3-
##### java-based distributed database platform
4-
###### (c) 2010 - 2021 head systems, ltd
5-
###### current revision: release 2021.1
6-
###### for detailed information see:
7-
###### http://io.digital and doc/InterferenceManual.pdf
8-
###### contacts: info@inteference.su
1+
# interference open cluster
2+
3+
##### pure-java opensource distributed database platform
4+
(c) 2010 - 2021 head systems, ltd
5+
6+
current revision: release 2021.1
7+
for detailed information see doc/InterferenceManual.pdf
8+
9+
contacts: info@inteference.su
910
##### https://github.com/interference-project/interference
11+
##### http://io.digital
1012

1113

1214
## Concepts & features
1315

16+
######i.o.cluster also known as interference open cluster is a simple java framework enables you to launch a distributed database and complex event processing service within your java application, using JPA-like interface and annotations for structure mapping and data operations. This software inherits its name from the interference project, within which its mechanisms were developed.
17+
18+
######i.o.cluster is a opensource, pure java software.
19+
20+
The basic unit of the i.o.cluster service is a node - it can be a standalone running service, or a service running within some java application.
21+
22+
Each i.o.cluster node has own persistent storage and can considered and used as a local database with following basic features:
23+
1424
- runs in the same JVM with your application
1525
- operates with simple objects (POJOs)
1626
- uses base JPA annotations for object mapping directly to persistent storage
17-
- supports horizontal scaling SQL queries
27+
- supports SQL queries with READ COMMITTED isolation level
1828
- supports transactions
19-
- supports complex event processing (CEP) and simple streaming SQL
29+
- supports complex event processing and streaming SQL
2030
- can be used as a local or distributed SQL database
21-
- allows you to inserts data and run SQL queries from any node included in the cluster
22-
- does not require the launch of any additional coordinators
2331
- uses the simple and fast serialization
24-
- uses indices for fast access to data and increase performance of SQL joins
32+
- uses persistent indices for fast access to data and increase performance of SQL joins
33+
- allows flexible management of data in memory for stable operation of a node at any ratio of storage size / available memory, which allows, depending on the problem being solved, how to allocate all data directly in memory with a sufficient heap size, or use access to huge storages with a minimum heap size of java application
34+
35+
Nodes can be joined into a cluster, at the cluster level with inter-node interactions, we get the following features:
36+
- allows you to insert data and run SQL queries from any node included in the cluster
37+
- support of horizontal scaling SQL queries with READ COMMITTED isolation level
38+
- support of transparent cluster-level transactions
39+
- support of complex event processing (CEP) and simple streaming SQL
40+
- i.o.cluster nodes does not require the launch of any additional coordinators
41+
42+
##Overview
43+
44+
Initially, the service was designed in such a way that each node is a java application that can be launched both by sharing one JVM with the client application using the service, or autonomously.
45+
46+
Each node uses its own storage and, being included in the cluster, replicates to other nodes all changes made on it, and also reflects changes made on other nodes.
47+
48+
You can start the service of each specific node inside an application and use fast access to data inside the node, as well as execute queries that will automatically scale to other nodes in the cluster.
49+
50+
Also from your java application, you can use remote client connections to the nodes of an existing cluster without the need to deploy a full service with its own storage (see Remote Client).
51+
52+
Each of the nodes includes several mechanisms that ensure its operation:
53+
54+
- core algorithms (supports structured persistent storage, supports indices, custom serialization, heap management, local and distributed sync processes)
55+
- SQL and CEP processor
56+
- event transport, which is used to exchange messages between nodes, as well as between a node and a client application
57+
a brief diagram of the internal implementation of the service on the example of one node:
58+
59+
![Screenshot](doc/interference.png)
60+
61+
##Distributed persistent model
2562

26-
## NOTE:
63+
To include a node in the cluster, you must specify the full list of cluster nodes (excluding this one) in the cluster.nodes configuration parameter. The minimum number of cluster nodes is 2, and the maximum is 64 (for more details, see cluster configuration rules below).
2764

28-
Interference is not a RDBMS in the classical sense, and it does
29-
not support ddl operations (the table structure is created on the basis
30-
of @Entity class JPA-compatible annotations).
65+
After such configuration, we may start all configured nodes as cluster. In this case, all nodes will be use specific messages (events) for provide inter-node data consistency and horizontal-scaling queries.
66+
67+
Interference open cluster is a decentralized system. This means that the cluster does not use any coordination nodes; instead, each node follows to a set of some formal rules of behavior that guarantee the integrity and availability of data within a certain interaction framework.
68+
69+
Within the framework of these rules, all nodes of the Interference open cluster are equivalent. This means that there is no separation in the system of master and slave nodes - changes to user tables can be made from any node, also all changes are replicated to all nodes, regardless of which node they were made on.
70+
71+
Running commit in a local user session automatically ensures that the changed data is visible on all nodes in the cluster.
72+
73+
##Distribute rules
74+
75+
The concept of interference open cluster is based on a simple basic requirement, which can be literally expressed as follows: we must allow insertion and modification of data at the cluster level from any node, and we must allow data retrieval from any node, using as much as possible the computing resources of the cluster as a whole. Further, we accept the condition that all cluster nodes must be healthy and powered on, if any of the nodes has been turned off for a while, it will not be turned on to receive data until her storage is synchronized with other nodes. In practice, in the absence of changes in the moment, this means that there are identical copies of the storage on the cluster nodes. To prevent conflicts of changes in cluster, several lock modes are used:
76+
77+
- table level (a session on a node locks the entire table)
78+
- frame level (a session on a node locks a frame)
79+
- disallowed changes for non-owner nodes
80+
81+
here it is necessary to explain in more detail: all data inserts on a certain node are performed into a frame which was allocated on the same node, for which, in turn, the node is the owner. This is done so that when there are simultaneous inserts into a table from several nodes at once, there are no conflicts during replication. Subsequently, this distinction allows us to understand whether or not to request permission to change the data in the frame at the cluster level or not. Moreover, it allows us to implement a mode when changes to frames on a non-owner node are prohibited. This mode is used on cluster nodes if one or more other nodes become unavailable (we cannot know for certain whether the node is down or there is a problem in the network connection).
82+
83+
Thus, let's repeat again:
84+
85+
- all cluster nodes should be equivalent
86+
- all changes on any of the nodes are mapped to other nodes immediately
87+
- data inserts are performed in local storage structure, and then the changes are replicated to other nodes.
88+
- if replication is not possible (the node is unavailable or the connection is broken), a persistent change queue is created for this node
89+
- the owner of any data frame is the node on which this frame has been allocated
90+
- data changes in node own dataframe are performed immediately, else, performed distributed lock for dataframe on cluster level
91+
- if cluster is failed (some node are offline or connection broken), all data changes are not allowed or changes in only node own dataframes allowed
92+
- the cluster uses the generation of unique identifiers for entities (@DistributedId annotation) so that the identifier is unique within the cluster, but not just within the same node
93+
- the cluster does not use any additional checks for uniqueness, requiring locks at the cluster level
94+
95+
##SQL horizontal-scaling queries
96+
97+
All SQL queries called on any of the cluster nodes will be automatically distributed among the cluster nodes for parallel processing, if such a decision is made by the node based on the analysis of the volume of tasks (the volume of the query tables is large enough, etc.)
98+
If during the processing of a request a node is unavailable, the task distributed for this node will be automatically rescheduled to another available node.
99+
100+
##Complex event processing concepts
101+
102+
So, we must allow insertion and modification of data at the cluster level from any node, and we must allow data retrieval from any node, using as much as possible the computing resources of the cluster as a whole.
103+
104+
The next concept of interference open cluster is that any table is at the same time a queue, in particular, using the SELECT STREAM clause, we can retrieve records in exactly the same order in which they were added. In general, at the cluster level, the session.persist() operation can be considered as publishing a persistent event. Based on our basic distribution rules, we send this event to all nodes.
105+
106+
Interference open cluster does not currently support the standard DML UPDATE and DELETE operations, instead for bulk table processing (including the optional WHERE clause) we have implemented PROCESS and PROCESS STREAM clauses that allow us to process each record from a selection of one of the EventProcessor interface implementations.
107+
108+
On the one hand, this approach allows us to obtain results similar to those that we would achieve using UPDATE and DELETE, on the other hand, it significantly expands the possibilities for custom processing of records, allowing full event processing. For the sake of fairness, it is need noting that you can get similar results using standard SELECT and SELECT STREAM, using some custom code to process the result set, but PROCESS and PROCESS STREAM implement processing at the core level of the cluster, which significantly improve the performance, second, this statements are launched at the cluster level and provide a ready-made implementation for distributed event processing.
31109

32110
## Quick Start Application
33111

@@ -60,15 +138,21 @@ Next, specify the necessary set of keys in the project
60138

61139
```
62140
-Dsu.interference.config=interference.properties
141+
-verbose:gc
142+
-Xloggc:/ioclustergc.log
143+
-XX:+PrintGCDetails
144+
-XX:+PrintGCDateStamps
145+
-XX:+AggressiveOpts
146+
-Xms1G
147+
-Xmx4G
148+
-XX:MaxMetaspaceSize=256m
149+
-XX:+UseStringDeduplication
150+
-XX:ParallelGCThreads=4
151+
-XX:ConcGCThreads=2
152+
-Dlogback.configurationFile=config/app-log-config.xml
63153
-Dcom.sun.management.jmxremote
64154
-Dcom.sun.management.jmxremote.port=8888
65-
-Dcom.sun.management.jmxremote.local.only=false
66155
-Dcom.sun.management.jmxremote.authenticate=false
67156
-Dcom.sun.management.jmxremote.ssl=false
68-
-Xms1g
69-
-Xmx4g
70-
-XX:MaxMetaspaceSize=256m
71-
-XX:ParallelGCThreads=8
72-
-XX:ConcGCThreads=4
73157
```
74158

config/properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ sync.lock.enable=true
4949

5050
# size of blocking queue, which use in SQL retrieve
5151
# mechanism for prevent of heap overload
52+
# NOTE: too small values for large frame sizes may cause locks on queue.put() during distributed processing
5253
retrieve.queue.size=100000
5354

5455
# the number of threads for parallel processing of the SQL query

doc/InterferenceManual.pdf

45.3 KB
Binary file not shown.

doc/interference.png

32.1 KB
Loading

src/main/java/su/interference/core/Config.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ public class Config {
106106
private static final int HEAP_USE_THR_INDX_DEFAULT = 60;
107107
private static final int HEAP_USE_THR_TEMP_DEFAULT = 40;
108108
private static final int HEAP_USE_THR_UNDO_DEFAULT = 50;
109+
// locks and processing
110+
private static final boolean IGNORE_COMMAND_CHANNEL_FAILURES_DEFAULT = true;
109111

110112
public final int LOCAL_NODE_ID;
111113
public final String DB_PATH;
@@ -141,6 +143,8 @@ public class Config {
141143
// internal
142144
public final int TEST_DISTRIBUTE_MODE = 1;
143145
public final int CHECK_AVAIL_FRAME_TIMEOUT = 3000;
146+
// locks and processing
147+
public final boolean IGNORE_COMMAND_CHANNEL_FAILURES = true;
144148

145149
private final Properties p;
146150

src/main/java/su/interference/core/Frame.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,11 @@ public synchronized int updateChunk(DataChunk chunk, Object o, Session s, LLT ll
450450
return chunk.getBytesAmount();
451451
}
452452

453-
public synchronized void deleteChunk (int ptr, Session s, LLT llt) {
453+
public synchronized void deleteChunk (int ptr, Session s, LLT llt, boolean ignoreNoLocal) {
454454
if (!this.isLocal()) {
455-
throw new CannotAccessToForeignRecord();
455+
if (!ignoreNoLocal) {
456+
throw new CannotAccessToForeignRecord();
457+
}
456458
}
457459
final Transaction tran = s.getTransaction();
458460
final long sync = LLT.getSyncId();

src/main/java/su/interference/core/IndexFrame.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ public HashMap<Long, Long> getAllocateMap() {
424424
final long allocId = bd.getAllocId();
425425
imap.put(c.getHeader().getFramePtr(), allocId);
426426
} else {
427-
logger.error("getAllocaleMap found null data frame for frame id " + c.getHeader().getFramePtr());
427+
logger.error("getAllocateMap found null data frame for frame id " + c.getHeader().getFramePtr());
428428
}
429429
}
430430
}

src/main/java/su/interference/core/Instance.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ this software and associated documentation files (the "Software"), to deal in
4949
public class Instance implements Interference {
5050

5151
public static final String RELEASE = "2021.1";
52-
public static final int SYSTEM_VERSION = 20210905;
52+
public static final int SYSTEM_VERSION = 20210926;
5353

5454
public static final String DATA_FILE = "datafile";
5555
public static final String INDX_FILE = "indxfile";

src/main/java/su/interference/core/RetrieveQueue.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ this software and associated documentation files (the "Software"), to deal in
2424

2525
package su.interference.core;
2626

27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
2729
import su.interference.persistent.Session;
30+
2831
import java.util.concurrent.LinkedBlockingQueue;
2932

3033
/**
@@ -33,6 +36,7 @@ this software and associated documentation files (the "Software"), to deal in
3336
*/
3437

3538
public class RetrieveQueue {
39+
private final static Logger logger = LoggerFactory.getLogger(RetrieveQueue.class);
3640
private final LinkedBlockingQueue<Chunk> q;
3741
private final ManagedCallable r;
3842
private volatile boolean retrieve = true;
@@ -53,7 +57,7 @@ public synchronized Object poll(Session s) {
5357
return c.getEntity(s);
5458
}
5559
} catch (Exception e) {
56-
e.printStackTrace();
60+
logger.error("exception occured during retrieveQueue.poll", e);
5761
}
5862
return null;
5963
}
@@ -69,7 +73,7 @@ public synchronized Chunk cpoll() {
6973
return c;
7074
}
7175
} catch (Exception e) {
72-
e.printStackTrace();
76+
logger.error("exception occured during retrieveQueue.cpoll", e);
7377
}
7478
return null;
7579
}

src/main/java/su/interference/core/SyncFrame.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ public SyncFrame(Frame frame, Session s, FreeFrame fb) throws Exception {
7272
public SyncFrame(Frame frame, Session s, FreeFrame fb, boolean proc) throws Exception {
7373
final Table t = Instance.getInstance().getTableById(frame.getObjectId());
7474
final FrameData bd = Instance.getInstance().getFrameById(frame.getPtr());
75-
allowR = frame.isLocal() ? !t.isNoTran() || t.getName().equals("su.interference.persistent.UndoChunk") : false;
75+
//allowR = frame.isLocal() || bd.isLockedLocally() ? !t.isNoTran() || t.getName().equals("su.interference.persistent.UndoChunk") : false;
76+
allowR = !t.isNoTran() || (frame.isLocal() && t.getName().equals("su.interference.persistent.UndoChunk"));
7677
this.proc = bd == null ? false : proc;
7778
distributed = t.isDistributed();
7879

@@ -113,7 +114,7 @@ public SyncFrame(Frame frame, Session s, FreeFrame fb, boolean proc) throws Exce
113114
logger.info("evicted frame caused an NPE during SyncFrame construction id = " + frame.getPtr());
114115
}
115116
} catch (Exception e) {
116-
e.printStackTrace();
117+
logger.error("exception occured during SyncFrame.init", e);
117118
}
118119
parentId = 0;
119120
lcId = 0;

0 commit comments

Comments
 (0)