Synchronizing Oracle Transactions into Couchbase with Oracle GoldenGate

Español

There are situations where data resides in several data stores across your company. Imagine a Product Catalog System. As an example, let us consider an Oracle Database holding master data serving logistics, provisioning, stock control and other back-end applications.

On the other hand, consider a web portal as front application for you customers. This application will have a lot of concurrent clients, and performance of the catalog subsystem is critical. This is a typical use case for Couchbase. You will get high performance and scalability, and perhaps you can also use Couchbase for storing user profiles, user sessions, or as a consolidation layer for other data stores.

In this scenario, a change in the master data in Oracle can be done by a back-end application, maybe adding a new product, or change a price for a particular product. Now your data in Couchbase is out of sync. How do you propagate this change to Couchbase to get consistency?

This is exactly what Oracle GoldenGate does. It takes transactions from an Oracle database and propagate to a target data store. Couchbase is not a supported target out-of-the-box yet, so you can use Oracle GoldenGate for Java adapter to act as the handler process.

cb_ggadapter

There are some aspects to consider before going into details:

Data modeling. Oracle is a relational database, with tables, rows and columns. On the other hand, Couchbase is a Document database, holding JSON documents with not fixed schema. Often documents at Couchbase will contain referenced data in the same data structure, to avoid complex joins and improve performance.

Data Loading. The first step to synchronize your data will be an initial load. From this point you can propagate changes from Oracle to Couchbase.

You can find an example implementation in this github repository. You will find there a tool for making initial load from Oracle and a GoldenGate java adapter for Couchbase.

Detailed instructions are available in the github repository. In a nutshell, the steps are:

  1. Make an initial load from Oracle to Couchbase
  2. Install GoldenGate in source and target machines
  3. Configure Oracle source database
  4. Install CouchbaseGoldenGateAdapter
  5. Configure GoldenGate processes: extract, pump and replicat
  6. Start the GoldenGate processes

As an example, you can use Oracle SQLPlus and Couchbase cbq to see how it works. Let us do a simple insert.

We will insert a new row in the table regions, with region_id=5. Initially, this registry is not present in Oracle nor in Couchbase:

(Oracle SQLPlus)

before5

(Couchbase cbq)

before5_cb

Now we do an insert in Oracle SQLPlus, followed by a commit

after5

Check that new document has been propagated to Couchbase:

after5_cb

So here you have it; GoldenGate replicating Oracle transactions to Couchbase.

 

Moving data from Oracle to Couchbase

One request I found frequently in customers is about moving data between Oracle and Couchbase. Oracle is a widely deployed relational database, and customers moving to Couchbase have this starting point challenge. How do we load my Couchbase database from the relational data in Oracle?

First thing to consider is that we are talking about different kind of database. Oracle database hold data organized in rows in tables. Each table has a fixed column set, and each row in a column is uniquely determined by a set of fields: the primary key. A database instance has many different tables.

On the other hand, Couchbase is a general purpose Document database. Couchbase follows a key-value approach where the key is a single String, and the value has no specific format. Usually, we use Couchbase as a Document store, where the value has a JSON format. In this way, there are some advanced features we can use, like global secondary indexes, views and N1QL, a SQL-like language for data access.

In Couchbase, there is not a fixed schema for holding data. Each JSON Document can have different attributes. In case of a new kind of data coming in, you do not need to modify the schema or create a new table, like in the relational world. This flexibility is one of the reasons customers are moving to Couchbase.

Another big difference between relational word and document databases are about data normalization. Relational databases general rule is to organize the columns (attributes) and tables of a relational database to minimize data redundancy. Data modeling in Couchbase, on the other hand, focus on maximizing performance on data access, so denormalize data is a common practice.

For this exercise we will use the following conventions:

  • Each JSON Document will include a root-element equal to the name of the table
  • All the attribute names will be lower-case
  • Couchbase is a key-value document database. The format of the key will be derived from the relational primary key as follows:
[table name in lower case]::[value of field1 of the PK]::[value of field 2 of the PK]:: ...
  • Numeric, boolean and text data types will be preserved in the transformation
  • Oracle Date and Timestamps types will be stored in Couchbase as milliseconds since January 1, 1970, 00:00:00 GMT

 

oracle2couchbase_1

So now it is time to write some code to do the magic … Don’t panic. I did it for you.

We will use the oracle2couchbase tool available here (Disclaimer: this is an unsupported tool!). Feel free to spent some time looking the code. Not too complex.

You will find instructions on how to run in your environment.

As example data from Oracle, let us use the HR model provided with any Oracle distribution as an example schema. We will move that to a Couchbase bucket named HR.

The command line looks as follows:

java -cp ./oracle2couchbase.jar:./lib/couchbase-java-client-2.2.2.jar:./lib/couchbase-core-io-1.2.2.jar:./lib/rxjava-1.0.15.jar:./lib/ojdbc6.jar -DcbClusterAddress=couchbaseMachine -DcbBucketName=HR -DoraAddress=oracleMachine -DoraUser=HR -DoraPassword=oracle -DoraService=XE -DoraTables=COUNTRIES,DEPARTMENTS,EMPLOYEES,JOBS,JOB_HISTORY,LOCATIONS,REGIONS com.oracle2couchbase.Loader

Now we can access to our data. Let us use SQL for Oracle and N1QL for Couchbase.

First query: look for the locations whose city name starts with ‘B’

Oracle SQLPlus

sqlplus1

Couchbase Query Workbench

n1ql1

This was the same query syntax.

Let us do some more complex: Count for the name of locations by country. Include the country name by doing a JOIN with the related JSON document countries (or table, in the relational world!), and order by total, then on name. This example shows how relationships are maintained.

Oracle SQLPlus

sqlplus2

Couchbase Query Workbench

n1ql2

Very similar syntax, as you can see.

To finish, let me notice that this is just an example, a first step on how to load data from Oracle to Couchbase. A more proper data design may include denormalize some data by embedding referred data on JSON documents.

If you want to go for an in depth discussion, do not miss the following excellent content:

 

Setting up a production ready cluster with MongoDB and Couchbase

Español

Congratulations! Your new NoSQL project is ready for go live. Your single node development environment has been so easy to deploy and work with. But, wait a moment!

Does that environment fit the production requirements? Are you ready for a system failure? How will your system survive a machine crash? Will you support the amount of data required? Are you ready to cope with the concurrent load expected?

So your single node is not enough. You need a proper production environment. You need a cluster.

In this entry, we will compare the effort for deploying a production cluster with two popular NoSQL Document Databases: MongoDB and Couchbase.

For this exercise, we will set up a production ready cluster with the following requirements:

  • The data will be distributed evenly in three shards
  • The cluster will support the failure of one node without data loosing
  • The cluster will support load balancing of the requests
  • For setting up the cluster, we will follow the official documentation for both MongoDB and Couchbase.

For those of you that can’t wait, let’s show the results and a short summary. In the next pages will go deep into the details:

mongo1 couchbase1

Number of machines required

14

3

Load Balancer

1

Not required

Number of commands executed

128

27

Number of files edited

28

0

This is how the different architectures looks like:

mongo1

mongo2

couchbase1

couchbase2

Summary

With this comparison, done following the official documentation from both MongoDB and Couchbase, it is easy to see what the differences between Couchbase and MongoDB are from an operational perspective. It is far easier to create, manage and operate Couchbase all while better utilizing server resources with few servers and better performance.

With Couchbase you also get a better and simpler inter-datacenter replication method to enable Disaster Recovery, High Availability and all at scale.

From development point of view, in MongoDB, you will need to enable sharding at the database level and the collection level. Furthermore, in order to a get an evenly balanced data distribution you will need to choose an appropriate sharding key, which can be tricky and cannot be changed after data insertion [1] [2].

To get an idea of the complexity, take a look at the following statement in the MongoDB documentation [3]:

“IMPORTANT

It takes time and resources to deploy sharding. If your system has already reached or exceeded its capacity, it will be difficult to deploy sharding without impacting your application.

As a result, if you think you will need to partition your database in the future, do not wait until your system is over capacity to enable sharding.”

Architecture details

MongoDB Architecture

We are following this documentation from MongoDB:

According to these recommendations and our initial requirements:

  1. We will need three Config Servers, each one in its own machine.
  2. The entry point for the clients are the Router process (mongos). We will use two of them, each one in his own machine.
  3. We will need a Load Balancer with client affinity. [NOTE: as an alternative to point 2 and 3, we can have one mongos instance on each application server]
  4. We will use three Shards, with one Replica Set on each one.
  5. Each Replica Set will contain three mongod instances, each one in its own machine. In total we will use 9 machines for sharding (3 shards x 3 mongod/shard x 1 machine/mongod)

Our MongoDB cluster architecture looks like this:

mongo2

  • Each Replica Set has three processes (mongod) each running on different machines. One of them acts a primary node, taking care of the data writing, and the other two acts as replica nodes, holding a copy of the master data in case of failure of the primary.
  • Each shard takes care of a subset of the data. The partitioning is done by choosing a shard key or by a hashing algorithm for each document and that key must be passed in with every call to the database or risk a scattered gather.
  • We deploy one replica set on each shard [5].
  • Access to the database is done through router nodes (mongos).
  • Clients talk to the mongos through a load balancer with client affinity.

With this deployment we need fourteen machines and one load balancer.

Couchbase Architecture

We are following this documentation from Couchbase:

According to these recommendations and our initial requirements:

  1. In Couchbase, each keyspace is called bucket. Each bucket is divided in a fixed number of partitions (1024), called vBuckets. All the vBuckets are distributed evenly among the nodes in the cluster. In order to divide the data in three shards, we will need 3 nodes, each one running on one machine. In this way, each node will have 1/3 of the data.
  2. Data is distributed evenly across the Data Service nodes
  3. Each document in the database is replicated automatically to a different node in the cluster
  4. Routing is done by directly from your client application code using the Couchbase SDK library. No special routing node or load balancer is needed

In our case, the Couchbase cluster architecture looks like this:

couchbase2

With this deployment we need three machines.

Detailed Installation of environment

For this exercise we will use 14 virtual machines Linux CentOS 7, with 2 Gb RAM each one.

We will name each machine: dbbox1, dbbox2, … dbbox14.

We have used fixed IPs and defined all the hostsnames on /etc/hosts file for all the machines.

MongoDB cluster setup

MongoDB installation

We will install MongoDB on 14 machines . On each machine:

vi /etc/yum.repos.d/mongodb-org-3.0.repo
[EDIT FILE]>>>>
[mongodb-org-3.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/x86_64/
gpgcheck=0
enabled=1
<<<<
sudo yum install -y mongodb-org
vi /etc/selinux/config
[EDIT FILE]>>>>
SELINUX=disabled
#SELINUX=enforcing
<<<<<
chkconfig mongod off
systemctl disable firewalld
reboot

(6 commands + 2 file edits) x 14 machines = 84 commands + 28 file edits

Configuration Servers

On 3 machines (dbbox10, dbbox11, dbbox12)

mkdir -p /mongodb/config
export LC_ALL=C
mongod --configsvr --logpath /mongodb/config/log --logappend --dbpath /mongodb/config --fork

3 commands x 3 machines = 9 commands

Routers (mongos)

On two machines (dbbox13, dbbox14)

mkdir /mongodb
mongos --configdb dbbox10:27019,dbbox11:27019,dbbox12:27019 --fork --logappend --logpath /mongodb

2 commands x 2 machines = 4 commands

Shards (mongod)

On nine machines (dbbox1, dbbox2, …, dbbox9)

First we will set up the replica sets

mkdir -p /mongodb/rs1_1
# Note different replica set and port for each process
mongod --shardsvr --replSet rs1 --dbpath /mongodb/rs1_1 --logpath /mongodb/log.rs1 --fork --logappend --smallfiles --oplogSize 50 --port 27001

(on each machine change replicas set names to match the architecture graph)

2 commands x 9 machines = 18 commands

On dbbox1:

mongo --port 27001
> rs.initiate()
{
"info2" : "no configuration explicitly specified -- making one",
"me" : "dbbox1:27001",
"ok" : 1
}
rs1:OTHER> rs.add("dbbox4:27001")
{ "ok" : 1 }
rs1:PRIMARY> rs.add("dbbox7:27001")
{ "ok" : 1 }

3 commands

On dbbox2:

mongo --port 27001
> rs.initiate()
{
"info2" : "no configuration explicitly specified -- making one",
"me" : "dbbox2:27001",
"ok" : 1
}
rs2:OTHER> rs.add("dbbox5:27001")
{ "ok" : 1 }
rs2:PRIMARY> rs.add("dbbox8:27001")
{ "ok" : 1 }

3 commands

On dbbox3:

mongo --port 27001
> rs.initiate()
{
"info2" : "no configuration explicitly specified -- making one",
"me" : "dbbox3:27001",
"ok" : 1
}
rs3:OTHER> rs.add("dbbox6:27001")
{ "ok" : 1 }
rs3:PRIMARY> rs.add("dbbox9:27001")
{ "ok" : 1 }

3 commands

Shards configuration:

On dbbox10:

mongo
mongos> sh.addShard("rs1/dbbox1:27001")
{ "shardAdded" : "rs1", "ok" : 1 }
mongos> sh.addShard("rs2/dbbox2:27001")
{ "shardAdded" : "rs2", "ok" : 1 }
mongos> sh.addShard("rs3/dbbox3:27001")
{ "shardAdded" : "rs3", "ok" : 1 }

4 commands

Check configuration

mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5612784c13c13614cd1e823b")
}
shards:
{  "_id" : "rs1",  "host" : "rs1/dbbox1:27001,dbbox4:27001,dbbox7:27001" }
{  "_id" : "rs2",  "host" : "rs2/dbbox2:27001,dbbox5:27001,dbbox8:27001" }
{  "_id" : "rs3",  "host" : "rs3/dbbox3:27001,dbbox6:27001,dbbox9:27001" }
balancer:
Currently enabled:  yes
Currently running:  no
Failed balancer rounds in last 5 attempts:  0
Migration Results for the last 24 hours:
No recent migrations
databases:
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }

Total:

128 commands

28 file edits

Couchbase: cluster setup

Couchbase Installation

We will install Couchbase on 3 machines (dbbox1, dbbox2, dbbox3). On each machine:

# Disable swappiness
sudo echo 0 > /proc/sys/vm/swappiness
sudo echo '' >> /etc/sysctl.conf
sudo echo '#Set swappiness to 0 to avoid swapping' >> /etc/sysctl.conf
sudo echo 'vm.swappiness = 0' >> /etc/sysctl.conf
# Disable THP
sudo echo never > /sys/kernel/mm/transparent_hugepage/enabled
sudo echo never > /sys/kernel/mm/transparent_hugepage/defrag
# Download binary
wget http://packages.couchbase.com/releases/4.0.0/couchbase-server-enterprise-4.0.0-centos7.x86_64.rpm
sudo rpm --install couchbase-server-enterprise-4.0.0-centos7.x86_64.rpm

8 commands x 3 machines = 24 commands

Cluster configuration

This can be done from a web browser. In this exercise we will use the CLI interface.

This will be done from one machine (dbbox1).

The first command initializes the cluster. The second command add node 2 to the cluster. The third command add node 3 to the cluster.

/opt/couchbase/bin/couchbase-cli cluster-init -c dbbox1.mysite.com:8091 -u Administrator -p change_it --cluster-username=Administrator --cluster-password=change_it --cluster-ramsize=256 --services=data,index,query

/opt/couchbase/bin/couchbase-cli server-add -c dbbox1.mysite.com:8091 –u Administrator –p change_it --server-add=dbbox2.mysite.com:8091 --services=data,index,query

/opt/couchbase/bin/couchbase-cli server-add -c dbbox1.mysite.com:8091 -u Administrator -p change_it --server-add=dbbox3.mysite.com:8091 --server-add-username=Administrator --server-add-password=change_it --services=data,index,query

3 commands

Total:

27 commands

NOTES

[1] (MongoDB)  Shard Keys –  http://docs.mongodb.org/manual/core/sharding-shard-key/

[2] (MongoDB)  Considerations for Selecting Shard Keys – http://docs.mongodb.org/manual/tutorial/choose-a-shard-key/

[3] (MongoDB)  Sharded Cluster Requirements – http://docs.mongodb.org/manual/core/sharded-cluster-requirements/

[4] (MongoDB)  Production Cluster Architecture – http://docs.mongodb.org/manual/core/sharded-cluster-architectures-production/

[5] (MongoDB)  Deploy a Sharded Cluster – http://docs.mongodb.org/manual/tutorial/deploy-shard-cluster/

[6] (MongoDB)  Deploy a Replica Set – http://docs.mongodb.org/manual/tutorial/deploy-replica-set/

[7] (Couchbase) Cluster Setup  – http://developer.couchbase.com/documentation/server/4.0/clustersetup/manage-cluster-intro.html

[8] (Couchbase) Command Line Interface reference – http://developer.couchbase.com/documentation/server/4.0/cli/cli-intro.html

[9] (Couchbase) Client Topology Awareness –  http://developer.couchbase.com/documentation/server/4.0/concepts/client-topology-awareness.html