http://blog.csdn.net/canot/article/details/52040415
About the individual's understanding of the pub/sub mechanism provided by Redis in the previous blog, it also mentions the idea of how to avoid one of the biggest flaws in Redis's pub/sub-The Persistence of messages (http://blog.csdn.net/canot/ article/details/51975566). This article is primarily about the code implementation of its ideas (Redis's pub/sub message persistence):
The implementation of the most core listener in the PUB/SUB mechanism:
Import Redis.clients.jedis.Jedis;Import Redis.clients.jedis.JedisPubSub;Import Redis.clients.util.RedisInputStream;PublicClassPubsublistenerExtendsjedispubsub {Private String clientId;Private Handlerredis Handlerredis;An ID must be created when generating the PubsublistenerPublicPubsublistener (String cliendid, Jedis Jedis) {This.clientid = Cliendid; Jedis.auth ("XXXX"); Handlerredis =New Handlerredis (Jedis); }@OverridePublicvoidOnMessage (String channel, String message) {if ("Quit". Equals (message)) {This.unsubscribe (channel); } handlerredis.handler (channel, message); }Really deal with the place of acceptancePrivatevoidMessage (string channel, String message) {SYSTEM.OUT.PRINTLN ("Message receive:" + Message +", Channel:" + Channel +"..."); }@OverridePublicvoidOnpmessage (string pattern, string channel, String message) {TODO auto-generated Method Stub}@OverridePublicvoidOnsubscribe (String Channel,int subscribedchannels) {Save subscribers in a "subscription active collection" Handlerredis.subscribe (channel); System.out.println ("Subscribe:" + channel);@OverridePublicvoidOnunsubscribe (String Channel,int subscribedchannels) {handlerredis.ubsubscribe (channel); System.out.println ("Unsubscribe:" + channel);@OverridePublicvoidOnpunsubscribe (String pattern,int subscribedchannels) {TODO auto-generated Method Stub}@OverridePublicvoidOnpsubscribe (String pattern,int subscribedchannels) {TODO auto-generated Method Stub} class Handlerredis {Private Jedis Jedis;PublicHandlerredis (Jedis Jedis) {This.jedis = Jedis; }PublicvoidHandler (string channel, String message) {int index = Message.indexof ("/");if (Index <0) {Message not valid, discardReturn } Long Txid = long.valueof (message.substring (0, index)); String key = ClientId +"/" + channel;while (true) {String LM = Jedis.lindex (Key,0);Get the first messageif (lm = =NULL) {Break }int li = Lm.indexof ("/");If the message is not valid, delete and processif (Li <0) {String result = Jedis.lpop (key);Delete current Messageis emptyif (result = =NULL) {Break } message (channel, LM);Continue } Long Lxid = long.valueof (lm.substring (0, Li));Get the Txid of a messageResidual messages before direct consumption of TXIDif (Txid >= lxid) {jedis.lpop (key);Deletes the current message message (channel, LM);Continue }else {Break } } }Persistent subscription operationsPublicvoid Subscribe (string channel) { //ensures that the format in the Subscriber collection is a unique identifier/subscribed channel String key = ClientId + "/" + channel; //Determine if the client exists in the collection in boolean isexist = Jedis.sismember ("persis_sub", key); if (!isexist) { //does not exist add Jedis.sadd ("persis_sub", Key);}} public void ubsubscribe (String channel) {string key = ClientId + "/" + channel; //Jedis.srem ("persis_sub", key) from the "Active Subscribers" collection; //delete "subscriber Message queue" Jedis.del (channel);} }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21st
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
An inner class Handlerredis is defined in listener. The Listener class delivers onmessage and Onsubscribe two methods to Handlerredis. Handler handles this method in the same way that the queue is maintained. A message () method is defined in the Listener class, which is the handler callback method, where the message is actually processed.
The subscription client class for the channel:
import Redis.clients.jedis.jedis;public class subclient {private Jedis Jedis; private Pubsublistener listener; public subclient (String host,pubsublistener PubSubListener) { Jedis = new Jedis (host), Jedis.auth ( "XXXXX"); this.listener = Pubsublistener; } public void sub (String channel) { Jedis.subscribe (listener, channel); } public void unsubscribe (String Channel) {listener.unsubscribe (channel);}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21st
- 22
The channel's message is published by the client:
Import Java.util.Set;Import Redis.clients.jedis.Jedis;PublicClasspubclient {Private Jedis Jedis;PublicPubclient (String host) {Jedis =New Jedis (host); Jedis.auth ("wx950709"); }/** * Every message that is published needs to be persisted in subscriber Message Queuing * *@param message * *PublicvoidPut (String message) {Get all active message receiver clients clientid/channel set<string> subclients = jedis.smembers ("Persis_sub");for (String subs:subclients) {//saves each client's message Jedis.rpush (Subs, message); }} public void publish (String Channel, String message) {//each message has a globally unique ID // Txid to prevent the subscriber from "disorderly ordering" during data processing, this requires the subscriber to parse the MESSAGE Long Txid = jedis.incr ( "Message_txid"); String content = Txid + "/" + message; this.put (content); Jedis.publish (channel, content); //set ID for each message, final message format 1000/messagecontent} public void close (String channel) { Jedis.publish (channel,
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21st
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
To test the boot class:
Import Redis.clients.jedis.Jedis;PublicClassMain {PublicStaticvoidMain (string[] args)Throws exception{pubclient pubclient =New Pubclient ("127.0.0.1");Final String channel ="Pubsub-channel222"; Pubsublistener listener =New Pubsublistener ("Client_one",new Jedis ( "127.0.0.1")); Subclient subclient = new subclient ( "127.0.0.1", listener); Thread T1 = new Thread (new Runnable () { @Override public void run () {//at the API level, this is a polling operation and will not return unsubscribe until Subclient.sub is called ( Channel); } }); T1.setdaemon (true); T1.start (); int i = 0; while (i < 2) {Pubclient.publish (channel, " "Message" +i); i++; Thread.Sleep (1000);}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21st
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
"Go" uses Redis's pub/sub to implement JMS-like message persistence