memcached 使用 / go 操作memcached (gomemcache) / python 操作 memcached (python-memcached)

燕砚文
2023-12-01

简介

Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。
Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。这些数据可以是数据库调用、API调用或者是页面渲染的结果

安装

这里使用docker安装
docker-compose.yaml

  version: "3.7"
  services:
    memcached:
      image: memcached
      ports:
        - 21211:11211
      healthcheck:
        test: ["CMD", "echo", "stats", "|",  "nc", "127.0.0.1", "11211"]
        interval: 20s
        timeout: 1s
        retries: 20

使用

使用telnet 链接 memcached, 并测试其方法:

luslin@local:~$ telnet 127.0.0.1 21211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

1. 存储命令

a. set

Memcached set 命令用于将 value(数据值) 存储在指定的 key(键) 中。
如果set的key已经存在,该命令可以更新该key所对应的原来的数据,也就是实现更新的作用。
语法:
set 命令的基本语法格式如下:

set key flags exptime bytes [noreply] 
value
  • key:键值 key-value 结构中的 key,用于查找缓存值。
  • flags:可以包括键值对的整型参数,客户机使用它存储额外信息 。
  • exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
  • bytes:在缓存中存储的字节数
  • noreply(可选): 该参数告知服务器不需要返回数据
  • value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)

例如:

set l1 0 10000 1
a
STORED # 返回结果

b. add

Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中。
如果 add 的 key 已经存在,则不会更新数据(过期的 key 会更新),之前的值将仍然保持相同,并获得响应 NOT_STORED。
语法:
add 命令的基本语法格式如下:

add key flags exptime bytes [noreply]
value

例如:

add l1 0 10000 2
aa 
NOT_STORED # 没有设置成功
add l2 0 10000 1
b
STORED 
get l1 l2
VALUE l1 0 1
a
VALUE l2 0 1
b

c. replace

Memcached replace 命令用于替换已存在的 key(键) 的 value(数据值)。
如果 key 不存在,则替换失败,并且您将获得响应 NOT_STORED。

语法:
replace 命令的基本语法格式如下:

replace key flags exptime bytes [noreply]
value

例如:

replace l1 0 10000 2
aa
STORED
replace l3 0 10000 1
a
NOT_STORED
get l1 l3
VALUE l1 0 2
aa
END

d. append

Memcached append 命令用于向已存在 key(键) 的 value(数据值) 后面追加数据 。

语法:
append 命令的基本语法格式如下:

append key flags exptime bytes [noreply]
value

例如:

append l1 0 10000 1
b
STORED
append l3 0 10000 1
c
NOT_STORED
get l1 l3
VALUE l1 0 3
aab
END

e. prepend

Memcached prepend 命令用于向已存在 key(键) 的 value(数据值) 前面追加数据 。

语法:
prepend 命令的基本语法格式如下:

prepend key flags exptime bytes [noreply]
value

例如:

prepend l1 0 10000 1
p
STORED
get l1
VALUE l1 0 4
paab
END

f. CAS 命令

Memcached CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作
它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入。
检查是通过cas_token参数进行的, 这个参数是Memcach指定给已经存在的元素的一个唯一的64位值。
语法:
CAS 命令的基本语法格式如下:

cas key flags exptime bytes unique_cas_token [noreply]
value
  • unique_cas_token通过 gets 命令获取的一个唯一的64位值。

例如:
12 为 cas_token, 当使用命令修改值后, token改为17。这时再用 12 去修改就不会起效果了

VALUE l1 0 4 12
paab
END
set l1 0 10000 1
a
STORED
gets l1
VALUE l1 0 1 17
a
END
cas l1 0 100000 1 12 
b
EXISTS
gets l1
VALUE l1 0 1 17
a
END
cas l1 0 100000 1 17
b
STORED
gets l1
VALUE l1 0 1 18
b
END

2. 查找命令

a. get

Memcached get 命令获取存储在 key(键) 中的 value(数据值) ,如果 key 不存在,则返回空。

语法:
get 命令的基本语法格式如下:

get key

多个 key 使用空格隔开,如下:

get key1 key2 key3

例如:

get l1 l2 
VALUE l1 0 4
paab
VALUE l2 0 1
b
END

b. gets

Memcached gets 命令获取带有 CAS 令牌存 的 value(数据值) ,如果 key 不存在,则返回空。
语法:
gets 命令的基本语法格式如下:

gets key

多个 key 使用空格隔开,如下:

gets key1 key2 key3

例如:

gets l1 l2
VALUE l1 0 4 12  # 这里的12 代表 cas令牌
paab
VALUE l2 0 1 8
b
END

c. delete

Memcached delete 命令用于删除已存在的 key(键)。
delete 命令的基本语法格式如下:

delete key [noreply]

例如:

set l3 0 10000 1
e
STORED
delete l3
DELETED
get l3
END

d. delete

Memcached incr 与 decr 命令
Memcached incr 与 decr 命令用于对已存在的 key(键) 的数字值进行自增或自减操作。
incr 与 decr 命令操作的数据必须是十进制的32位无符号整数。
如果 key 不存在返回 NOT_FOUND,如果键的值不为数字,则返回 CLIENT_ERROR,其他错误返回 ERROR

语法:
incr 命令的基本语法格式如下:

incr key increment_value

例如:

set l3 0 10000 1
0
STORED
incr l3 1
1
get l3
VALUE l3 0 1
1
END
decr l3 2
0
get l3
VALUE l3 0 1
0
END
incr l1 1
CLIENT_ERROR cannot increment or decrement non-numeric value
incr l4 1
NOT_FOUND

gomemcache

github 地址:github.com/bradfitz/gomemcache
文档地址: https://pkg.go.dev/mod/github.com/bradfitz/gomemcache@v0.0.0-20190913173617-a41fca850d0b

环境:

gogomemcache
go1.13.5v0.0.0-20190913173617-a41fca850d0b

简单使用:

func painc_err(err error)  {
	if err != nil {
		panic(err)
	}
}
func TestSetAndGet(t *testing.T) {
	client := memcache.New("127.0.0.1:21211")
	err := client.Ping()
	painc_err(err)
	err = client.Set(&memcache.Item{Key: "a1", Value: []byte("a"),Flags: 0, Expiration: 100000})
	painc_err(err)
	item, err := client.Get("a1")
	painc_err(err)
	fmt.Println(string(item.Value))
	item, err = client.Get("a2")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(string(item.Value))
	}
}

结果

a
memcache: cache miss

常用方法

type Client
	func New(server ...string) *Client
	func (c *Client) Add(item *Item) error
	func (c *Client) CompareAndSwap(item *Item) error    # CAS
	func (c *Client) Decrement(key string, delta uint64) (newValue uint64, err error)
	func (c *Client) Delete(key string) error
	func (c *Client) DeleteAll() error
	func (c *Client) FlushAll() error
	func (c *Client) Get(key string) (item *Item, err error)
	func (c *Client) GetMulti(keys []string) (map[string]*Item, error)
	func (c *Client) Increment(key string, delta uint64) (newValue uint64, err error)
	func (c *Client) Ping() error
	func (c *Client) Replace(item *Item) error
	func (c *Client) Set(item *Item) error

常见错误:

var (
	// ErrCacheMiss means that a Get failed because the item wasn't present.
	ErrCacheMiss = errors.New("memcache: cache miss")

	// ErrCASConflict means that a CompareAndSwap call failed due to the
	// cached value being modified between the Get and the CompareAndSwap.
	// If the cached value was simply evicted rather than replaced,
	// ErrNotStored will be returned instead.
	ErrCASConflict = errors.New("memcache: compare-and-swap conflict")

	// ErrNotStored means that a conditional write operation (i.e. Add or
	// CompareAndSwap) failed because the condition was not satisfied.
	ErrNotStored = errors.New("memcache: item not stored")

	// ErrServer means that a server error occurred.
	ErrServerError = errors.New("memcache: server error")

	// ErrNoStats means that no statistics were available.
	ErrNoStats = errors.New("memcache: no statistics available")

	// ErrMalformedKey is returned when an invalid key is used.
	// Keys must be at maximum 250 bytes long and not
	// contain whitespace or control characters.
	ErrMalformedKey = errors.New("malformed: key is too long or contains invalid characters")

	// ErrNoServers is returned when no servers are configured or available.
	ErrNoServers = errors.New("memcache: no servers configured or available")
)

python-memcached

github 地址:github.com/linsomniac/python-memcached

安装:

pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com python-memcached

测试:

class FooStruct(object):

    def __init__(self):
        self.bar = "baz"

    def __str__(self):
        return "A FooStruct"

    def __eq__(self, other):
        if isinstance(other, FooStruct):
            return self.bar == other.bar
        return 0


class TestMemcache(unittest.TestCase):
    def setUp(self):
        # TODO(): unix socket server stuff
        servers = ["127.0.0.1:21211"]
        self.mc = Client(servers, debug=1)

    def tearDown(self):
        self.mc.flush_all()
        self.mc.disconnect_all()

    def check_setget(self, key, val, noreply=False):
        self.mc.set(key, val, noreply=noreply)
        newval = self.mc.get(key)
        self.assertEqual(newval, val)

    def test_setget(self):
        self.check_setget("a_string", "some random string")
        self.check_setget("a_string_2", "some random string", noreply=True)
        self.check_setget("an_integer", 42)
        self.check_setget("an_integer_2", 42, noreply=True)

其他详细方法可参考:https://github.com/linsomniac/python-memcached/blob/master/tests/test_memcache.py

 类似资料: