redigo操作 及 发布订阅

61 篇文章 0 订阅
3 篇文章 0 订阅

用户头像用redis存的,当用户更换头像时,把数据库就完事了吗?当然没有,因为Redis里还是老数据。那你会说不是有过期时间吗?是的,但有的过期时间设置的较长如24小时并且我们想立即生效怎么办?这时候我们就可以利用Redis的发布订阅机制来实现数据的实时刷新。

过程:

step1. 用户在头像编辑页面更换头像后,存数据库,并且在channel(已经被头像显示页面订阅)删除后重新发布一个

step2. 头像显示页面循环检测时发现此channel有receive到数据,于是读取更新原来的头像地址,前端页面就显示出新的图片


目录

redigo操作

发布订阅

使用场景

概念

redis中的发布订阅

redigo demo


redigo操作

golang操作redis主要有两个库,go-redis和redigo。两者操作都比较简单,区别上redigo更像一个client执行各种操作都是通过Do函数去做的,redis-go对函数的封装更好,相比之下redigo操作redis显得有些繁琐。但是官方更推荐redigo,所以项目中我使用了redigo。

1.连接redis

package redisclient
 
import (
    "fmt"
    redigo "github.com/garyburd/redigo/redis"
)
 
var pool *redigo.Pool
 
func init() {
    redis_host := "127.0.0.1"
    redis_port := 6379
    pool_size := 20
    pool = redigo.NewPool(func() (redigo.Conn, error) {
        c, err := redigo.Dial("tcp", fmt.Sprintf("%s:%d", redis_host, redis_port))
        if err != nil {
            return nil, err
        }
        return c, nil
    }, pool_size)
}
 
func Get() redigo.Conn {
    return pool.Get()
}

之后我们调用redisclient包中的.Get()就可以生成一个redis连接池对象来操作redis。

2.操作redis

package main
 
import (
    "fmt"
    "redisclient"
    "github.com/garyburd/redigo/redis"
)
 
func main() {
    c := redisclient.Get()
 
    //记得销毁本次链连接
    defer c.Close()
 
    //写入数据
    _, err := c.Do("SET", "go_key", "redigo")
    if err != nil {
        fmt.Println("err while setting:", err)
    }
 
    //判断key是否存在
    is_key_exit, err := redis.Bool(c.Do("EXISTS", "go_key"))
    if err != nil {
        fmt.Println("err while checking keys:", err)
    } else {
        fmt.Println(is_key_exit)
    }
 
    //获取value并转成字符串
    account_balance, err := redis.String(c.Do("GET", "go_key"))
    if err != nil {
        fmt.Println("err while getting:", err)
    } else {
        fmt.Println(account_balance)
    }
 
    //删除key
    _, err = c.Do("DEL", "go_key")
    if err != nil {
        fmt.Println("err while deleting:", err)
    }
 
    //设置key过期时间
    _, err = c.Do("SET", "mykey", "superWang", "EX", "5")
    if err != nil {
        fmt.Println("err while setting:", err)
    }
 
    //对已有key设置5s过期时间
    n, err := c.Do("EXPIRE", "go_key", 5)
    if err != nil {
        fmt.Println("err while expiring:", err)
    } else if n != int64(1) {
        fmt.Println("failed")
    }
}

发布订阅

使用场景

众所周知,我们用Redis无非就是将系统中不怎么变的、查询又比较频繁的数据缓存起来,例如我们系统首页的轮播图啊,页面的动态链接啊,一些系统参数啊,公共数据啊都加载到Redis,然后有个后台管理系统去配置修改这些数据。

打个比方我们首页的轮播图要再增加一个图,那我们就在后管系统加上,加上就完事了吗?当然没有,因为Redis里还是老数据。那你会说不是有过期时间吗?是的,但有的过期时间设置的较长如24小时并且我们想立即生效怎么办?这时候我们就可以利用Redis的发布订阅机制来实现数据的实时刷新。当我们修改完数据后,点击刷新按钮,通过发布订阅机制,订阅者接收到消息后调用重新加载的方法即可。

概念

发布订阅其作用是为了减少依赖关系,通常也叫观察者模式。主要是把耦合点单独抽离出来作为第三方,隔离易变化的发送方和接收方。

Pub/Sub 从字面上理解就是发布(Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。

这一功能最明显的用法就是构建实时消息系统,比如普通的即时聊天,群聊等功能。订阅某个channel的信息,发布信息到某个channel上。

简单的应用场景的话, 以门户网站为例, 当编辑更新了某推荐板块的内容后: CMS发布清除缓存的消息到channel (推送者推送消息),门户网站的缓存系统通过channel收到清除缓存的消息 (订阅者收到消息),更新了推荐板块的缓存。

发送方:只负责向第三方发送消息。(杂志社把读者杂志交给邮局)
接收方:被动接收消息。(1:向邮局订阅读者杂志,2:去门口接邮过来的杂志)
第三方:存储订阅杂志的接收方,并在杂志过来时送给接收方。 (邮局)

架构:Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分,发布者,订阅者和Channel。发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息

redis中的发布订阅

redis实现完整的发布订阅范式,就是说任何一台redis服务器,启动后都可以当做发布订阅服务器。

1、普通订阅
a、订阅bar频道。格式:subscribe name1 name2。 
成功订阅回复,分别对应订阅类型、订阅频道、订阅数量。

b、发布bar频道。格式:publish channelname message。

c、订阅bar频道的回复,分别对应消息类型,频道,消息。

2、模式订阅
redis支持模式匹配订阅,*为模糊匹配符。
订阅所有频道的消息:psubscribe * 
订阅以news.开头的所有频道:psubscribe news.*

3、取消订阅
取消普通订阅和取消模式订阅的命令。

unsubscribe bar
punsubscribe ba*
取消在官方提供的连接工具中无法模拟的。

4、查看订阅信息
命令:pubsub channels [pattern],查看订阅消息是redis在2.8中新增加的命令之一。

4.1、返回当前服务器被订阅的所有频道。
127.0.0.1:6379> pubsub channels
1) "bar"

4.2、指定匹配参数,返回与模式匹配的所有频道。
127.0.0.1:6379> pubsub channels ba*
1) "bar"

4.3、接受任意多个频道作为输入参数,返回这些频道的订阅者数量。
127.0.0.1:6379> pubsub numsub bar bar2
1) "bar"
2) (integer) 1
3) "bar2"
4) (integer) 0

redigo demo

//redis 发布订阅
func main()  {
	err := initRedis()
	if err != nil {
		logs.Debug(fmt.Sprintf("connect redis err: %s", err.Error()))
		os.Exit(1)
	}
	//监听test频道
	pubSub,err:=rds.Sub("test")
	if err!=nil {
		fmt.Println(err)
	}
	//订阅
	go func() {
		var receipt interface{}
		var err error
		for  {
			receipt,err=pubSub.Receive()
			if err !=nil {
				fmt.Println(err)
			}
			//fmt.Println(reflect.ValueOf(receipt).String())
			if receipt !="" {
				switch v := receipt.(type) {
				case *redis.Message://单个订阅subscribe
					fmt.Printf("%s: message: %s\n", v.Channel,v.Payload)
				case error:
					return
 
				}
			}
		}
	}()
	//向test频道发布消息
	for i:=0;i<10 ;i++  {
		_,err:=rds.Pub("test",strconv.Itoa(i))
		if err !=nil {
			fmt.Println(err)
		}
		time.Sleep(time.Second)
	}
	//http.ListenAndServe(":80",nil)
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值