ในบทเรียนนี้ เราจะเรียนรู้วิธีการ implement ระบบ Redis pub/sub โดยใช้ library Jedis
Jedis Library
Jedis เป็น Java client library สำหรับ Redis datastore มีขนาดเล็ก ใช้งานง่าย และรองรับ Redis 2.8.x, 3.x.x และขึ้นไปอย่างเต็มที่
ระบบ Redis Pub/Sub
Redis นำรูปแบบ messaging paradigm Publish/Subscribe มาใช้ ผู้ส่ง (publisher) ไม่ได้ส่งข้อความโดยตรงไปยังผู้รับ (subscriber) แต่เผยแพร่ (publish) ข้อความไปยัง channel เฉพาะ ผู้รับที่ต้องการรับข้อความจะสมัครรับ (subscribe) จาก channel หนึ่งหรือหลายรายการ และจะได้รับข้อความที่เผยแพร่ไปยัง channel เหล่านั้นเท่านั้น
Project Setup
สร้าง Maven project แบบง่ายใน IDE ที่ชอบ และเพิ่ม dependency ต่อไปนี้ใน pom.xml:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.0.1</version> </dependency>
Redis Installation
ต้องติดตั้ง Redis เวอร์ชันล่าสุด
Jedis Connection
สร้าง object ของ Jedis (redis.clients.jedis.Jedis) เพื่อเชื่อมต่อ Java code กับ Redis:
Jedis jedis = new Jedis();
หากรัน Redis service บน local machine และ port เริ่มต้น (6379) default constructor จะทำงานได้เลย มิฉะนั้นต้องส่ง host url และ port number ที่ถูกต้องเข้าไปใน constructor
Subscribe To Channels
สร้าง class "ChannelSubscribe" จะสมัครรับ channel C1 และ C2 โดยสร้าง client ที่จะรับข้อความเมื่อ client อื่น publish ข้อความไปยัง channel C1 หรือ C2
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class ChannelSubscribe {
public static void main(String[] args) {
Jedis jedis = null;
try {
jedis = new Jedis();
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println("Channel " + channel + " has sent a message : " + message );
if(channel.equals("C1")) {
unsubscribe(channel);
}
}
@Override
public void onSubscribe(String channel, int subscribedChannels) {
System.out.println("Client is Subscribed to channel : "+ channel);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of channels");
}
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
System.out.println("Client is Unsubscribed from channel : "+ channel);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of channels");
}
};
jedis.subscribe(jedisPubSub, "C1", "C2");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
Output
เมื่อรัน class "ChannelSubscribe" output จะเป็นดังนี้:

Publish To Channels
สร้าง class "ChannelPublish" จะเชื่อมต่อ Redis server ด้วย jedis และ publish ข้อความ 2 ข้อความแต่ละอันไปยัง channel C1 และ C2
import redis.clients.jedis.Jedis;
public class ChannelPublish {
public static void main(String[] args) {
Jedis jedis = null;
try {
jedis = new Jedis();
jedis.publish("C1", "First message to channel C1");
jedis.publish("C2", "First message to channel C2");
jedis.publish("C1", "Second message to channel C1");
jedis.publish("C2", "Second message to channel C2");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
Output
เมื่อรัน class "ChannelPublish" output ใน console ChannelSubscribe จะเป็นดังนี้:

Subscribe To Patterns
สร้าง class "PatternSubscribe" จะสมัครรับ pattern C* และ D? โดยสร้าง client
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class PatternSubscribe {
public static void main(String[] args) {
Jedis jedis = null;
try {
jedis = new Jedis();
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onPMessage(String pattern, String channel, String message) {
System.out.println("Channel " +channel+ " has sent a message : " +message+ " on pattern " + pattern);
if(pattern.equals("C*")) {
punsubscribe(pattern);
}
}
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
System.out.println("Client is Subscribed to pattern : "+ pattern);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of patterns");
}
@Override
public void onPUnsubscribe(String pattern, int subscribedChannels) {
System.out.println("Client is Unsubscribed from pattern : "+ pattern);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of patterns");
}
};
jedis.psubscribe(jedisPubSub, "C*", "D?");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
Output
เมื่อรัน class "PatternSubscribe" output จะเป็นดังนี้:

Publish To Patterns
สร้าง class "PatternPublish" จะเชื่อมต่อ Redis server และ publish ข้อความไปยัง channel C13, D2, C134, และ D3
import redis.clients.jedis.Jedis;
public class PatternPublish {
public static void main(String[] args) {
Jedis jedis = null;
try {
jedis = new Jedis();
jedis.publish("C13", "Message to channel C13");
jedis.publish("D2", "Message to channel D2");
jedis.publish("C134", "Message to channel C134");
jedis.publish("D3", "Message to channel D3");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
Output
เมื่อรัน class "PatternPublish" output ใน console PatternSubscribe จะเป็นดังนี้:

อ้างอิง
- Pub Sub Command Docs
ขอจบบทเรียนสำหรับวิธี implement Redis pub/sub system โดยใช้ Jedis library หากชอบบทเรียนนี้ กรุณาแบ่งปันความคิดเห็นและแชร์ให้ผู้อื่นด้วยครับ