当前位置: 代码迷 >> 综合 >> Go解析php-mem扩展写入的数据(序列化+zlib)
  详细解决方案

Go解析php-mem扩展写入的数据(序列化+zlib)

热度:4   发布时间:2024-01-18 10:58:38.0

原因:工作中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 mainimport ("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#L101const 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.5MBfunc 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.ErrCacheMissreturn 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 bytedataLength := 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
}

记录下学习下

  相关解决方案