After learning Redis as a message queue, we studied the functions of Redis chat.
In fact, with a relational database can also realize the message function, I have been using MySQL to write a simple message function. The RDB idea is as follows:
* * In the actual use of the MySQL database can be fully implemented chat function, set up a table, save the recipient's username, message, isconsumed and other information, the user login after using the heartbeat mechanism to constantly detect the database and consumption of messages. Heartbeat can do a lot of things, such as detection of whether the current user is logged in, if you have logged in to remove the user before the implementation of a user logon function. The heartbeat can use JS's periodic function to continue to start the asynchronous request back to the table, the background query messages without messages * *
The 1.Redis enables one-to-one chat features (implementation based on Lpush and Brpop)
Simple implementation of a user to another user to send multiple messages, the idea is:
One-on-one chat ideas: (implemented with Lpush and Brpop)
1. Message producers produce messages to Redis: When a message is produced, it is sent to the corresponding key based on the username of the recipient and the type of message, using Lpush to send the message (generated by username key)
2. The consumer of the message consumes the corresponding message from the username key, according to username. If necessary, you can write the message to an RDB to avoid data loss. (Get the message from the user based on the rule username generated key)
3. The contents of the message header to the sender, such as the original message content is: Hello, in order to know that the sender of the message can be changed to: Zhang San *-*hello (in order to obtain the sender of the message)
Directly below the code:
User.java (only one username useful)
PackageCn.xm.jwxt.bean.system;Importjava.util.List;ImportJava.util.Set; Public classUser { PrivateString username;//User name PublicString GetUserName () {returnusername; } Public voidSetusername (String username) { This. Username = Username = =NULL?NULL: Username.trim (); }}
Redis-chat.properties
redis.url=127.0.0.1redis.port=6379redis.maxidle=30redis.minidle=10 Redis.maxtotal=100redis.maxwait=20000
Jedis Tool Class: (Return to Jedis connection)
PackageCn.xm.redisChat.util;ImportRedis.clients.jedis.Jedis;ImportRedis.clients.jedis.JedisPool;ImportRedis.clients.jedis.JedisPoolConfig;Importjava.io.IOException;ImportJava.io.InputStream;Importjava.util.Properties;/*** @Author: QLQ * @Description * @Date: 21:32 2018/10/9*/ Public classJedispoolutils {Private StaticJedispool pool =NULL; Static { //Load configuration fileInputStream in = Jedispoolutils.class. getClassLoader (). getResourceAsStream ("Redis-chat.properties"); Properties Pro=NewProperties (); Try{pro.load (in); } Catch(IOException e) {e.printstacktrace (); } //Get Pool ObjectJedispoolconfig Poolconfig =NewJedispoolconfig (); Poolconfig.setmaxidle (Integer.parseint (Pro.get ("Redis.maxidle"). ToString ()));//Maximum Idle CountPoolconfig.setmaxwaitmillis (Integer.parseint (Pro.get ("redis.maxwait"). ToString ()));//Maximum Idle CountPoolconfig.setminidle (Integer.parseint (Pro.get ("Redis.minidle"). ToString ()));//minimum number of idlePoolconfig.setmaxtotal (Integer.parseint (Pro.get ("Redis.maxtotal"). ToString ()));//Maximum number of connectionsPool =NewJedispool (Poolconfig, Pro.getproperty ("Redis.url"), Integer.parseint (Pro.get ("Redis.port"). toString ())); } //ways to get Jedis resources Public StaticJedis Getjedis () {returnPool.getresource (); }}
Message producer: (Processes the message header plus the sender of the message and generates key based on the recipient's username)
PackageCn.xm.redisChat.one2one;ImportCn.xm.jwxt.bean.system.User;Importcn.xm.redisChat.util.JedisPoolUtils;ImportOrg.slf4j.Logger;Importorg.slf4j.LoggerFactory;ImportRedis.clients.jedis.Jedis;/*** @Author: QLQ * @Description message producer (according to the message) * @Date: 23:02 2018/10/13*/ Public classRedismessageproducer {Private Static FinalLogger log = Loggerfactory.getlogger (redismessageproducer.class); /*** How to send a message * *@paramSenduser The user who sent the message *@paramSendtouser The user who received the message *@parammessages variable parameter return multiple messages *@return */ Public Static BooleansendMessage (user senduser, user sendtouser, String ... messages) {Jedis Jedis=Jedispoolutils.getjedis (); Try{String key= Sendtouser.getusername () + ": Msg"; //The content of the message plus the sender of the message is split with *-* and cannot be enhanced for loop for(inti = 0, length_1 = messages.length; i < length_1; i++) {Messages[i]= Senduser.getusername () + "*-*" +Messages[i]; } Long Lpush= Jedis.lpush (key, messages);//The return value is how many messages are still not consumedLog.debug ("User {} send message [{}] to {}", Senduser.getusername (), Messages, Sendtouser.getusername ()); Log.debug ("User {} has {} messages", Sendtouser.getusername (), Lpush); } Catch(Exception e) {log.error ("SendMessage Error", E); } finally{jedis.close (); } return true; }}
Message consumers: (using the thread pool to get the message, according to receive the message username from the corresponding key to get the corresponding message, and resolve the message key and sender and content)
PackageCn.xm.redisChat.one2one;ImportCn.xm.jwxt.bean.system.User;Importcn.xm.redisChat.util.JedisPoolUtils;ImportOrg.slf4j.Logger;Importorg.slf4j.LoggerFactory;ImportRedis.clients.jedis.Jedis;Importjava.util.List;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;ImportJava.util.concurrent.ScheduledExecutorService;ImportJava.util.concurrent.TimeUnit;/*** @Author: QLQ * @Description Message consumer * @Date: 23:44 2018/10/13*/ Public classRedismessageconsumer {Private Static FinalLogger log = Loggerfactory.getlogger (Redismessageconsumer.class); /*** parameter is the size of the initialized thread pool*/ Private Static FinalScheduledexecutorservice Batchtaskpool = Executors.newscheduledthreadpool (2); /*** Consumer News * *@paramConsumeruser The user receiving the message*/ Public Static voidConsumermessage (FinalUser Consumeruser) { FinalJedis Jedis =Jedispoolutils.getjedis (); //creates a new thread, and the threads pool gets the messageRunnable Runnable =NewRunnable () {@Override Public voidrun () { while(true) {List<String> messages = Jedis.brpop (0, Consumeruser.getusername () + ": Msg");//0 is timeout, return a collection, the first is the message key, the second is the content of the messageString key = Messages.get (0);//The first one is key .String message = Messages.get (1);//the second one is the message .String sendusername = message.substring (0, Message.indexof ("*-*"));//gets the sender of the messageMessage = Message.substring (Message.indexof ("*-*") +3);//Get message contentLog.debug ("ThreadName is {},user {} consumer message {}, sended by {}", Thread.CurrentThread (). GetName (), Consumeruser.getusername (), message, sendusername); } } }; //getting messages in the thread pool//The first parameter is the task that needs to be performed, the second parameter is the first delay time, the third parameter is the interval of two executions, and the fourth parameter is the unit of timeBatchtaskpool.schedulewithfixeddelay (runnable, 3,5, Timeunit.seconds); }}
Test class: (Lisi and WANGWU consumer messages)
PackageCn.xm.redisChat.one2one;ImportCn.xm.jwxt.bean.system.User;/*** @Author: QLQ * @Description message * @Date: 0:04 2018/10/14*/ Public classConsumermessageapp { Public Static voidMain (string[] args) {User Sndtouser=NewUser (); Sndtouser.setusername ("Lisi"); User SndToUser2=NewUser (); Sndtouser2.setusername ("Wangwu"); Redismessageconsumer.consumermessage (Sndtouser); Redismessageconsumer.consumermessage (SNDTOUSER2); }}
Zhangsan sending messages to Lisi and WANGWU
PackageCn.xm.redisChat.one2one;ImportCn.xm.jwxt.bean.system.User;/*** @Author: QLQ * @Description production message Test * @Date: 23:59 2018/10/13*/ Public classProducermessageapp { Public Static voidMain (string[] args) {User Snduser=NewUser (); Snduser.setusername ("Zhangsan"); User Sndtouser=NewUser (); Sndtouser.setusername ("Lisi"); User SndToUser2=NewUser (); Sndtouser2.setusername ("Wangwu"); Redismessageproducer.sendmessage (Snduser, Sndtouser,"Give John Doe the message One", "Give John Doe the message two"); Redismessageproducer.sendmessage (Snduser, SndToUser2,"Give Harry the Message one", "Give Harry the message two"); }}
1. Start the consumer first
2. After starting the consumer
The consumer console is as follows:
The producer console is as follows:
3. After starting the consumer again
Consumer console:
Producer Control Desk:
At this point, a simple one-off chat is implemented, in fact a simple user sends a message to another user. the above is implemented in this way even if the user online will accept messages that were not previously accepted. Only after Brpop will the message disappear.
In fact, the actual development can be based on the requirements, the actual message type, content and so on.
If you have time, you can use Kindeditor to implement a simple one-to-one web chat system, this feature is ready to be completed. ==============
Redis Implements chat features