Go language series (nine) - Socket Programming and Redis

Socket Programming

A, socket programming overview

  What is socket programming? socket programming is an interactive computer program PC machine 2 is connected via a two-way for data communication, the end is a socket connection. as well as the concept of a socket on the socket of the translation means, in fact, can also be very vivid metaphor for the socket to plug the electricity went there (on the network). In fact, socket programming as inter-process communication mechanism UNIX systems, commonly referred to as "socket" is used to describe a collection of IP addresses and ports, is the handle (file descriptor communication in a unix system, because all are under UNIX It is a file).

UNIX socket programming process roughly as follows:

  • 服务端:socket(),bind(),listen(),accept(),read()/write(),close()
  • 服务端:socket(), connect(),read()/write(),close()

Two, Go socket programming language library

Base package go in the language of the network net package contains a lot of network I / O, TCP / IP, UDP, DNS, Unix domain sockets and so on.

Although it is directly facing the underlying network to provide I / O accesses, but the main interface package TCP communication is relatively simple, easy to use, comprising:

  • Client connection method using Dial
  • Listen method used by the server to listen
  • Accept method accepts the server be linked
  • Package type connection object Conn

Third, the client and server

 1. Server processing flow

  • a. listening port

  • b. receiving client link

  • c. Create goroutine, the link processing

2. The client process flow

  • a. establish a link with the server

  • b. Make data transceiver

  • c. Close Links

3. The server code

package main

import (
	"fmt"
	"net"
)

func main() {
	fmt.Println("start server...")
	listen, err := net.Listen("tcp", "0.0.0.0:50000")
	if err != nil {
		fmt.Println("listen failed, err:", err)
		return
	}
	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("accept failed, err:", err)
			continue
		}
		go process(conn)
	}
}
func process(conn net.Conn) {
	defer conn.Close()
	for {
		buf := make([]byte, 512)
		n, err := conn.Read(buf)
		if err != nil {
			fmt.Println("read err:", err)
			return
		}

		fmt.Printf(string(buf[0:n]))
	}
}

4. client code

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)

func main() {

	conn, err := net.Dial("tcp", "localhost:50000")
	if err != nil {
		fmt.Println("Error dialing", err.Error())
		return
	}

	defer conn.Close()
	inputReader := bufio.NewReader(os.Stdin)
	for {
		input, _ := inputReader.ReadString('\n')
		trimmedInput := strings.Trim(input, "\r\n")
		if trimmedInput == "Q" {
			return
		}
		_, err = conn.Write([]byte(trimmedInput))
		if err != nil {
			return
		}
	}
}

5. Send http request

package main

import (
	"fmt"
	"io"
	"net"
)

func main() {

	conn, err := net.Dial("tcp", "www.baidu.com:80")
	if err != nil {
		fmt.Println("Error dialing", err.Error())
		return
	}
	defer conn.Close()
	msg := "GET / HTTP/1.1\r\n"
	msg += "Host:www.baidu.com\r\n"
	msg += "Connection:keep-alive\r\n"
	// msg += "User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\r\n"
	msg += "\r\n\r\n"

	//io.WriteString(os.Stdout, msg)
	n, err := io.WriteString(conn, msg)
	if err != nil {
		fmt.Println("write string failed, ", err)
		return
	}
	fmt.Println("send to baidu.com bytes:", n)
	buf := make([]byte, 4096)
	for {
		count, err := conn.Read(buf)
		fmt.Println("count:", count, "err:", err)
		if err != nil {
			break
		}
		fmt.Println(string(buf[0:count]))
	}
}

 Redis

A, Redis Introduction

  redis is an open source key-value high-performance memory database, can use it as a data structure of the remote. Supported value type is very large, such as string, list (list), set (collection), hash tables, and so on. redis very high performance, stand-alone can be achieved 15w qps, usually suitable for caching.

 1. Features

  • Support more types of data 
    and the like Memcached, which supports the stored value relatively more types, including string (string), List (list), SET (set), zset (sorted set ordered set) and hash (hash type ). [1]

  • Operating support complex 
    data types are supported push / pop, add / remove and on the intersection and union, and difference richer operation, and these operations are atomic. On this basis, Redis supports a variety of different ways of sorting. [2]

  • Support master-slave synchronization. 
    Like with memcached, in order to ensure efficiency, the data is cached in memory. Redis difference is that will periodically update the data written to disk or to modify the operation of writing additional log file, and on this basis realize the master-slave (master and slave) synchronization. Data can be synchronized from the primary server to an arbitrary number from the server, the server may be associated with the primary server from another server. This allows the tree Redis single executable copy. May intentionally or unintentionally write data from the disk. Since the full implementation of the publish / subscribe mechanism, so that the database synchronization from a tree anywhere, can subscribe to a channel and receive the full message master server publishing record. Synchronization scalability and redundancy data useful for a read operation.

2. Common usage scenarios

  • Under high concurrent data cache. For example, in a scene, while a large number of logs into the database server will bring enormous pressure, then you can first write data redis, and then by the rediswrite pressure simultaneously written to the database, reduced.
  • Hot rapid information display. Suppose now have a news page, you need to quickly display the first 20 columns each hot news, if you query the database directly, in a large number of simultaneous users will consume a great amount of database requests. Then you can use redisto optimize, in a news entry when the title, time and written sources redis, the client access, you can remove the one-day hot news list from memory one time, greatly enhance the speed and saving the server request overhead.
  • Save session information. You can login user information into the cache redisand also set keythe expiration time, so the background apifiltering request, the user can read information from memory, and redisthe expiration mechanism, natural support user identity verification period, with very convenient.
  • Statistics count. Such a system common function is to limit the same user logins all fixed time period or number of requests, then the user can id as key, value is the number of times, the count information is cached, and there are INCRBYcommands native support.
  • other. Redis is very widely distributed application scenarios, queues, publish and subscribe, statistical analysis, etc., you can look at the introduction explain other articles.

  Redis appears, to a large extent compensate for the lack of such memcached key / value store, it can play a very good complement to relational database in some situations. It provides Java, C / C ++, C #, PHP, JavaScript, Perl, Object-C, Python, Ruby, Erlang and other clients, very easy to use. Redis official website address is very easy to remember, is redis.io . Currently, Vmware in financing the development and maintenance of Redis project.

Two, Redis main data structures

  There are five basic Redis data structures to meet the needs of the vast majority of cache structure, and if you feel awkward when the use of a storage structure, is likely to be wrong storage structure, consider the correct implementation of other structures .

  • String, can be a string, integer and floating point numbers. If the data is serialized, and then modify the operation involved, is not recommended string, consider usingHash
  • Hash, key-value object may store object data, such as user information or the like.
  • List, an ordered set of data elements may be repeated, with LPUSH, LPOP, RPUSH, RPOPand other instructions can be implemented in combination stack and queue operations.
  • Set, unordered collection of unique elements.
  • Sorted Set, Sort ordered version, you can set the Scorevalue to determine the elemental sort, user ranking for this business scenario.

 Two, Redis use

 1. reducing

  redigo is a GO redis client-side implementation language. The project is located https://github.com/garyburd/redigo

 2. Install redigo

redigo no other dependencies, can be installed directly go get 

go get github.com/garyburd/redigo/redis

 3. Connect redis

package main

import (
	"fmt"
	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}

	defer c.Close()
}

 4. Establish a connection pool

  Redigo Pool structure maintains a connection pool Redis. The application calls the Get method to get a connection from the pool, and use of resources Close method of connecting the connection returns to the pool. Generally, we declare a global connection pool during system initialization, and then need to operate redisto get connected, the instruction is executed.

the pool: = {& redis.Pool 
        maxidle:. 3, / * maximum number of idle connections * / 
        maxActive:. 8, / * maximum number of active connections * / 
        the Dial: FUNC () (redis.Conn, error) { 
            C, ERR: = redis.Dial ( "tcp", "link address, e.g. 127.0.0.1:6379", redis.DialPassword ( "password")) 
            ! = nil {IF ERR 
                return nil, ERR 
            } 
            return C, nil 
        }, 
} 
C: pool.Get = () 
the defer c.Close ()
main Package 

Import (
     " FMT " 

    " github.com/garyburd/redigo/redis " 
) 

var the pool * redis.Pool 

FUNC the init () { 
    the pool = & redis.Pool { 
        maxidle:      16, / * maximum number of idle connections * / 
        maxActive: 0,   / * maximum number of active connections * / 
        the IdleTimeout: 300 , 
        the Dial: FUNC () (redis.Conn, error) { 
            C, ERR: = redis.Dial ( " TCP " , " localhost: 6379 " , Redis .DialPassword ( " 0000 "))
            if err != nil {
                return nil, err
            }
            return c, nil
        },
    }
}

func main() {

    c := pool.Get()
    defer c.Close()

    _, err := c.Do("Set", "abc", 100)
    if err != nil {
        fmt.Println(err)
        return
    }

    r, err := redis.Int(c.Do("Get", "abc"))
    if err != nil {
        fmt.Println("get abc failed,", err)
        return
    }

    fmt.Println(r)
    pool.Close()
}
Examples of connection pool redis

 The execution instruction

  View source found Conn interface has a common method of execution Redis commands:

//gomodule/redigo/redis/redis.go

// Conn represents a connection to a Redis server.
type Conn interface {
    // Close closes the connection.
    Close() error

    // Err returns a non-nil value when the connection is not usable.
    Err() error

    // Do sends a command to the server and returns the received reply.
    Do(commandName string, args ...interface{}) (reply interface{}, err error)

    // Send writes the command to the client's output buffer.
    Send(commandName string, args ...interface{}) error

    // Flush flushes the output buffer to the Redis server.
    Flush() error

    // Receive receives a single reply from the Redis server
    Receive() (reply interface{}, err error)
}

 http://redis.io/commands  in Redis Command Reference lists the available commands. doParameters and redis-cliconsistent format command parameters, such as SET key value EX 360 the corresponding function is invoked Do("SET", "key", "value","EX",360), the command commonly used examples include:  

c := pool.Get()
defer c.Close()
//存值,
_, err := c.Do("SET", "key", "value")
//设置过期时间
_, err := c.Do("SET", "key", "value","EX",360)
//存int
_, err := c.Do("SET", "key", 2)

//取值
v,err:=redis.String(c.Do("GET","key"))
bytes, err := redis.Bytes(c.Do("GET", "key"))
package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func main() {
    var p *int
    var a int
    p = &a
    *p = 0

    c, err := redis.Dial("tcp", "localhost:6379")
    if err != nil {
        fmt.Println("conn redis failed,", err)
        return
    }

    defer c.Close()
    _, err = c.Do("Set", "abc", 100)
    if err != nil {
        fmt.Println(err)
        return
    }

    r, err := redis.Int(c.Do("Get", "abc"))
    if err != nil {
        fmt.Println("get abc failed,", err)
        return
    }

    fmt.Println(r)
}
set operation
package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func main() {
    c, err := redis.Dial("tcp", "localhost:6379")
    if err != nil {
        fmt.Println("conn redis failed,", err)
        return
    }

    defer c.Close()
    _, err = c.Do("MSet", "abc", 100, "efg", 300)
    if err != nil {
        fmt.Println(err)
        return
    }

    r, err := redis.Ints(c.Do("MGet", "abc", "efg"))
    if err != nil {
        fmt.Println("get abc failed,", err)
        return
    }

    for _, v := range r {
        fmt.Println(v)
    }
}
mset operation
package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func main() {
    c, err := redis.Dial("tcp", "localhost:6379")
    if err != nil {
        fmt.Println("conn redis failed,", err)
        return
    }

    defer c.Close()
    _, err = c.Do("HSet", "books", "abc", 100)
    if err != nil {
        fmt.Println(err)
        return
    }

    r, err := redis.Int(c.Do("HGet", "books", "abc"))
    if err != nil {
        fmt.Println("get abc failed,", err)
        return
    }

    fmt.Println(r)
}
hset operation
package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func main() {
    c, err := redis.Dial("tcp", "localhost:6379")
    if err != nil {
        fmt.Println("conn redis failed,", err)
        return
    }

    defer c.Close()
    _, err = c.Do("lpush", "book_list", "abc", "ceg", 300)
    if err != nil {
        fmt.Println(err)
        return
    }

    r, err := redis.String(c.Do("lpop", "book_list"))
    if err != nil {
        fmt.Println("get abc failed,", err)
        return
    }

    fmt.Println(r)
}
list queue operation
package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func main() {
    c, err := redis.Dial("tcp", "localhost:6379")
    if err != nil {
        fmt.Println("conn redis failed,", err)
        return
    }

    defer c.Close()
    _, err = c.Do("expire", "abc", 10)
    if err != nil {
        fmt.Println(err)
        return
    }
}
Set an expiration time

 

Guess you like

Origin www.cnblogs.com/zhangyafei/p/10993160.html