Vitess Source Read the Memcache client of the cache series (also talk about the love and hate of GC and Golang error handling mechanism)

Source: Internet
Author: User
Tags cas
This is a creation in Article, where the information may have evolved or changed. Memcache's client implementation file is Memcache.go, implements the Memcached protocol client, for learning Golang client network programming,

Memcache.go is still worth a visit. It is strange that the Vitess installation documentation does not mention the requirement to install memcached, as to why the use of Memcache,

Rather than the in-process cache to save overhead? The documentation for Vitess is described in this way:

Go ' s existing mark-and-sweep garbage collector is sub-optimal for systems the use large amounts of the static memory (like CA Ches). In the case of VTOCC, this would is the row cache. To alleviate this, we intend-memcache for the time being. If the GC ends up addressing this, it should is fairly trivial to switch to a in-memory row cache is not translated. In short, the vitess author also believes that the in-process cache is a better solution, because the current Golang GC implementation is not ideal,

So I chose the memcache. In addition, here is an article to share the journey from Ruby to Golang to C also shows that go GC is not mature enough.

A friend of the watercress also shared the experience of Golang manual memory management, see here

Hopefully, one of the next highlights of the go team is to fix the bugs in the GC (which seems less realistic in the short term) and solve the problems of the existing GC in several ways: 1. Try to choose 64-bit operating system, do not use 32-bit (not the root of the road), refer to https://groups.google.com/group/golang-nuts/browse_thread/thread/ab1971bb9459025d#2. A large number of objects are managed using pools as much as possible, and Redis and memcache are good choices, because this part of memory management is given to them, and Vitess is doing it 3. Manual management is also a good choice, refer to the brother of the Watercress article

GC problem can be left aside, to see the Memcache client, or first put the most important, that is memcache in the vitess play what role? The answer is the main component in the Cache_pool inside the row cache, see what are the highlights in the bottom memcache of the architecture diagram? The usual, first on the data structure type Connection struct { Conn Net. Conn Buffered Bufio. Readwriter} since net. Conn has implemented the read and write interfaces, then why use Bufio. Readwriter, guess there are 2 reasons 1. The performance of the Bufio itself may be higher because the bufferd (not actually tested) 2. More convenient, Bufio. Readwriter also implemented a series of interfaces such as Readstring,readline, can be more convenient to implement Memcache protocol this in the next source can be seen, no longer detail the key to see a few functions on the line, the rest of you see the code can // Learn how to construct reader and writer, which is very common in Golang .
Func newconnection (NC net. Conn) *connection {
return&connection{
CONN:NC,
Buffered:bufio. readwriter{
Bufio. Newreader (NC), // as long as the read interface is implemented, it can be used to construct reader
Bufio. Newwriter (NC), // as long as the write interface is implemented, it can be used to construct writer
},
}
}

Func (self *connection) Close () {
Self.conn.Close ()
Self.conn = Nil // used to determine if a connection is closed, see isclosed function
}

Func (self *connection) IsClosed () BOOL{
returnSelf.conn = Nil

}

Next, enjoy Golang's beautiful error handling mechanism.

Take the Get function as an example:

Func (self *connection) Get (key string) (Value [] byte, Flags UInt16, err error) { // a function that has a name returns the value, and then writes a return to return it automatically.
Defer HandleError (&ERR)
Value, flags, _ = self. Get( " Get ", key)
return

}

Without seeing the long try and cache, the code is about 5 lines less. Someone said, not just a few curly braces, kiss, give you a few more functions to see


func (self *connection) Gets (Key string ) (value [] byte , Flags uint16, CAS UInt64, err Error) {
Defer HandleError (&ERR)
Value, flags, cas = self. Get( " gets ", key)
return
}

Func (self *connection) Set (key string, flags UInt16, timeout UInt64, value [] byte) (Stored BOOL, err Error) {
Defer HandleError (&ERR)
returnSelf.store ( " Set ", key, flags, timeout, value, 0), Nil
}

Func (self *connection) ADD (key string, flags UInt16, timeout UInt64, value [] byte) (Stored BOOL, err Error) {
Defer HandleError (&ERR)
returnSelf.store ( " Add ", key, flags, timeout, value, 0), Nil
}

Func (self *connection) Replace (key string, flags UInt16, timeout UInt64, value [] byte) (Stored BOOL, err Error) {
Defer HandleError (&ERR)
returnSelf.store ( " Replace ", key, flags, timeout, value, 0), Nil
}

Func (self *connection) Append (key string, flags UInt16, timeout UInt64, value [] byte) (Stored BOOL, err Error) {
Defer HandleError (&ERR)
returnSelf.store ( " Append ", key, flags, timeout, value, 0), Nil
}

Func (self *connection) prepend (key string, flags UInt16, timeout UInt64, value [] byte) (Stored BOOL, err Error) {
Defer HandleError (&ERR)
returnSelf.store ( " prepend ", key, flags, timeout, value, 0), Nil
}

Func (self *connection) Cas (key string, flags UInt16, timeout UInt64, value [] byte, CAS UInt64) (stored BOOL, err Error) {
Defer HandleError (&ERR)
returnSelf.store ( " CAs ", key, flags, timeout, value, CAs), nil
}

Func (self *connection) Delete (key string) (Deleted BOOL, err Error) {
Defer HandleError (&ERR)
// delete <key> [<time>] [noreply]\r\n
Self.writestrings ( " Delete ", Key, " \ r \ n ")
Reply: = Self.readline ()
ifStrings. Contains (reply, " ERROR ") {
Panic (Newmemcacheerror ( " Server Error "))
}
returnStrings. Hasprefix (reply, " DELETED "), Nil
}

obediently, this can be less than a lot of code lines, less than 50 rows or so, cannot but say this defer beautiful.

Said for a long while has not given the realization of handleerror, hurriedly serve type Memcacheerror struct{
Message string
}

// variable parameters, and this is a common pattern in Golang.
Func newmemcacheerror (format string, args ... Interface{}) Memcacheerror {
returnMemcacheerror{fmt. Sprintf (format, args ...)}
}

Func (self Memcacheerror) Error () string{
returnSelf. Message
}

Func handleError (Err *error) {
ifx: = Recover (); X! = Nil {
*err = x. (memcacheerror) // Golang are strongly typed, interface need to be forced to convert, which is also a common pattern of Golang
}}


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.