interprocess communication and clustering for a chat with redis and socket.io

I'm creating an advanced chat system with nodejs, socket.io and redis. The goal is to have a chat system where one joint chat room is for all users but with an extra possibility to get a private chat with a stuff for one-to-one support.

my app.js looks like the following:

/********************************** Required **********************************/ 
var express = require('express')
  , app = express()
  , http = require('http')
  , server = http.createServer(app)
  , io = require('socket.io').listen(server);

var cluster = require('cluster')
  , http = require('http')
  , numCPUs = require('os').cpus().length;

  /* this is for redis integration */
var redis =  require('redis')
  , RedisStore =  require('socket.io/lib/stores/redis')
  , pub  = redis.createClient()
  , sub  = redis.createClient()
  , client  = redis.createClient();

io.set('store', new RedisStore({
    redisPub: pub,
    redisSub: sub,
    redisClient: client
}));
/********************************** Required **********************************/ 


/********************************** Objects **********************************/ 

function User(socketID, username, role) {
    var _socketID = socketID;
    var _username = username;
    var _role = role;
    var _userObjectList = null;

    console.log('user is being created');

    this.getSocketID = function() {
        return _socketID;
    }

    this.getUsername = function() {
        return _username;
    }

    this.getRole = function() {
        return _role;
    }

    this.setRole = function(role) {
        _role = role;
        _userObjectList = new Array();
    }

    this.addUser = function(userObject) {
        _userObjectList[userObject.getUsername()] = userObject;
    }

    this.getUserCount = function() {
        if(_role != Roles.staff)
            return -1;
        return Object.keys(_userObjectList).length; 
    }
}

/********************************** Objects **********************************/ 


/********************************** Static Variables **********************************/ 

function Roles() {
}

Roles.user = "user";
Roles.staff = "staff";

/********************************** Static Variables **********************************/ 


/********************************** Variables **********************************/ 

// usernames which are currently connected to the chat
var usernames = {};
var staff = {};
var socketIDList = {};
var users = new Array();

/********************************** Variables **********************************/ 


/********************************** Functions **********************************/ 
function getUsernames() {
    return Object.keys(users);
}

function getStaffObjects() {
    var objects = new Array();
    console.log('getting users ' + Object.keys(users));
    for (key in users) {
        console.log('testing if ' + key + ' is a staff member');
        if(users[key].getRole() == Roles.staff) {
            console.log(key + ' is a staff member');
            objects[key]=users[key];
        }
    }
    return objects;
}

function isValidUsername(username) {
    if(username == null)
        return false;
    var validation = /^[a-zA-Z]\w{2,20}/g;
    return validation.test(username);   
}

/********************************** Functions **********************************/ 



/********************************** Cluster **********************************/ 

if (cluster.isMaster) {
  server.listen(8080);
  console.log('listening now');

  // Fork workers.
  console.log('i am the master');
  for (var i = 0; i < numCPUs; i++) {
    console.log('forking cluster node ' + i);
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  // Workers can share any TCP connection
  // In this case its a HTTP server
  console.log('i am worker #' + cluster.worker.id);
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}

/********************************** Cluster **********************************/  


// routing
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});




io.sockets.on('connection', function (socket) {

  // when the client emits 'sendchat', this listens and executes
  socket.on('sendchat', function (data) {
    // we tell the client to execute 'updatechat' with 2 parameters
    io.sockets.emit('updatechat', socket.username, data);
  });

  socket.on('pm', function(to, message) {
    var id = users[to].getSocketID();
    io.sockets.socket(id).emit('updatePrivateChat', socket.username, message);
  });

  socket.on('staffMessage', function(to, message) {
    console.log("message to " + to + ": " + message);
    var id = users[to].getSocketID();
    io.sockets.socket(id).emit('updateStaffChat', socket.username, message);
  });


  // when the client emits 'adduser', this listens and executes
  socket.on('adduser', function(username){
    if(isValidUsername(username) && users[username] == null){ // user does not already exist
        // we store the username in the socket session for this client
        socket.username = username;
        // add the client's username to the global list
        users[username] = new User(socket.id, socket.username, Roles.user);
        console.log('added user ' + username + '. now we have ' + Object.keys(users).length + " users");
        // echo to client they've connected
        socket.emit('updatechat', 'SERVER', 'you have connected');
        // echo globally (all clients) that a person has connected
        socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has connected');
        // update the list of users in chat, client-side
        io.sockets.emit('updateusers', getUsernames());
    }
    else{
        socket.emit('usernameExists', username);
    }

  });

  // when the user wants to chat with staff
  socket.on('contactStaff', function(){

    /***************** search for a free staff ***************/
    var member = null;
    console.log('user ' + users[socket.username].getUsername() + ' wants to contact staff');
    var staffList = getStaffObjects();
    if(Object.keys(staffList).length == 0)
        console.log('error. no staff available');
    else {
        var staffNumber = Math.floor(Math.random() * (Object.keys(staffList).length-1));
        var i = 0;

        console.log("StaffList Length: " + Object.keys(staffList).length);
        for(key in staffList) {
            if(i == staffNumber) {
                member = staffList[key]
                staffname = member.getUsername();
                break;
            }
            i++;
        }
        console.log('adding ' + socket.username + ' to ' + member.getUsername());
        member.addUser(users[socket.username]);
        console.log('new contact for staff member. ' + member.getUsername() + ' has now ' + member.getUserCount() + ' contacts');

        console.log('staffFound: ' + member.getUsername() + ", user: " + socket.username);
        io.sockets.socket(users[socket.username].getSocketID()).emit('staffFound', member.getUsername());
        io.sockets.socket(users[socket.username].getSocketID()).emit('updateStaffChat', member.getUsername(), "Sie haben einen Mitarbeiter kontaktiert. Was kann ich für Sie tun?");
        io.sockets.socket(member.getSocketID()).emit('staffFound', socket.username);
        io.sockets.socket(member.getSocketID()).emit('updateStaffChat', socket.username, "Sie wurden von dem Benutzer " + socket.username + " kontaktiert");
    }      


  });

  // register a staff member
  socket.on('registerAsStaff', function(password){
    if(password != "abc")
        return false;

    var staffname = socket.username;

    users[socket.username].setRole(Roles.staff);
    console.log('new staff member: ' + socket.username + " with role: " + users[socket.username].getRole());
  });


  // when the user disconnects.. perform this
  socket.on('disconnect', function(){
    // remove the username from global usernames list
    users[socket.username] = null;
    delete users[socket.username];
    // update list of users in chat, client-side
    io.sockets.emit('updateusers', usernames);
    // echo globally that this client has left
    socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
  });
});

My problem: The chat ist working. Clustering itself is working, but of cause I need a correct redis integration. Could anyone help me on how to do that? Is my solution in general a performant solution for a big amount of clients (max. 1000-2000 in the first step)? - I know I will have to benchmark testing and so on, but is there anything you see that would prevent me from doing that?

I also need a solution to have multiple instances lateron. I found that description on http://blog.cloudfoundry.com/2013/01/24/scaling-real-time-apps-on-cloud-foundry-using-node-js-and-redis/. I understand the problem of socket.io with multiple instances, but I don't understand the implementation. Could anybody please provide a short example on how to do this?