這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。在上篇用純go在本機類比了下分布式隊列的東西。這裡補上Redis隊列部份。
用Redis做隊列有下面三個問題需解決:
1. 隊列構建
使用Redis的RPUSH/LPOP來解決
2. 參數傳遞/解析
用戶端將JOSN參數存入Redis,Server端取出後解析還原。
3. 串連池
redigo支援Redis串連池
下面代碼就是具體解決實現:
//Redis做背景工作隊列//author: Xiong Chuan Liang//date: 2015-3-25package mainimport ("bytes""encoding/json""errors""fmt""time""github.com/garyburd/redigo/redis")func main() {r, err := newRedisPool("", "")if err != nil {fmt.Println(err)return}//將job放入隊列r.Enqueue()//依次取出兩個Jobr.GetJob()r.GetJob()}type RedisPool struct {pool *redis.Pool}func newRedisPool(server, password string) (*RedisPool, error) {if server == "" {server = ":6379"}pool := &redis.Pool{MaxIdle: 3,IdleTimeout: 240 * time.Second,Dial: func() (redis.Conn, error) {c, err := redis.Dial("tcp", server)if err != nil {return nil, err}if password != "" {if _, err := c.Do("AUTH", password); err != nil {c.Close()return nil, err}}return c, err},TestOnBorrow: func(c redis.Conn, t time.Time) error {_, err := c.Do("PING")return err},}return &RedisPool{pool}, nil}type Job struct {Class string `json:"Class"`Args []interface{} `json:"Args"`}//類比用戶端func (r *RedisPool) Enqueue() error {c := r.pool.Get()defer c.Close()j := &Job{}j.Class = "mail"j.Args = append(j.Args, "xcl_168@aliyun.com", "", "body", 2, true)j2 := &Job{}j2.Class = "Log"j2.Args = append(j2.Args, "ccc.log", "ddd.log", []int{222, 333})for _, v := range []*Job{j, j2} {b, err := json.Marshal(v)if err != nil {return err}_, err = c.Do("rpush", "queue", b)if err != nil {return err}}fmt.Println("[Enqueue()] succeed!")return nil}//類比Job Serverfunc (r *RedisPool) GetJob() error {count, err := r.QueuedJobCount()if err != nil || count == 0 {return errors.New("暫無Job.")}fmt.Println("[GetJob()] Jobs count:", count)c := r.pool.Get()defer c.Close()for i := 0; i < int(count); i++ {reply, err := c.Do("LPOP", "queue")if err != nil {return err}var j Jobdecoder := json.NewDecoder(bytes.NewReader(reply.([]byte)))if err := decoder.Decode(&j); err != nil {return err}fmt.Println("[GetJob()] ", j.Class, " : ", j.Args)}return nil}func (r *RedisPool) QueuedJobCount() (int, error) {c := r.pool.Get()defer c.Close()lenqueue, err := c.Do("llen", "queue")if err != nil {return 0, err}count, ok := lenqueue.(int64)if !ok {return 0, errors.New("類型轉換錯誤!")}return int(count), nil}/*運行結果:[Enqueue()] succeed![GetJob()] Jobs count: 2[GetJob()] mail : [xcl_168@aliyun.com body 2 true][GetJob()] Log : [ccc.log ddd.log [222 333]][root@xclos src]#*/ 可以看到Go已能取得參數。都是些最基礎的東西。
MAIL: xcl_168@aliyun.com
BLOG: http://blog.csdn.net