How to set up a Mysql Cluster in Amazon EC2

February 9th, 2010

I didn’t write this. I am just syndicating from a site that keeps trying to redirect me through a javascript hack.

This is a quick Howto for setting up MySQL cluster using Amazon EC2 instances. I have used 3 small instances (1 mgmt + 2 data nodes) from RightScale’s CentOS 5 public image to test things. I’ve a working cluster using these steps but there’s no guarantee that these steps works for you as well.

Management server for cluster:
Although we can set up management server for cluster in one of the data node but we should have a third node as if one of the two MySQL cluster nodes fails, and the management server is not running, then the data on the two cluster nodes will become inconsistent and if the same node fails which have management server, then we will not be able to create another node or configure cluster.

Beginning with MySQL 5.1.6, it is possible to store the non-indexed columns of NDB tables on disk, rather than in RAM as with previous versions of MySQL Cluster. Here I’m using MySQL 5.1.26-rc as its the latest version while writing this article.

Let’s dive in practical:
1. Fireup 3 instances and note down their public and private IPs, dedicate roles(mgmt, node) for them and login in management node. Install ncurses library for MySQL compilation requirement:
# yum install ncurses ncurses-devel

2. Download mysql source from its source download page:
# cd /usr/src
# groupadd mysql
# useradd -g mysql mysql
# wget http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.26-rc.tar.gz/from/ftp://mirror.services.wisc.edu/mirrors/mysql/
# tar xzf mysql-5.1.26-rc.tar.gz
# cd mysql-5.1.26-rc

3. Compile and install:
# ./configure –enable-community-features –with-mysqld-user=mysql –with-mysqlmanager –with-plugins=ndbcluster
# make && make install

4. Create required directories:
# mkdir -p /var/lib/mysql/mysql-cluster/backup
# chown -R mysql:mysql /var/lib/mysql
# cd /var/lib/mysql/mysql-cluster
# vim config.ini

[NDBD DEFAULT]
NoOfReplicas=2
DataMemory=80M # How much memory to allocate for data storage
IndexMemory=18M # How much memory to allocate for index storage
# For DataMemory and IndexMemory, we have used the
# default values. Since the “world” database takes up
# only about 500KB, this should be more than enough for
# this example Cluster setup.
[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]
# Section for the cluster management node
[NDB_MGMD]
# IP address of the management node (this system)
HostName=10.252.169.x
# Section for the storage nodes
[NDBD]
# IP address of the first storage node
HostName=10.254.237.x
DataDir=/var/lib/mysql/mysql-cluster
BackupDataDir=/var/lib/mysql/mysql-cluster/backup
DataMemory=2048M
[NDBD]
# IP address of the second storage node
HostName=10.251.74.x
DataDir=/var/lib/mysql/mysql-cluster
BackupDataDir=/var/lib/mysql/mysql-cluster/backup
DataMemory=2048M

# one [MYSQLD] per storage node
[MYSQLD]
[MYSQLD]

Save and close the file.

5. Start management server. You can also copy ndb_mgmd in system path for easy access.
# /usr/src/mysql-5.1.26-rc/storage/ndb/src/mgmsrv/ndb_mgmd -f /var/lib/mysql/mysql-cluster/config.ini

***
Setup of Node1 and Node2:

1. These settings are identical for Node 1 and Node 2. Let’s start by adding mysql user and group:
# groupadd mysql
# useradd -g mysql mysql

2. Install required ncurses library for MySQL compilation:
# yum install ncurses ncurses-devel

3. Download, compile and install MySQL:
# cd /usr/src
# wget http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.26-rc.tar.gz/from/ftp://mirror.services.wisc.edu/mirrors/mysql/
# tar xzf mysql-5.1.26-rc.tar.gz
# cd mysql-5.1.26-rc
# ./configure –enable-community-features –with-mysqld-user=mysql –with-mysqlmanager –with-plugins=ndbcluster
# make && make install

4. Install initial mysql db:
# /usr/src/mysql-5.1.26-rc/scripts/mysql_install_db –user=mysql

5. Create directories:
# mkdir -p /var/lib/mysql/mysql-cluster/backup
# chown -R mysql:mysql /var/lib/mysql

6. Copy init script from mysql source to preferred location:
# cp /usr/src/mysql-5.1.26-rc/support-files/mysql.server /etc/init.d/
# chmod 755 /etc/init.d/mysql.server

7. Create config file for MySQL:
# vim /etc/my.cnf

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1
ndbcluster
# IP address of the cluster management node
ndb-connectstring=10.253.191.210
default-storage-engine=NDBCLUSTER
#Those are for future tuning
#max_connections=341
#query_cache_size=16M
#thread_concurrency = 4
[client]
port=3306
socket=/var/lib/mysql/mysql.sock
[mysql.server]
user=mysql
basedir=/usr/local
[mysql_cluster]
# IP address of the cluster management node
ndb-connectstring=10.253.191.x
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

Save and close the file.

8. You can also include MySQL directories in your path (Optional).
# PATH=$PATH:/usr/local/mysql/bin:/usr/local/mysql/libexec
# export PATH

9. Start MySQL Server now:
# /etc/init.d/mysql.server start

10. Repeat these steps in node 2 and start MySQL on both nodes. MySQL should start without any complain. You should also update the password for root user.

Test the cluster:

1. Focus again on Management node to have a look of Cluster connectivity. Open the ndb cluster management console. You should add this directory in PATH or can copy files to your system bin. (I’m a bit lazy ;)
# /usr/src/mysql-5.1.26-rc/storage/ndb/src/mgmclient/ndb_mgm
– NDB Cluster — Management Client –

2. Issue command to view status of cluster:
ndb_mgm> show;
Connected to Management Server at: localhost:1186
Cluster Configuration
———————
[ndbd(NDB)] 2 node(s)
id=2 @10.254.237.x (Version: 5.1.26, Nodegroup: 0, Master)
id=3 @10.251.74.x (Version: 5.1.26, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1 @10.252.169.x (Version: 5.1.26)

[mysqld(API)] 2 node(s)
id=4 @10.254.237.x (Version: 5.1.26)
id=5 @10.251.74.x (Version: 5.1.26)
ndb_mgm> quit

Everything should run fine.

3. Jump on the node 1 (or 2, doesnt matter in a cluster :) and try to create db, table and issue commands. BE SURE to use ENGINE=NDBCLUSTER while table creation else cluster will not work, means data will not be replicated throughtout cluster. Insert some records and check that on other node.

Conclusion:
It’s a basic test cluster and I would not reccommend it for any production use. In fact, as per one of MySQL expert, “I would advise you to consider if MySQL Cluster is really a right choice for your project, it’s often not, probably in 99.9% of the cases I encountered, and does not give expected results” and when asking the alternate, “usually some MySQL/InnoDB in Master/Master, Master/Slave setup can work well enough to handle very high rate of transactions.”

Of course, ther are several considerations you have to take care, like network connectivity between instanes, backup to S3 and automatic promotion of second master in case first one failed. I’m looking on these and as well as on to setup Master/Master replication with S3 backup. I’ll post that here, once done.

Blog Action Day

October 15th, 2009

The new post on climate change is up on All You Can Green. Just follow this link to read it.

Ruby + Thin + Camping : Serving static files with Thin vs. Camping’s work around.

March 31st, 2009

I have been working with camping for a while and I didnt like how it required me to write methods to handle my static files. Stumbling across some things I read about using “Thin” and “Rack” I was able to serve static files through thin server versus using the camping framework. The file I am using has a .ru extension rather than a .rb extension because it is a rack config file.

%w[ rubygems camping active_record camping/db camping/session reststop json active_support net/http rack ].each { |x| require x}

Camping.goes :Operator

#So after the Camping Instantiation I use this little piece of code to let thin handle the static files.
use Rack::Static, :urls => ["/static", "/images", "/css", "/javascripts"], :root => File.expand_path(File.dirname(__FILE__))

#All my Operator Code goes in here#

#Here us the end of my file. To start the Thin + Camping application.

Operator::Models::Base.establish_connection :adapter => ’sqlite3′, :database => ‘operator.db’
Operator::Models::Base.logger = Logger.new(‘operator.log’)
run Rack::Adapter::Camping.new(Operator)

now type: thin start -r ./myfile.ru

I hope this helps all who like to go camping but take the “Thin” path to get to where they are going.

Ruby + Soap4r : Complex headers

March 31st, 2009

I was was using Soap4r to talk to a Enterprise Messaging Bus and was able to come up with this to pass complex headers that were required by the Bus. So I am happy with my outcome. However this begs the question. “Why are we still using SOAP?”

require ’soap/header/simplehandler’

n = XSD::NS.new
n.assign(“soap”, “”)

class HeaderHandler < SOAP::Header::SimpleHandler
attr_accessor :value

def initialize(ns,tag)
super(XSD::QName.new(ns, tag))
@value = value
end

def on_simple_outbound
@value
end
End

h =
HeaderHandler.new(“http://service.asurion.com/schemas/MessageHeader/1.0.0“,
“MessageHeader”)
driver.headerhandler << h
h.value = {XSD::QName.new(“http://example.com/schemas/MessageHeader/1.0.0“,
“Context”) => {XSD::QName.new(“http://example.com/schemas/
exampleCanonicalModel/1.0.0″, “Culture”) => “en-US” ,
XSD::QName.new(“http://example.com/schemas/ exampleCanonicalModel/1.0.0″,
“TimeStamp”) => “2009-01-09T17:44:32.6441748Z”, XSD::QName.new(“http://
example.com/schemas/exampleCanonicalModel/1.0.0″, “Principal”) =>
{XSD::QName.new(“http://example.com/schemas/exampleCanonicalModel/1.0.0“,”Sy
stemUsername”) => “clientname”,
XSD::QName.new(“http://example.com/schemas/exampleCanonicalModel/1.0.0“,”Sys
temPassword”) => 55555555},
XSD::QName.new(“http://example.com/schemas/exampleCanonicalModel/1.0.0“,
“LineOfBusiness”) => “Handset”,
XSD::QName.new(“http://example.com/schemas/exampleCanonicalModel/1.0.0“,
“Application”) => “Aggregator”,
XSD::QName.new(“http://example.com/schemas/exampleCanonicalModel/1.0.0“,
“Client”) => “Google”,
XSD::QName.new(“http://example.com/schemas/exampleCanonicalModel/1.0.0“,
“Channel”) => “InStore”}}

###################################### Output of header from wiredump

<soap:Header>
<n1:MessageHeader
xmlns:n1=”http://example.com/schemas/MessageHeader/1.0.0
soap:mustUnderstand=”0″>
<n1:Context
xmlns:n2=”http://example.com/schemas/exampleCanonicalModel/1.0.0“>
<n2:LineOfBusiness>Handset</n2:LineOfBusiness>
<n2:Client>Google</n2:Client>
<n2:Channel>InStore</n2:Channel>
<n2:Application>Aggregator</n2:Application>
<n2:Principal>
<n2:SystemPassword>55555555</n2:SystemPassword>
<n2:SystemUsername>clientname</n2:SystemUsername>
</n2:Principal>
<n2:TimeStamp>2009-01-09T17:44:32.6441748Z</n2:TimeStamp>
<n2:Culture>en-US</n2:Culture>
</n1:Context>
</n1:MessageHeader>
</soap:Header>

Python + SOAPpy module

July 14th, 2008

I have been tinkering around with Python lately and have had a little trouble here and there. I first had a problem with installing the psycopg2 adapter for Postgres integration. come to find out that installing packages from macports is not always the best thing. So a simple “sudo port uninstall psycopg2” and then compile from binary fixed the problem.

Now I am wresteling with the SOAPpy install. It keeps giving me the error when building ”

Traceback (most recent call last):
File “setup.py”, line 8, in <module>
from SOAPpy.version import __version__
File “/Users/xrs/Downloads/SOAPpy-0.12.0/SOAPpy/__init__.py”, line 5, in <module>
from Client      import *
File “/Users/xrs/Downloads/SOAPpy-0.12.0/SOAPpy/Client.py”, line 46
from __future__ import nested_scopes
SyntaxError: from __future__ imports must occur at the beginning of the file

“. So after some reading and banging my head on the keyboard i found this handy article.

http://www.python.org/dev/peps/pep-0236/

Upon reading I found that in Python 2.5 wants all nested_scopes to be called at the beginning of the file and that only certain statements can be ahead of the import statement. So “yeah”, this is something a experienced Python programmer would have figured out in a couple of minutes. Oh well, just like with any other language you have to do some walking around in circles before you realize the end to the loop is to read the manual.

Flex Builder + Ubuntu

June 24th, 2008

So recently Adobe released its Flex Builder for Linux. After learning this the first thing that popped in my head is awesome I can figure out how to unsuccessfully install something after 10 tries again. So after fiddleing with Flex Builder for about 30 minutes I got it installed. Heres what I had to do.

First check your system for the necessities needed for  the Flex Builder Eclipse Plugin to work

Linux Header (linux-headers-2.6.24-19-generic)

sudo apt-get install linux-headers-2.6.24-16-generic

Eclipse Classic 3.3.2

wget http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.3.2-200802211800/eclipse-SDK-3.3.2-linux-gtk.tar.gz

tar xzvf eclipse-SDK-3.3.2-linux-gtk.tar.gz

this should give you a directory called eclipse. I moved mine to my home directory.

mv ./eclipse /home/<username>/

(this will come in handy during the installation process.)

Java JRE 1.5

I had to use 1.5 otherwise Flex Builder would not install

–minimum install

sudo apt-get install sun-java5-jre

– what I did

sudo apt-get install sun-java5-jre sun-java5-plugin sun-java5-bin sun-java5-fonts

after installing java you have to tell Ubuntu what version of Java you want to use

sudo update-alternatives –config java

There are 4 alternatives which provide `java’.

Selection    Alternative
———————————————–
1    /usr/bin/gij-4.2
+        2    /usr/lib/jvm/java-gcj/jre/bin/java
3    /usr/lib/jvm/java-6-sun/jre/bin/java
*         4    /usr/lib/jvm/java-1.5.0-sun/jre/bin/java

Press enter to keep the default[*], or type selection number:

select java-1.5.0, in my case #4

Next Download the flex builder.

wget http://download.macromedia.com/pub/labs/flex/flexbuilder_linux/flexbuilder_linux_install_a3_033108.bin

The INSTALL file will tell you to make the bin file executable (chmod +x) but I didn’t feel like it. So I just did the following

sh ./flexbuilder_linux_install_a3_033108.bin

and so the adobe installer begins.

The installer will ask you where you want to put “Adobe_Flex_Builder_Linux” directory

/home/<username>/Adobe_Flex_Builder_Linux

ehhhh why not.

Next the installer will ask you to select you current eclipse directory. (remember from earlier?)

/home/<username>/eclipse

after hitting next it should install the flex builder without any errors. If you do get errors I would sugget “sudo su -” then running the .bin file again. Pay attention to the paths of the Adobe_Flex_Builder_Linux directory creation.

Well I hope this helps those out there who love Ubuntu, but sometimes get exhausted with always having to configure 5 other things before they can use the program they want.

little knight

March 14th, 2008

Blogged with the Flock Browser

Chicken Little

March 5th, 2008

My little boy in his halloween costume….

Blogged with the Flock Browser

Super Songer Family

March 5th, 2008

So this is a little glimpse of what really goes on in my head while everyone else is talking about something important.

Super Songer Family

Canadian Mouse

March 5th, 2008

This Drawing was inspired by a character that Katie’s seven year old cousin imagined.
Canadian Mouse