Download

Download release 0.11.0.0 from [https://kafka.apache.org/downloads]. Unzip it.

Start ZooKeeper

ZooKeeper is included in the above package. See ROOT\libs\zookeeper-3.4.6.jar.

> .\bin\windows\zookeeper-server-start.bat config\zookeeper.properties

Start Kafka

bin\windows\kafka-server-start.bat config\server.properties

Create a topic

 bin\windows\kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
 Created topic "test".

List topics bin\windows\kafka-topics.bat --list --zookeeper localhost:2181

Send a message

λ bin\windows\kafka-console-producer.bat --broker-list localhost:9092 --topic test
>This is a test message
>This is another test message

Start a consumer

bin\windows\kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning

Setting up a multi-broker cluster

Edit the new configuration files

copy config\server.properties config\server-1.properties
copy config\server.properties config\server-2.properties

config/server-1.properties
  broker.id=1
  listeners=PLAINTEXT://:9093
  log.dir=/tmp/kafka-log-1

config/server-2.properties
  broker.id=2
  listeners=PLAINTEXT://:9094
  log.dir=/tmp/kafka-log-2

Note: For log.dir, use Linux style path.

Start server-1 and server-2

bin\windows\kafka-server-start.bat config\server-1.properties
bin\windows\kafka-server-start.bat config\server-2.properties

Create a topic

λ bin\windows\kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 3 --partitions 1 --topic my-replica
ted-topic
Created topic "my-replicated-topic".

Describe a topic

λ bin\windows\kafka-topics.bat --describe --zookeeper localhost:2181 --topic my-replicated-topic
Topic:my-replicated-topic       PartitionCount:1        ReplicationFactor:3     Configs:
        Topic: my-replicated-topic      Partition: 0    Leader: 2       Replicas: 2,0,1 Isr: 2,0,1

Note: If you kill one node, you will notice a difference in Isr: 2,0,1

Why am I getting this?

  1. Get the SQL query by enable DEBUG log level on hibernate (org.hibernate). In my case, it looks like,
SELECT ...
FROM table_name fetch first ? rows only;
  1. Test this query in SQL developer (or other tools). You will likely get the same error.

In my case, the problem is featch first ? rows only. This is a feature available to Oracle 12g+.

How can I solve it?

If your database is on a lower version, it should use ROWNUM to limit the result.

SELECT *
FROM   (SELECT ...
        FROM table_name)
WHERE  ROWNUM <= ?

Change jpa.database-platform to org.hibernate.dialect.Oracle10gDialect will produce the above query.

How to check the database version?

Try

SELECT version FROM V$INSTANCE;
// OR
SELECT * FROM V$VERSION

How can I know which tablespace is MY default tablespace?

select * from DBA_USERS where USERNAME='MyADP';`

Note: Not all users can do this. If your user does not have access to DBA_USERS, you may get

ORA-00942: table or view does not exist
00942. 00000 -  "table or view does not exist"
*Cause:
*Action:
Error at Line: 48 Column: 15

Where is this specified?

When you create a new user, you can optionally specify the default tablespace and default temporary tablespace for any objects created by that user. For example

CREATE USER phil IDENTIFIED BY s3cr3t
      DEFAULT TABLESPACE philtablespace
      TEMPORARY TABLESPACE philtemp;

If you omit the clauses when creating the user, the user will inherit the database default values. These can be queried as follows:

SELECT *
  FROM DATABASE_PROPERTIES
  WHERE PROPERTY_NAME LIKE `DEFAULT%TABLESPACE`

You would then get something like:

PROPERTY_NAME                 PROPERTY_VALUE    DESCRIPTION
DEFAULT_PERMANENT_TABLESPACE	SYSTEM	          Default Permanent Tablespace ID
DEFAULT_TEMP_TABLESPACE	      TEMP	            ID of default temporary tablespace

More information see here on stackexchange.

Dockerfile

Jekyll is based on ruby, so we build our image based on the ruby image.

FROM ruby
MAINTAINER eagle.xiao@gmail.com

Some gems requires a Javascript runtime, so we need to install node and python-pygments is required for syntax highlighting.

RUN apt-get update
RUN apt-get install -y node python-pygments

The jekyll gem. Bundler is required if you have your own Gemfile in the folder.

RUN gem install jekyll bundler

Map a folder from host to /src in the container and expose 4000

VOLUME /src
EXPOSE 4000

Setup working dir.

WORKDIR /src

Ideally, we should run bundle install first and then have the ENTRYPOINT to be ENTRYPOINT ["jekyll"]. I don’t know how to do it that way. (CMD?)

ENTRYPOINT bundle install && jekyll serve -H 0.0.0.0

Build the docker image

Change directory into where the Dockerfile is stored. Do not miss the “.” a the end.

docker build -t mrcoder/jekyll .

Clone theme

I use a theme forked from here. Simply clone it locally:

git clone https://github.com/mmistakes/hpstr-jekyll-theme.git

Run the Docker image

docker run --rm -v "$PWD:/src" -p 4000:4000 mrcoder/jekyll

If you are running it with boot2docker, you need to find out the ip of the docker host with boot2docker ip and open the site with http://ip-of-the-host:4000.

When I read the README of Flux, I found it difficult to get the point of the following section:

We originally set out to deal correctly with derived data: for example, we wanted to show an unread count for message threads while another view showed a list of threads, with the unread ones highlighted. This was difficult to handle with MVC — marking a single thread as read would update the thread model, and then also need to update the unread count model. These dependencies and cascading updates often occur in a large MVC application, leading to a tangled weave of data flow and unpredictable results.

Seriously, why it is “difficult to handle with MVC”?

While different people have different understand of the old MVC, the typical structure looks like V to C has a 1 to 1 map and M to V/C has a 1 to many map. It works so good if the structure make sense. What makes it difficult is actually when you want to have a 1 to 1 map for M to V/C and all the Ms needs a machanism to be kept synced.

Say, for example, we have only one model for the two views - “an unread count for message threads” and “a list of threads, with unread ones highlighted”. It is not SO difficult because when makring a single thread as read we can update the only one model, and it will not lead to “a tangled weave of data flow” or unpredictable results”.

Hmm, so why will one want to MAKE it difficult?

No, noboday want to make it difficult. Just by have two separate models for the two views make it a lot simple to understand. Yes, we just want to make it SIMPLE rather than DIFFICULT. In the following diagram, Controller disappears (sort of merged into View), Store is nothing more than Model.

However, we need a machanism to keep the two models synced. We have tones of ways to - create reference between each other, having another model refer to them, event-based synchorization, etc. We will discuss two options below.

Option 1: Refer to unreadCountModel from threadModel

Suppose there is not message bus (Dispatcher). The views listen to stores and stores listens to action creators. (Note, there other way to do so, for example update Views via Controller, but the point here is to show the complexity for populating changes across models).

// in threadModel
...
var unreadCountModel = unreadCountModel();

return {
    setAsRead: function(id) {
            _.forEach(threadArray, function(thread) {
                if (thread.id === id) {
                thread.read = true;
            }
        })
        updateUnreadCountModel();
    },
    updateUnreadCountModel: function () {
        var unreadCount = _.filter(threadArray, function(thread) {return !thread.read;}).size();
        unreadCountModel.setUnreadNumber(unreadCount);
    }
}
...

It is not SO difficult, but it would be more tricky if within setUnreadNumber, we need to update the threadModel - typical circel dependency problem.

Option 2: Dispatcher

Of course, we will spend some time explaining how Dispatcher can address this problem.

// in threadModel
onAction: function(action) {
    if (action.type === 'MARK_AS_READ') {
            _.forEach(threadArray, function(thread) {
                if (thread.id === action.payload.id) {
                thread.read = true;
            }
    }
}

// in unreadCountModel
onAction: function(action) {
    if (action.type === 'MARK_AS_READ') {
        unreadCount = _.filter(threadArray, function(thread) {return !thread.read;}).size();
    }
}

Conclusion

While we have been told that Model is stable than View, we have to acknowledge that some models are ViewModels. It is equally likely to change. Having a 1 to 1 map between Model and View makes more sense.

Technically speaking, Dispatcher is a singleton object which in OOD is a smell. However, I do not see a problem here. It just simplies the design. It works like a message bus and it should be a singleton, right?