Redis队列部份

来源:互联网 发布:传媒杂志 知乎 编辑:程序博客网 时间:2024/05/18 01:08
        在上篇用纯go在本机模拟了下分布式队列的东西。这里补上Redis队列部份。
用Redis做队列有下面三个问题需解决:

 1. 队列构建
     使用Redis的RPUSH/LPOP来解决

 2. 参数传递/解析 
   客户端将JOSN参数存入Redis,Server端取出后解析还原。

 3. 连接池

      redigo支持Redis连接池

下面代码就是具体解决实现:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. //Redis做后台任务队列  
  2. //author: Xiong Chuan Liang  
  3. //date: 2015-3-25  
  4.   
  5. package main  
  6.   
  7. import (  
  8.     "bytes"  
  9.     "encoding/json"  
  10.     "errors"  
  11.     "fmt"  
  12.     "time"  
  13.   
  14.     "github.com/garyburd/redigo/redis"  
  15. )  
  16.   
  17. func main() {  
  18.   
  19.     r, err := newRedisPool("""")  
  20.     if err != nil {  
  21.         fmt.Println(err)  
  22.         return  
  23.     }  
  24.   
  25.     //将job放入队列  
  26.     r.Enqueue()  
  27.   
  28.     //依次取出两个Job  
  29.     r.GetJob()  
  30.     r.GetJob()  
  31. }  
  32.   
  33. type RedisPool struct {  
  34.     pool *redis.Pool  
  35. }  
  36.   
  37. func newRedisPool(server, password string) (*RedisPool, error) {  
  38.   
  39.     if server == "" {  
  40.         server = ":6379"  
  41.     }  
  42.   
  43.     pool := &redis.Pool{  
  44.         MaxIdle:     3,  
  45.         IdleTimeout: 240 * time.Second,  
  46.         Dial: func() (redis.Conn, error) {  
  47.             c, err := redis.Dial("tcp", server)  
  48.             if err != nil {  
  49.                 return nil, err  
  50.             }  
  51.   
  52.             if password != "" {  
  53.                 if _, err := c.Do("AUTH", password); err != nil {  
  54.                     c.Close()  
  55.                     return nil, err  
  56.                 }  
  57.             }  
  58.             return c, err  
  59.         },  
  60.         TestOnBorrow: func(c redis.Conn, t time.Time) error {  
  61.             _, err := c.Do("PING")  
  62.             return err  
  63.         },  
  64.     }  
  65.   
  66.     return &RedisPool{pool}, nil  
  67. }  
  68.   
  69. type Job struct {  
  70.     Class string        `json:"Class"`  
  71.     Args  []interface{} `json:"Args"`  
  72. }  
  73.   
  74. //模拟客户端  
  75. func (r *RedisPool) Enqueue() error {  
  76.   
  77.     c := r.pool.Get()  
  78.     defer c.Close()  
  79.   
  80.     j := &Job{}  
  81.     j.Class = "mail"  
  82.     j.Args = append(j.Args, "xcl_168@aliyun.com""""body", 2, true)  
  83.   
  84.     j2 := &Job{}  
  85.     j2.Class = "Log"  
  86.     j2.Args = append(j2.Args, "ccc.log""ddd.log", []int{222, 333})  
  87.   
  88.     for _, v := range []*Job{j, j2} {  
  89.         b, err := json.Marshal(v)  
  90.         if err != nil {  
  91.             return err  
  92.         }  
  93.   
  94.         _, err = c.Do("rpush""queue", b)  
  95.         if err != nil {  
  96.             return err  
  97.         }  
  98.     }  
  99.   
  100.     fmt.Println("[Enqueue()] succeed!")  
  101.   
  102.     return nil  
  103. }  
  104.   
  105. //模拟Job Server  
  106. func (r *RedisPool) GetJob() error {  
  107.     count, err := r.QueuedJobCount()  
  108.     if err != nil || count == 0 {  
  109.         return errors.New("暂无Job.")  
  110.     }  
  111.     fmt.Println("[GetJob()] Jobs count:", count)  
  112.   
  113.     c := r.pool.Get()  
  114.     defer c.Close()  
  115.   
  116.     for i := 0; i < int(count); i++ {  
  117.         reply, err := c.Do("LPOP""queue")  
  118.         if err != nil {  
  119.             return err  
  120.         }  
  121.   
  122.         var j Job  
  123.         decoder := json.NewDecoder(bytes.NewReader(reply.([]byte)))  
  124.         if err := decoder.Decode(&j); err != nil {  
  125.             return err  
  126.         }  
  127.   
  128.         fmt.Println("[GetJob()] ", j.Class, " : ", j.Args)  
  129.     }  
  130.     return nil  
  131. }  
  132.   
  133. func (r *RedisPool) QueuedJobCount() (int, error) {  
  134.     c := r.pool.Get()  
  135.     defer c.Close()  
  136.   
  137.     lenqueue, err := c.Do("llen""queue")  
  138.     if err != nil {  
  139.         return 0, err  
  140.     }  
  141.   
  142.     count, ok := lenqueue.(int64)  
  143.     if !ok {  
  144.         return 0, errors.New("类型转换错误!")  
  145.     }  
  146.     return int(count), nil  
  147. }  
  148.   
  149. /* 
  150. 运行结果: 
  151.  
  152. [Enqueue()] succeed! 
  153. [GetJob()] Jobs count: 2 
  154. [GetJob()]  mail  :  [xcl_168@aliyun.com  body 2 true] 
  155. [GetJob()]  Log  :  [ccc.log ddd.log [222 333]] 
  156. [root@xclos src]# 
  157.  
  158. */  
    可以看到Go已能取得参数。都是些最基础的东西。
0 0
原创粉丝点击