redis實現發布(訂閱)消息


redis實現發布(訂閱)消息

什么是redis的發布訂閱(pub/sub)?   Pub/Sub功能(means Publish, Subscribe)即發布及訂閱功能。基於事件的系統中,Pub/Sub是目前廣泛使用的通信模型,它采用事件作為基本的通信機制,提供大規模系統所要求的松散耦合的交互模式:訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的一個事件或一類事件;發布者(如服務器)可將訂閱者感興趣的事件隨時通知相關訂閱者。熟悉設計模式的朋友應該了解這與23種設計模式中的觀察者模式極為相似。 

看到發布訂閱的特性,用來做一個簡單的實時聊天系統再適合不過了。這是其中之一,當然這樣的東西,我們開發中很少涉及到。再舉一個常用的,在我們的分布式架構中,常常會遇到讀寫分離的場景,在寫入的過程中,就可以使用redis發布訂閱,使得寫入值及時發布到各個讀的程序中,就保證數據的完整一致性。再比如,在一個博客網站中,有100個粉絲訂閱了你,當你發布新文章,就可以推送消息給粉絲們拉。總之場景很多,需要去挖掘。。

Redis的pub/sub是一種消息通信模式,主要的目的是解除消息發布者和消息訂閱者之間的耦合,  Redis作為一個pub/sub的server, 在訂閱者和發布者之間起到了消息路由的功能。

Redis 發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。

Redis 客戶端可以訂閱任意數量的頻道。

當有新消息通過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被發送給訂閱它的所有客戶端。

 

// *************************************************************************** }
//
// Delphi REDIS Client
//
// Copyright (c) 2015-2017 Daniele Teti
//
// https://github.com/danieleteti/delphiredisclient
//
// ***************************************************************************
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ***************************************************************************

unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, redis.client, redis.commons,
  redis.netlib.indy, System.threading,
  Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Memo1: TMemo;
    Edit2: TEdit;
    Label1: TLabel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Edit2KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    _redis: IRedisClient;
    FTask: ITask;
    FClosing: Boolean;
    procedure SendChatMessage;
    procedure OnMessage(const ANickName, AMessage: string);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

uses System.json, ShellAPI;
{$R *.dfm}


procedure TForm2.Button1Click(Sender: TObject);
begin
  ShellExecute(0, pchar('open'), pchar(Application.ExeName), nil, nil, SW_SHOW);
end;

procedure TForm2.Edit2KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_RETURN then
  begin
    SendChatMessage;
    Key := 0;
    Edit2.Clear;
  end;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FClosing := True;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  FClosing := False;
  Label1.Caption := InputBox('Chat user name',
    'What is your user name in this chat?', 'd.teti' + (100 + Random(999))
    .ToString);
  _redis := NewRedisClient();
  FTask := TTask.Run(
    procedure
    var
      r: IRedisClient;
    begin
      r := NewRedisClient;
      r.SUBSCRIBE(['chat'],
        procedure(channel, message: string)
        var
          jobj: TJSONObject;
          msg, nickname: string;
        begin
          jobj := TJSONObject.ParseJSONValue(message) as TJSONObject;
          nickname := jobj.GetValue<TJSONString>('nickname').Value;
          msg := jobj.GetValue<TJSONString>('message').Value;
          TThread.Synchronize(nil,
            procedure
            begin
              Self.OnMessage(nickname, msg);
            end);
        end,
        function: Boolean
        begin
          Result := Assigned(Self) and (not FClosing);
        end);
    end);
end;

procedure TForm2.OnMessage(const ANickName, AMessage: string);
begin
  Memo1.Lines.Add('[' + ANickName + '] ' + DateTimeToStr(now));
  Memo1.Lines.Add(AMessage);
  Memo1.Lines.Add('---');
end;

procedure TForm2.SendChatMessage;
var
  jobj: TJSONObject;
begin
  jobj := TJSONObject.Create;
  try
    jobj.AddPair('nickname', Label1.Caption).AddPair('message', Edit2.Text);
    _redis.PUBLISH('chat', jobj.ToString);
  finally
    jobj.Free;
  end;
end;

end.

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM