原因:工作中php使用mem,有直接jsonencode方式的写入,使用目前的mem插件就能很好的去读,但是php中可以直接写入mem一个数组类型,这种情况,php-mem扩展会先进行自身的序列化然后zlib存储到mem中,Go取出的数据,二进制使用binary解析出为乱码,问题进行解决

找到一个git源

How to read fastlz or zlib php compressed memcache key from go · GitHub

package main

import (
	"encoding/binary"
	"errors"
	"github.com/bradfitz/gomemcache/memcache"
	"github.com/digitalcrab/fastlz"
)

// 这个地址需要认真看下,只有看了这个才知道 怎么区分 两种压缩方式 see https://github.com/php-memcached-dev/php-memcached/blob/master/php_memcached.c#L101

const MEMC_VAL_COMPRESSED = (1 << 0)                           // 1
const MEMC_VAL_COMPRESSION_ZLIB = (1 << 1)                     // 10
const MEMC_VAL_COMPRESSION_FASTLZ = (1 << 2)                   // 100
const MAX_MEMORY_ALLOWED_FOR_MEMCACHE uint = 1024 * 1024 * 1.5 // 1.5MB

func GetDataFromCache(cacheKey string) (data []byte, err error) {
	var decompressedValue []byte  
	
	returnData, err := MemcacheClient.Get(cacheKey)

	if err != nil {
		// maybe pass the original error if err != memcache.ErrCacheMiss
		return nil, errors.New("Cache key not found or get action failed")
	}

	if returnData.Flags > 0 &&
		((returnData.Flags>>4)&MEMC_VAL_COMPRESSED) > 0 &&
		((returnData.Flags>>4)&MEMC_VAL_COMPRESSION_FASTLZ) > 0 {

        //前4个字节存储的是数据长度,需要单独截取出来,解析出错的原因根本所在找到了,后续处理的问题就简单了,GO默认是小端的获取数据方式
		// first 4 bytes contain the length in little endian format (right to left), the content starts from the 5th byte
		dataLength := uint(binary.LittleEndian.Uint32(returnData.Value[:4]))
		if dataLength > MAX_MEMORY_ALLOWED_FOR_MEMCACHE {
			return nil, errors.New("Could not uncompress data, too large")
		}

		decompressedValue, err = fastlz.Decompress(returnData.Value[4:], dataLength)
		if err != nil {
			return nil, err
		}

		return decompressedValue, nil
	} else if returnData.Flags > 0 &&
		((returnData.Flags>>4)&MEMC_VAL_COMPRESSED) > 0 &&
		((returnData.Flags>>4)&MEMC_VAL_COMPRESSION_ZLIB) > 0 {
		
		// you will need to implement it, but most probably
		// it will be in the same format with the first 4 bytes representing
		// the length and the rest being the data. See https://golang.org/pkg/compress/zlib/
        //这块儿作者没有实现,自己也可以比较容易的实现,同fashlz方式
	}

	return returnData.Value, nil
}

func main () {
  // you need to connect to memcache here
}

记录下学习下

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐