- 浏览: 87045 次
- 性别:
- 来自: 郑州
文章分类
- 全部博客 (69)
- java (28)
- linux (6)
- redis (4)
- C# (3)
- 架构 (10)
- java ee (1)
- web (1)
- 操作系统 (7)
- sqlserver (1)
- android (2)
- Hadoop (12)
- 大数据 (21)
- 分布式 事务 消息 (10)
- linux mysql (1)
- 数据库 (3)
- 关于hadoop之bootshell使用 (2)
- 关于hbase---HTableInterfaceFactory (1)
- Spring (3)
- Hbase (5)
- jstorm (10)
- nginx (1)
- 分布式 (1)
- 区块链 (3)
- dubbo (1)
- nacos (1)
- 阿里 (1)
- go (3)
- 缓存 (1)
- memcached (1)
- ssdb (1)
- 源码 (1)
最新评论
-
想个可以用的名字:
楼主,能不能给发一份源代码,1300246542@qqq.co ...
spring+websocket的使用 -
wahahachuang5:
web实时推送技术使用越来越广泛,但是自己开发又太麻烦了,我觉 ...
websocket -
dalan_123:
前提是你用的是spring mvc 才需要加的1、在web.x ...
spring+websocket的使用 -
string2020:
CharacterEncodingFilter这个filter ...
spring+websocket的使用
一、缓存
cache模块是一个go缓存管理器,目前能够支持多种缓存方式: Memory、File、Redis、Memcached等多种缓存适配模式,整体的设计想法参考'database/sql',
二、如何使用
go get -u github.com/astaxie/beego/cache
三、代码使用
1、首先要导入cache
import (
"github.com/astaxie/beego/cache"
)
2、初始化Cache
// 初始化一个内存缓存器并提供 60s进行缓存key有效检查
bm, err := cache.NewCache("memory", {"interval":60})
使用方式:
bm.Put("astaxie", 1, 10 * time.Second) // 添加
bm.Get("astaxie") // 获取
bm.IsExist("astaxie") // 存在
bm.Delete("astaxie") // 删除
注意:若是使用redis、memcached两种缓存方式需要引入对应的内容
go get -u github.com/astaxie/beego/cache/memcache // 获取memcache
go get -u github.com/gomodule/redigo/redis // 获取redis
在使用的地方引入:
import _ "github.com/astaxie/beego/cache/memcache"
import _ github.com/gomodule/redigo/redis
四、引擎设置
1.Memory引擎
配置项:
{"interval":60}
指定gc检查的时间,定时检查cache中每个item是否有效
2.Memcache引擎
Memcache引擎使用的是gomemcache.
配置项:{"key":"collectionName","conn":":6039","dbNum":"0","password":"thePassWord"}
key: Redis collection 的名称
conn: Redis 连接信息
dbNum: 连接 Redis 时的 DB 编号. 默认是0.
password: 用于连接有密码的 Redis 服务器.
3.Redis引擎
Redis引擎使用redigo.
配置项:
{"conn":":6039"}
4.file
配置项
{"CachePath":"./cache","FileSuffix":".cache","DirectoryLevel":2,"EmbedExpiry":120}
CachePath 表示缓存的文件目录,
FileSuffix 表示文件后缀,
DirectoryLevel 表示目录层级,
EmbedExpiry 表示过期设置
五、自定义cache引擎
cache 模块采用了接口的方式实现,因此用户可以很方便的实现接口,然后注册就可以实现自己的 Cache 引擎:
type Cache interface {
Get(key string) interface{}
GetMulti(keys []string) []interface{}
Put(key string, val interface{}, timeout time.Duration) error
Delete(key string) error
Incr(key string) error
Decr(key string) error
IsExist(key string) bool
ClearAll() error
StartAndGC(config string) error
}
用户开发完需要进行如下的操作: 将自定义的cache引擎注入到本地缓存中心:adapters对应的map中
func init() {
Register("newcache", NewDefineCache())
}
补充
1、redis对应的缓存包使用
import (
"fmt"
"github.com/gomodule/redigo/redis"
"log"
"time"
)
const (
REDIS_SERVER = "127.0.0.1"
REDIS_PORT = 6379
DEFAULT_KEY = "beecacheRedis"
)
type RedisPool struct {
p *redis.Pool
conninfo string
password string
maxIdle int
dbNum int
}
func NewRedisCache() RedisPool {
return RedisPool{}
}
func (rc *RedisPool) InitRedisPool() {
rc.conninfo = fmt.Sprintf("%s:%d", REDIS_SERVER, REDIS_PORT)
dialFunc := func() (conn redis.Conn, err error) {
conn, err = redis.Dial("tcp", rc.conninfo)
if err != nil {
return nil, err
}
// password
if rc.password != "" {
if _, err = conn.Do("AUTH", rc.password); err != nil {
conn.Close()
return nil, err
}
}
_, selecterr := conn.Do("SELECT", rc.dbNum)
if selecterr != nil {
conn.Close()
return nil, err
}
return
}
rc.p = &redis.Pool{
MaxIdle: 100,
IdleTimeout: 180 * time.Second,
Dial: dialFunc,
}
}
func Associate(originKey interface{}) string {
return fmt.Sprintf("%s:%s", DEFAULT_KEY, originKey)
}
func main() {
redisPool := NewRedisCache()
redisPool.InitRedisPool()
conn := redisPool.p.Get()
defer conn.Close()
resp, err := conn.Do("SET", Associate("hello"), "world")
if err != nil {
panic(err)
}
fmt.Println(resp)
resp, err = conn.Do("GET", Associate("hello"))
if err != nil {
panic(err)
}
//sresp , err := redis.Values(resp, err)
fmt.Println(redis.String(resp,err))
// add
for i:=0; i<1000; i++{
key := fmt.Sprintf("hello_%d",i)
value := fmt.Sprintf("world_%d", i)
_, err = conn.Do("SET", Associate(key),value)
if err != nil{
log.Println(err)
}
}
fmt.Println(redis.String(conn.Do("GET",Associate("hello_1"))))
var keys []interface{}
for i:=0; i < 50; i++{
key := fmt.Sprintf("hello_%d",i)
keys = append(keys, Associate(key))
}
fmt.Println(keys)
resp, err = conn.Do("MGET",[]interface{}{Associate("hello_1"),Associate("hello_2"),Associate("hello_3")}... )
fmt.Println(redis.Strings(resp, err))
resp, err = conn.Do("MGET",keys...) // 注意:mget指定key集合需要使用interface{}类型
if err != nil{
panic(err)
}
fmt.Println(redis.Strings(resp,err))
ckeys, err := redis.Strings(conn.Do("KEYS",Associate("*")))
fmt.Println(ckeys)
for _, key := range ckeys{
if _, err := conn.Do("DEL", (key)); err != nil{
log.Println(err)
}
}
fmt.Println(redis.String(conn.Do("GET",Associate("hello_999"))))
}
2、ssdb缓存包的使用
import (
"fmt"
"github.com/ssdb/gossdb/ssdb"
"log"
"math/rand"
"time"
)
func main() {
client, err := ssdb.Connect("127.0.0.1", 8888)
if err != nil {
panic(err)
}
resp, err := client.Do("set", "hello", "world")
if err != nil {
panic(err)
}
fmt.Println(resp)
// setx指令 ttl单位:s
resp, err = client.Do("setx", "hello1", "world1", int(2000*time.Millisecond/time.Second))
if err != nil {
panic(err)
}
fmt.Println(resp)
resp, err = client.Do("get", "hello")
if err != nil {
panic(err)
}
fmt.Println(resp)
//time.Sleep(2 * time.Second)
resp, err = client.Do("get", "hello1")
if err != nil {
panic(err)
}
fmt.Println(resp)
for i := 0; i < 1000; i++ {
resp, err = client.Do("set", fmt.Sprintf("hello%d", i), fmt.Sprintf("world%d", i))
if err != nil {
panic(err)
}
}
var keys []string
for i := 0; i < 50; i++ {
keys = append(keys, fmt.Sprintf("hello%d", i))
}
keys = append(keys, "hello10001")
resp, err = client.Do("multi_get", keys)
if err != nil {
panic(err)
}
fmt.Println(resp)
var values []interface{}
if err == nil {
for i := 1; i < len(resp); i += 2 {
values = append(values, resp[i+1])
}
}
fmt.Println(values)
resp, err = client.Do("get", "hello1")
if err != nil {
panic(err)
}
fmt.Println(resp)
// =============删除==============
keyStart, keyEnd, limit := "", "", 50
resp, err = client.Do("scan", keyStart, keyEnd, limit)
fmt.Println(resp)
for err == nil {
size := len(resp)
if size == 1 {
log.Println("not delete items")
break
}
keys := []string{}
for i := 1; i < size; i += 2 {
keys = append(keys, resp[i])
}
_, e := client.Do("multi_del", keys)
if e != nil {
panic(e)
}
if size > 2 {
keyStart = resp[size-2]
}
resp, err = client.Do("scan", keyStart, keyEnd, limit)
}
resp, err = client.Do("get", fmt.Sprintf("hello%d", rand.Intn(999)))
if err != nil {
panic(err)
}
fmt.Println(resp)
client.Do("incr", "counter", 1)
client.Do("incr", "counter", 1)
client.Do("incr", "counter", 1)
fmt.Println(client.Do("get", "counter"))
}
以上提供了两个直接使用对应的原始包示例,便于熟悉对应的beego中cache模块的内容
六、 源码
基本上其他实现方式 大体差异不是很大,故在此罗列ssdb的源码
package ssdb
import (
"encoding/json"
"errors"
"strconv"
"strings"
"time"
"github.com/ssdb/gossdb/ssdb"
"github.com/astaxie/beego/cache"
)
// 基于SSDB实现的缓存
// Cache SSDB adapter
type Cache struct {
conn *ssdb.Client // ssdb实例
conninfo []string // ssdb链接信息
}
//NewSsdbCache create new ssdb adapter.
func NewSsdbCache() cache.Cache { // 新建缓存
return &Cache{}
}
// 获取指定缓存key的内容
// Get get value from memcache.
func (rc *Cache) Get(key string) interface{} {
if rc.conn == nil {
if err := rc.connectInit(); err != nil { // 初始化ssdb链接
return nil
}
}
value, err := rc.conn.Get(key) // 执行查询
if err == nil {
return value
}
return nil
}
// 查询多个缓存key的内容
// GetMulti get value from memcache.
func (rc *Cache) GetMulti(keys []string) []interface{} {
size := len(keys)
var values []interface{}
if rc.conn == nil {
if err := rc.connectInit(); err != nil { // 初始化ssdb的链接
for i := 0; i < size; i++ { // 记录异常串
values = append(values, err)
}
return values
}
}
res, err := rc.conn.Do("multi_get", keys) // 执行get
resSize := len(res)
if err == nil {
for i := 1; i < resSize; i += 2 { //[ok key value key value key value] 响应结果格式
values = append(values, res[i+1])
}
return values
}
for i := 0; i < size; i++ {
values = append(values, err)
}
return values
}
// 删除多个key
// DelMulti get value from memcache.
func (rc *Cache) DelMulti(keys []string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Do("multi_del", keys) // 执行删除
return err
}
// 添加key到缓存并指定有效期
// 注意:目前只支持缓存值类型为string
// Put put value to memcache. only support string.
func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
v, ok := value.(string) // 需要保证提供的缓存值类型=string 否则会抛出error("value must string")
if !ok {
return errors.New("value must string")
}
var resp []string
var err error
ttl := int(timeout / time.Second) // 单位秒
if ttl < 0 { // 有效期<0 则对应的key一直有效
resp, err = rc.conn.Do("set", key, v)
} else { // 设置缓冲key及其有效期
resp, err = rc.conn.Do("setx", key, v, ttl)
}
if err != nil {
return err
}
if len(resp) == 2 && resp[0] == "ok" { // 解析response
return nil
}
return errors.New("bad response")
}
// 删除缓存key
// Delete delete value in memcache.
func (rc *Cache) Delete(key string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Del(key)
return err
}
// 增加缓存key计数
// Incr increase counter.
func (rc *Cache) Incr(key string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Do("incr", key, 1)
return err
}
// 减少缓存key计数
// Decr decrease counter.
func (rc *Cache) Decr(key string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Do("incr", key, -1)
return err
}
// 检查缓存key是否存在
// IsExist check value exists in memcache.
func (rc *Cache) IsExist(key string) bool {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return false
}
}
resp, err := rc.conn.Do("exists", key)
if err != nil {
return false
}
if len(resp) == 2 && resp[1] == "1" { // 响应格式:[ok 1]
return true
}
return false
}
// 清空缓存内容
// ClearAll clear all cached in memcache.
func (rc *Cache) ClearAll() error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
keyStart, keyEnd, limit := "", "", 50
resp, err := rc.Scan(keyStart, keyEnd, limit)
for err == nil { // 指定删除缓存key范围=50 防止过大影响ssdb
size := len(resp)
if size == 1 {
return nil
}
keys := []string{}
for i := 1; i < size; i += 2 {
keys = append(keys, resp[i])
}
_, e := rc.conn.Do("multi_del", keys)
if e != nil {
return e
}
keyStart = resp[size-2]
resp, err = rc.Scan(keyStart, keyEnd, limit)
}
return err
}
// 扫描指定范围的缓存key 且指定限定个数 防止对应的key量过大 导致ssdb出现问题
// Scan key all cached in ssdb.
func (rc *Cache) Scan(keyStart string, keyEnd string, limit int) ([]string, error) {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return nil, err
}
}
resp, err := rc.conn.Do("scan", keyStart, keyEnd, limit) // 执行scan操作
if err != nil {
return nil, err
}
return resp, nil
}
// 启动缓存服务并执行定期GC
// StartAndGC start memcache adapter.
// config string is like {"conn":"connection info"}.
// if connecting error, return.
func (rc *Cache) StartAndGC(config string) error {
var cf map[string]string
json.Unmarshal([]byte(config), &cf)
if _, ok := cf["conn"]; !ok { // 指定ssdb链接字符串: ip:port
return errors.New("config has no conn key")
}
rc.conninfo = strings.Split(cf["conn"], ";")
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
return nil
}
// 链接初始化 并持有
// connect to memcache and keep the connection.
func (rc *Cache) connectInit() error {
conninfoArray := strings.Split(rc.conninfo[0], ":")
host := conninfoArray[0]
port, e := strconv.Atoi(conninfoArray[1])
if e != nil {
return e
}
var err error
rc.conn, err = ssdb.Connect(host, port)
return err
}
func init() {
cache.Register("ssdb", NewSsdbCache)
}
cache模块是一个go缓存管理器,目前能够支持多种缓存方式: Memory、File、Redis、Memcached等多种缓存适配模式,整体的设计想法参考'database/sql',
二、如何使用
go get -u github.com/astaxie/beego/cache
三、代码使用
1、首先要导入cache
import (
"github.com/astaxie/beego/cache"
)
2、初始化Cache
// 初始化一个内存缓存器并提供 60s进行缓存key有效检查
bm, err := cache.NewCache("memory", {"interval":60})
使用方式:
bm.Put("astaxie", 1, 10 * time.Second) // 添加
bm.Get("astaxie") // 获取
bm.IsExist("astaxie") // 存在
bm.Delete("astaxie") // 删除
注意:若是使用redis、memcached两种缓存方式需要引入对应的内容
go get -u github.com/astaxie/beego/cache/memcache // 获取memcache
go get -u github.com/gomodule/redigo/redis // 获取redis
在使用的地方引入:
import _ "github.com/astaxie/beego/cache/memcache"
import _ github.com/gomodule/redigo/redis
四、引擎设置
1.Memory引擎
配置项:
{"interval":60}
指定gc检查的时间,定时检查cache中每个item是否有效
2.Memcache引擎
Memcache引擎使用的是gomemcache.
配置项:{"key":"collectionName","conn":":6039","dbNum":"0","password":"thePassWord"}
key: Redis collection 的名称
conn: Redis 连接信息
dbNum: 连接 Redis 时的 DB 编号. 默认是0.
password: 用于连接有密码的 Redis 服务器.
3.Redis引擎
Redis引擎使用redigo.
配置项:
{"conn":":6039"}
4.file
配置项
{"CachePath":"./cache","FileSuffix":".cache","DirectoryLevel":2,"EmbedExpiry":120}
CachePath 表示缓存的文件目录,
FileSuffix 表示文件后缀,
DirectoryLevel 表示目录层级,
EmbedExpiry 表示过期设置
五、自定义cache引擎
cache 模块采用了接口的方式实现,因此用户可以很方便的实现接口,然后注册就可以实现自己的 Cache 引擎:
type Cache interface {
Get(key string) interface{}
GetMulti(keys []string) []interface{}
Put(key string, val interface{}, timeout time.Duration) error
Delete(key string) error
Incr(key string) error
Decr(key string) error
IsExist(key string) bool
ClearAll() error
StartAndGC(config string) error
}
用户开发完需要进行如下的操作: 将自定义的cache引擎注入到本地缓存中心:adapters对应的map中
func init() {
Register("newcache", NewDefineCache())
}
补充
1、redis对应的缓存包使用
import (
"fmt"
"github.com/gomodule/redigo/redis"
"log"
"time"
)
const (
REDIS_SERVER = "127.0.0.1"
REDIS_PORT = 6379
DEFAULT_KEY = "beecacheRedis"
)
type RedisPool struct {
p *redis.Pool
conninfo string
password string
maxIdle int
dbNum int
}
func NewRedisCache() RedisPool {
return RedisPool{}
}
func (rc *RedisPool) InitRedisPool() {
rc.conninfo = fmt.Sprintf("%s:%d", REDIS_SERVER, REDIS_PORT)
dialFunc := func() (conn redis.Conn, err error) {
conn, err = redis.Dial("tcp", rc.conninfo)
if err != nil {
return nil, err
}
// password
if rc.password != "" {
if _, err = conn.Do("AUTH", rc.password); err != nil {
conn.Close()
return nil, err
}
}
_, selecterr := conn.Do("SELECT", rc.dbNum)
if selecterr != nil {
conn.Close()
return nil, err
}
return
}
rc.p = &redis.Pool{
MaxIdle: 100,
IdleTimeout: 180 * time.Second,
Dial: dialFunc,
}
}
func Associate(originKey interface{}) string {
return fmt.Sprintf("%s:%s", DEFAULT_KEY, originKey)
}
func main() {
redisPool := NewRedisCache()
redisPool.InitRedisPool()
conn := redisPool.p.Get()
defer conn.Close()
resp, err := conn.Do("SET", Associate("hello"), "world")
if err != nil {
panic(err)
}
fmt.Println(resp)
resp, err = conn.Do("GET", Associate("hello"))
if err != nil {
panic(err)
}
//sresp , err := redis.Values(resp, err)
fmt.Println(redis.String(resp,err))
// add
for i:=0; i<1000; i++{
key := fmt.Sprintf("hello_%d",i)
value := fmt.Sprintf("world_%d", i)
_, err = conn.Do("SET", Associate(key),value)
if err != nil{
log.Println(err)
}
}
fmt.Println(redis.String(conn.Do("GET",Associate("hello_1"))))
var keys []interface{}
for i:=0; i < 50; i++{
key := fmt.Sprintf("hello_%d",i)
keys = append(keys, Associate(key))
}
fmt.Println(keys)
resp, err = conn.Do("MGET",[]interface{}{Associate("hello_1"),Associate("hello_2"),Associate("hello_3")}... )
fmt.Println(redis.Strings(resp, err))
resp, err = conn.Do("MGET",keys...) // 注意:mget指定key集合需要使用interface{}类型
if err != nil{
panic(err)
}
fmt.Println(redis.Strings(resp,err))
ckeys, err := redis.Strings(conn.Do("KEYS",Associate("*")))
fmt.Println(ckeys)
for _, key := range ckeys{
if _, err := conn.Do("DEL", (key)); err != nil{
log.Println(err)
}
}
fmt.Println(redis.String(conn.Do("GET",Associate("hello_999"))))
}
2、ssdb缓存包的使用
import (
"fmt"
"github.com/ssdb/gossdb/ssdb"
"log"
"math/rand"
"time"
)
func main() {
client, err := ssdb.Connect("127.0.0.1", 8888)
if err != nil {
panic(err)
}
resp, err := client.Do("set", "hello", "world")
if err != nil {
panic(err)
}
fmt.Println(resp)
// setx指令 ttl单位:s
resp, err = client.Do("setx", "hello1", "world1", int(2000*time.Millisecond/time.Second))
if err != nil {
panic(err)
}
fmt.Println(resp)
resp, err = client.Do("get", "hello")
if err != nil {
panic(err)
}
fmt.Println(resp)
//time.Sleep(2 * time.Second)
resp, err = client.Do("get", "hello1")
if err != nil {
panic(err)
}
fmt.Println(resp)
for i := 0; i < 1000; i++ {
resp, err = client.Do("set", fmt.Sprintf("hello%d", i), fmt.Sprintf("world%d", i))
if err != nil {
panic(err)
}
}
var keys []string
for i := 0; i < 50; i++ {
keys = append(keys, fmt.Sprintf("hello%d", i))
}
keys = append(keys, "hello10001")
resp, err = client.Do("multi_get", keys)
if err != nil {
panic(err)
}
fmt.Println(resp)
var values []interface{}
if err == nil {
for i := 1; i < len(resp); i += 2 {
values = append(values, resp[i+1])
}
}
fmt.Println(values)
resp, err = client.Do("get", "hello1")
if err != nil {
panic(err)
}
fmt.Println(resp)
// =============删除==============
keyStart, keyEnd, limit := "", "", 50
resp, err = client.Do("scan", keyStart, keyEnd, limit)
fmt.Println(resp)
for err == nil {
size := len(resp)
if size == 1 {
log.Println("not delete items")
break
}
keys := []string{}
for i := 1; i < size; i += 2 {
keys = append(keys, resp[i])
}
_, e := client.Do("multi_del", keys)
if e != nil {
panic(e)
}
if size > 2 {
keyStart = resp[size-2]
}
resp, err = client.Do("scan", keyStart, keyEnd, limit)
}
resp, err = client.Do("get", fmt.Sprintf("hello%d", rand.Intn(999)))
if err != nil {
panic(err)
}
fmt.Println(resp)
client.Do("incr", "counter", 1)
client.Do("incr", "counter", 1)
client.Do("incr", "counter", 1)
fmt.Println(client.Do("get", "counter"))
}
以上提供了两个直接使用对应的原始包示例,便于熟悉对应的beego中cache模块的内容
六、 源码
基本上其他实现方式 大体差异不是很大,故在此罗列ssdb的源码
package ssdb
import (
"encoding/json"
"errors"
"strconv"
"strings"
"time"
"github.com/ssdb/gossdb/ssdb"
"github.com/astaxie/beego/cache"
)
// 基于SSDB实现的缓存
// Cache SSDB adapter
type Cache struct {
conn *ssdb.Client // ssdb实例
conninfo []string // ssdb链接信息
}
//NewSsdbCache create new ssdb adapter.
func NewSsdbCache() cache.Cache { // 新建缓存
return &Cache{}
}
// 获取指定缓存key的内容
// Get get value from memcache.
func (rc *Cache) Get(key string) interface{} {
if rc.conn == nil {
if err := rc.connectInit(); err != nil { // 初始化ssdb链接
return nil
}
}
value, err := rc.conn.Get(key) // 执行查询
if err == nil {
return value
}
return nil
}
// 查询多个缓存key的内容
// GetMulti get value from memcache.
func (rc *Cache) GetMulti(keys []string) []interface{} {
size := len(keys)
var values []interface{}
if rc.conn == nil {
if err := rc.connectInit(); err != nil { // 初始化ssdb的链接
for i := 0; i < size; i++ { // 记录异常串
values = append(values, err)
}
return values
}
}
res, err := rc.conn.Do("multi_get", keys) // 执行get
resSize := len(res)
if err == nil {
for i := 1; i < resSize; i += 2 { //[ok key value key value key value] 响应结果格式
values = append(values, res[i+1])
}
return values
}
for i := 0; i < size; i++ {
values = append(values, err)
}
return values
}
// 删除多个key
// DelMulti get value from memcache.
func (rc *Cache) DelMulti(keys []string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Do("multi_del", keys) // 执行删除
return err
}
// 添加key到缓存并指定有效期
// 注意:目前只支持缓存值类型为string
// Put put value to memcache. only support string.
func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
v, ok := value.(string) // 需要保证提供的缓存值类型=string 否则会抛出error("value must string")
if !ok {
return errors.New("value must string")
}
var resp []string
var err error
ttl := int(timeout / time.Second) // 单位秒
if ttl < 0 { // 有效期<0 则对应的key一直有效
resp, err = rc.conn.Do("set", key, v)
} else { // 设置缓冲key及其有效期
resp, err = rc.conn.Do("setx", key, v, ttl)
}
if err != nil {
return err
}
if len(resp) == 2 && resp[0] == "ok" { // 解析response
return nil
}
return errors.New("bad response")
}
// 删除缓存key
// Delete delete value in memcache.
func (rc *Cache) Delete(key string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Del(key)
return err
}
// 增加缓存key计数
// Incr increase counter.
func (rc *Cache) Incr(key string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Do("incr", key, 1)
return err
}
// 减少缓存key计数
// Decr decrease counter.
func (rc *Cache) Decr(key string) error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
_, err := rc.conn.Do("incr", key, -1)
return err
}
// 检查缓存key是否存在
// IsExist check value exists in memcache.
func (rc *Cache) IsExist(key string) bool {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return false
}
}
resp, err := rc.conn.Do("exists", key)
if err != nil {
return false
}
if len(resp) == 2 && resp[1] == "1" { // 响应格式:[ok 1]
return true
}
return false
}
// 清空缓存内容
// ClearAll clear all cached in memcache.
func (rc *Cache) ClearAll() error {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
keyStart, keyEnd, limit := "", "", 50
resp, err := rc.Scan(keyStart, keyEnd, limit)
for err == nil { // 指定删除缓存key范围=50 防止过大影响ssdb
size := len(resp)
if size == 1 {
return nil
}
keys := []string{}
for i := 1; i < size; i += 2 {
keys = append(keys, resp[i])
}
_, e := rc.conn.Do("multi_del", keys)
if e != nil {
return e
}
keyStart = resp[size-2]
resp, err = rc.Scan(keyStart, keyEnd, limit)
}
return err
}
// 扫描指定范围的缓存key 且指定限定个数 防止对应的key量过大 导致ssdb出现问题
// Scan key all cached in ssdb.
func (rc *Cache) Scan(keyStart string, keyEnd string, limit int) ([]string, error) {
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return nil, err
}
}
resp, err := rc.conn.Do("scan", keyStart, keyEnd, limit) // 执行scan操作
if err != nil {
return nil, err
}
return resp, nil
}
// 启动缓存服务并执行定期GC
// StartAndGC start memcache adapter.
// config string is like {"conn":"connection info"}.
// if connecting error, return.
func (rc *Cache) StartAndGC(config string) error {
var cf map[string]string
json.Unmarshal([]byte(config), &cf)
if _, ok := cf["conn"]; !ok { // 指定ssdb链接字符串: ip:port
return errors.New("config has no conn key")
}
rc.conninfo = strings.Split(cf["conn"], ";")
if rc.conn == nil {
if err := rc.connectInit(); err != nil {
return err
}
}
return nil
}
// 链接初始化 并持有
// connect to memcache and keep the connection.
func (rc *Cache) connectInit() error {
conninfoArray := strings.Split(rc.conninfo[0], ":")
host := conninfoArray[0]
port, e := strconv.Atoi(conninfoArray[1])
if e != nil {
return e
}
var err error
rc.conn, err = ssdb.Connect(host, port)
return err
}
func init() {
cache.Register("ssdb", NewSsdbCache)
}
发表评论
-
golang空间扩容
2019-01-08 15:47 400一、内存构成 内存管理组件构成 ... -
beego源码-config部分
2018-12-29 09:45 738写在前面beego 是一个 ... -
数据库深度解析 | 从NoSQL历史看未来(转)
2015-11-04 23:40 633http://mp.weixin.qq.com/s?__biz ... -
jedis系列
2015-08-03 13:35 0在redis如火如荼进行中,也使得我们不得不对各种redis ... -
配置多个redis
2015-06-29 15:34 1858配置多个redis客户端 <?xml version ... -
cedis
2015-06-22 21:52 802Codis 是一个分布式 Redis 解决方案, 对于 ...
相关推荐
simple-cache(文档+JAR+JAR源码)simple-cache(文档+JAR+JAR源码)simple-cache(文档+JAR+JAR源码)simple-cache(文档+JAR+JAR源码)simple-cache(文档+JAR+JAR源码)simple-cache(文档+JAR+JAR源码)simple-cache(文档+...
Beego是一个使用Go语言开发的开源框架,它旨在以Go语言的思维帮助开发者构建并开发Web应用程序。...文档还提供了源码的链接,并建议初学者先阅读快速入门部分,如果有需要,可以通过搜索邮件列表或者提问来获得帮助。
在 `beego-1.9.2.zip` 压缩包中,包含了 `beego` 框架的源码,这为我们深入理解其工作原理和扩展功能提供了可能。 ### 1. beego 框架的核心特性 - **快速开发**: `beego` 提供了丰富的中间件和工具,如路由管理、...
基于java的开发源码-HTTP代理服务器 Smart Cache.zip 基于java的开发源码-HTTP代理服务器 Smart Cache.zip 基于java的开发源码-HTTP代理服务器 Smart Cache.zip 基于java的开发源码-HTTP代理服务器 Smart Cache.zip ...
"Cache测试apk源码"是一个专门用于测试Android设备上可用缓存空间的应用,通过不断占用内存和缓存直至系统强制关闭,从而得知设备的缓存容量。 首先,我们要理解Android中的缓存类型。Android主要使用两种类型的...
这个是windows上源码编译opencv4.6.0+opencv-contrib4.6.0时候cmake时候缓存文件,只需要将压缩文件夹解压到opencv源码目录下面,cmake-gui上configure时候就不会报错,注意解压后文件夹名字是.cache,文件夹名字不能...
SpringBoot与缓存原理,整合redis、redis序列化,缓存注解、运行流程、原理讲解 配套三篇文章,推荐大家哦 https://blog.csdn.net/xiaozhegaa/article/details/110084902
本资源提供了一套基于Go和Beego的开源文库系统的设计源码,包含935个文件,其中包括291个Go源代码文件,172个GIF图片文件,以及102个PNG图片文件。此外,还包括101个JavaScript脚本文件,56个HTML页面文件,以及44个...
Android应用源码之-Image-Cache-master.zip项目安卓应用源码下载Android应用源码之-Image-Cache-master.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
这是一个基于Golang编程语言和Beego框架开发的接口在线文档管理系统源码项目,名为"Mindoc"。在本文中,我们将深入探讨这个系统的实现细节、技术栈以及如何使用和理解Beego框架。 Golang,也被称为Go语言,是Google...
5. **框架或库的限制**:vue-admin-elementui可能有一些特定的处理方式,需要查阅其文档或源码以确认是否与`noCache`设置冲突。 实现效果应为:在页面切换时,如果`noCache`设置为`true`,则浏览器会清除之前的页面...
ASP.NET 2.0是一个强大的Web应用程序开发框架,由微软公司推出,用于构建动态网站、Web应用程序和服务。...在ASPNET_Data_Tutorial_61_CS这个源码文件中,你将找到具体的实现示例,帮助你更好地理解和应用这一技术。
在这个"Memory Systems - Cache_SRAM_ddrmemorycache_memory_源码"的压缩包中,我们很可能会找到关于这些技术的源代码实现,这对于理解其工作原理和优化内存管理非常有帮助。 首先,让我们深入了解一下Cache。Cache...
1. 解压下载的源码包,例如:`tar -zxvf ngx_cache_purge-2.3.tar.gz` 或 `unzip ngx_cache_purge-master.zip`。 2. 进入解压后的目录,编译并添加到Nginx的模块列表中。这可能涉及运行`./configure --add-module=...
Beego用于Go中的企业应用程序的快速开发,包括RESTful API,Web应用程序和后端服务。 它的灵感来自龙卷风,锡纳特拉和Flask。 beego具有一些特定于Go的功能,例如接口和结构嵌入。 Beego由四个部分组成: 基本...
订餐网,外卖网源码,带积分商城,商家系统,外卖网站建设! 系统特点: 周密策划、项目为先 "项目指导技术,技术服从项目",这是我们一贯秉承的原则,也是我们与其他系统开发商、网站建设公司的本质区别所在!我们...
首先,`kafka源码导入eclipse时需要下载的cache`指的是在导入Kafka源代码到Eclipse之前,我们需要先获取并设置必要的构建依赖缓存。这些缓存通常包含了项目所需的第三方库和构建工具的本地副本,以避免每次构建时都...
这个是windows上源码编译opencv4.5.5+opencv-contrib4.5.5时候cmake时候缓存文件,只需要将压缩文件夹解压到opencv源码目录下面即可,cmake-gui上configure时候就不会报错,注意解压后文件夹名字是.cache,文件夹名字...
电商微信小程序源码+后台分享,亲测可用,有需要的朋友拿去!!! 电商微信小程序源码+后台分享,亲测可用,有需要的朋友拿去!!! 电商微信小程序源码+后台分享,亲测可用,有需要的朋友拿去!!! 电商微信小程序...
这个是windows上源码编译opencv4.9.0+opencv-contrib4.9.0时候cmake时候缓存文件,只需要将压缩文件夹解压到源码目录下面,cmake-gui上configure时候就不会报错,注意解压后文件夹名字是.cache,文件夹名字不能改变,...