xunch 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/xunch.rb +25 -0
- data/lib/xunch/cache/cache.rb +88 -0
- data/lib/xunch/cache/cache_builder.rb +68 -0
- data/lib/xunch/cache/field_object_cache.rb +120 -0
- data/lib/xunch/cache/list_field_object_cache.rb +63 -0
- data/lib/xunch/cache/list_object_cache.rb +59 -0
- data/lib/xunch/cache/object_cache.rb +63 -0
- data/lib/xunch/codec/codec.rb +31 -0
- data/lib/xunch/codec/hash_codec.rb +98 -0
- data/lib/xunch/codec/json_codec.rb +81 -0
- data/lib/xunch/shard/redis.rb +270 -0
- data/lib/xunch/shard/shard_info.rb +37 -0
- data/lib/xunch/shard/shard_redis.rb +267 -0
- data/lib/xunch/shard/sharded.rb +50 -0
- data/lib/xunch/utils/exceptions.rb +11 -0
- data/lib/xunch/utils/nginx_cache_helper.rb +52 -0
- data/lib/xunch/utils/rb_tree.rb +634 -0
- data/lib/xunch/utils/rb_tree_node.rb +67 -0
- data/lib/xunch/utils/types.rb +8 -0
- data/lib/xunch/utils/utils.rb +24 -0
- data/test/benchmark_test.rb +68 -0
- data/test/cache_builder_test.rb +28 -0
- data/test/cache_object.rb +120 -0
- data/test/consistency_hash_test.rb +31 -0
- data/test/field_object_cache_test.rb +430 -0
- data/test/hash_codec_test.rb +57 -0
- data/test/json_codec_test.rb +57 -0
- data/test/list_field_object_cache_test.rb +211 -0
- data/test/list_object_cache_test.rb +211 -0
- data/test/nginx_cache_helper_test.rb +45 -0
- data/test/object_cache_test.rb +322 -0
- data/test/rb_tree_test.rb +48 -0
- data/test/redis_benchmark_test.rb +54 -0
- data/test/redis_test.rb +58 -0
- data/test/running_test.rb +212 -0
- data/test/test.rb +176 -0
- data/test/track_record_origin.rb +58 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 11095eadd1ac6cf93128811cd1bab2d818e345b1
|
4
|
+
data.tar.gz: 8e60835af4879fd33dfa4fe7cfc67d009548d5c2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6b7ca3c02e48930d5d7b551a8393c677493d3ac74ba6dc69fbf54249233ff2804d62f353e93324b62449b255b76635e39d25a8a4ba98dca17ee3a697e9d934fa
|
7
|
+
data.tar.gz: fed73c21df8039c4622c9ca91328f66aa5cc933f61a2230af0bd5c870804b41a1e502abeee45f875652168bcb04158947c2a2c1a6f734e183351d69f8e1041a3
|
data/lib/xunch.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'yajl'
|
2
|
+
require 'date'
|
3
|
+
require 'bigdecimal'
|
4
|
+
require 'murmurhash'
|
5
|
+
require 'redis'
|
6
|
+
require 'yaml'
|
7
|
+
require 'xunch/utils/rb_tree'
|
8
|
+
require 'xunch/utils/rb_tree_node'
|
9
|
+
require 'xunch/utils/exceptions'
|
10
|
+
require 'xunch/utils/types'
|
11
|
+
require 'xunch/utils/utils'
|
12
|
+
require 'xunch/utils/nginx_cache_helper'
|
13
|
+
require 'xunch/shard/shard_info'
|
14
|
+
require 'xunch/shard/sharded'
|
15
|
+
require 'xunch/shard/shard_redis'
|
16
|
+
require 'xunch/shard/redis'
|
17
|
+
require 'xunch/codec/codec'
|
18
|
+
require 'xunch/codec/json_codec'
|
19
|
+
require 'xunch/codec/hash_codec'
|
20
|
+
require 'xunch/cache/cache'
|
21
|
+
require 'xunch/cache/object_cache'
|
22
|
+
require 'xunch/cache/field_object_cache'
|
23
|
+
require 'xunch/cache/list_field_object_cache'
|
24
|
+
require 'xunch/cache/list_object_cache'
|
25
|
+
require 'xunch/cache/cache_builder'
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Xunch
|
2
|
+
class Cache
|
3
|
+
|
4
|
+
def initialize(options, shard_infos)
|
5
|
+
@options = initialize_options(options)
|
6
|
+
@shard_redis = ShardRedis.new(@options[:regex],shard_infos)
|
7
|
+
end
|
8
|
+
|
9
|
+
def evict(key)
|
10
|
+
@shard_redis.del(assembleKey(key))
|
11
|
+
end
|
12
|
+
|
13
|
+
def batch_evict(keys)
|
14
|
+
new_keys = []
|
15
|
+
keys.each { |key|
|
16
|
+
new_keys.push assembleKey(key)
|
17
|
+
}
|
18
|
+
@shard_redis.batch_del(new_keys)
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy
|
22
|
+
@shard_redis.destroy
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
def getCacheObjectKey(value)
|
27
|
+
key = value.send(@options[:key_field_name])
|
28
|
+
raise ArgumentError("value #{value} key field can not be nil.") unless key != nil
|
29
|
+
key
|
30
|
+
end
|
31
|
+
|
32
|
+
def assembleKey(key)
|
33
|
+
name = @options[:name]
|
34
|
+
name + "_".concat(key.to_s).concat("_").concat(@options[:version].to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
def assembleTempKey(key)
|
38
|
+
name = @options[:name]
|
39
|
+
name + "_".concat(key.to_s).concat("_").concat(@options[:version].to_s).concat("_temp")
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize_options(options)
|
43
|
+
use_options = {}
|
44
|
+
expire_time = 60 * 60 * 24 * 1000
|
45
|
+
if(options["expire_time"] != nil)
|
46
|
+
expire_time = options["expire_time"]
|
47
|
+
end
|
48
|
+
use_options.store(:expire_time, expire_time)
|
49
|
+
|
50
|
+
if(options["cache_class"] != nil)
|
51
|
+
cache_class = eval(options["cache_class"])
|
52
|
+
elsif options["type"] != CacheType::LISTOBJECT && options["type"] != CacheType::LISTFIELDOBJECT
|
53
|
+
raise ArgumentError, "cache_class is nil"
|
54
|
+
end
|
55
|
+
use_options.store(:cache_class, cache_class)
|
56
|
+
|
57
|
+
version = 1
|
58
|
+
if(options["version"] != nil)
|
59
|
+
version = options["version"]
|
60
|
+
use_options.store(:version, version)
|
61
|
+
end
|
62
|
+
|
63
|
+
if(options["name"] != nil)
|
64
|
+
name = options["name"]
|
65
|
+
use_options.store(:name, name)
|
66
|
+
end
|
67
|
+
|
68
|
+
if(options["key_field_name"] != nil)
|
69
|
+
key_field_name = options["key_field_name"]
|
70
|
+
use_options.store(:key_field_name, key_field_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
if(options["timeout"] != nil)
|
74
|
+
timeout = options["timeout"]
|
75
|
+
use_options.store(:timeout, timeout)
|
76
|
+
end
|
77
|
+
|
78
|
+
regex = '[0-9]+'
|
79
|
+
if(options["regex"] != nil)
|
80
|
+
regex = options["regex"]
|
81
|
+
end
|
82
|
+
use_options.store(:regex, regex)
|
83
|
+
|
84
|
+
return use_options
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Xunch
|
2
|
+
class CacheBuilder
|
3
|
+
# every cache config hava attributes below:
|
4
|
+
# ['type'] => the cache type, have object|field_object|list_object
|
5
|
+
# ['name'] => the cache name, used for redis key prefix
|
6
|
+
# ['version'] => the cache version, maybe you change your cache object format and you will change a version of the cache
|
7
|
+
# ['expire_time'] => cache expire time for every key in millisecond
|
8
|
+
# ['cache_class'] => which type of object you cache, this will help us to encode/decode your object
|
9
|
+
# ['key_field_name'] => define which field in the object we used for redis key
|
10
|
+
# ['regex'] => a regex string which used for match consistency hash key
|
11
|
+
# ['shard_infos'] => define which redis instance we used for caching
|
12
|
+
#
|
13
|
+
#
|
14
|
+
def self.build(file)
|
15
|
+
configs = YAML.load_file(file)
|
16
|
+
shard_info_configs = configs["shard_infos"]
|
17
|
+
cache_configs = configs["caches"]
|
18
|
+
|
19
|
+
shards = {}
|
20
|
+
shard_info_configs.each_value { |shard_info_config|
|
21
|
+
options = {}
|
22
|
+
shard_info_config.each { |k,v|
|
23
|
+
options[k.to_sym] = v
|
24
|
+
}
|
25
|
+
shards[options[:name]] = ShardInfo.new(options)
|
26
|
+
}
|
27
|
+
caches = {}
|
28
|
+
lazy_caches = {}
|
29
|
+
cache_configs.each_value { |cache_config|
|
30
|
+
shard_names = cache_config["shards"].split(",")
|
31
|
+
shard_infos = []
|
32
|
+
shard_names.each { |shard_name|
|
33
|
+
shard_infos.push(shards[shard_name])
|
34
|
+
}
|
35
|
+
case cache_config["type"]
|
36
|
+
when CacheType::OBJECT
|
37
|
+
cache = Xunch::ObjectCache.new(cache_config,shard_infos)
|
38
|
+
caches[cache_config["name"]] = cache
|
39
|
+
when CacheType::FIELDOBJECT
|
40
|
+
cache = Xunch::FieldObjectCache.new(cache_config,shard_infos)
|
41
|
+
caches[cache_config["name"]] = cache
|
42
|
+
when CacheType::LISTOBJECT
|
43
|
+
lazy_caches[cache_config] = shard_infos
|
44
|
+
when CacheType::LISTFIELDOBJECT
|
45
|
+
lazy_caches[cache_config] = shard_infos
|
46
|
+
else
|
47
|
+
raise XunchConfigError.new("Unknown cache type #{cache_config["type"]}.")
|
48
|
+
end
|
49
|
+
}
|
50
|
+
lazy_caches.each { |cache_config,shard_infos|
|
51
|
+
delegate = caches[cache_config["delegate"]]
|
52
|
+
raise XunchConfigError.new("list_cache init error, delegate does not exist.") unless delegate != nil
|
53
|
+
cache = nil
|
54
|
+
case cache_config["type"]
|
55
|
+
when CacheType::LISTOBJECT
|
56
|
+
cache = Xunch::ListObjectCache.new(cache_config,shard_infos,delegate)
|
57
|
+
when CacheType::LISTFIELDOBJECT
|
58
|
+
cache = Xunch::ListFieldObjectCache.new(cache_config,shard_infos,delegate)
|
59
|
+
else
|
60
|
+
raise XunchConfigError.new("Unknown cache type #{cache_config["type"]}.")
|
61
|
+
end
|
62
|
+
|
63
|
+
caches[cache_config["name"]] = cache
|
64
|
+
}
|
65
|
+
caches
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Xunch
|
2
|
+
#
|
3
|
+
#
|
4
|
+
#
|
5
|
+
#
|
6
|
+
class FieldObjectCache < Cache
|
7
|
+
|
8
|
+
def initialize(options, shard_infos)
|
9
|
+
super
|
10
|
+
fields = options['fields']
|
11
|
+
if fields == nil
|
12
|
+
raise XunchConfigError.new("fields can not be nil")
|
13
|
+
end
|
14
|
+
fields_array = fields.split(",")
|
15
|
+
if fields_array.length == 1 and fields_array[0].strip.empty?
|
16
|
+
raise XunchConfigError.new("fields config error")
|
17
|
+
end
|
18
|
+
formatted_fields_array = Utils.format_fields(fields_array)
|
19
|
+
@fields_array = formatted_fields_array
|
20
|
+
@codec = HashCodec.new(@options[:cache_class],formatted_fields_array)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(key)
|
24
|
+
redis_key = assembleKey(key)
|
25
|
+
data = @shard_redis.mapped_hget(redis_key,@fields_array)
|
26
|
+
@codec.decode(data)
|
27
|
+
end
|
28
|
+
|
29
|
+
def put(value)
|
30
|
+
putex(value,@options[:expire_time])
|
31
|
+
end
|
32
|
+
|
33
|
+
def putex(value, ttl)
|
34
|
+
if(value == nil)
|
35
|
+
return
|
36
|
+
end
|
37
|
+
key = getCacheObjectKey(value)
|
38
|
+
key = assembleKey(key)
|
39
|
+
data = @codec.encode(value)
|
40
|
+
@shard_redis.hsetall(key,data,ttl)
|
41
|
+
end
|
42
|
+
|
43
|
+
def multi_get(keys)
|
44
|
+
redis_keys = Array.new(keys.length)
|
45
|
+
for i in 0 .. keys.length - 1 do
|
46
|
+
redis_keys[i] = assembleKey(keys[i])
|
47
|
+
end
|
48
|
+
datas = @shard_redis.mapped_hmget(redis_keys,@fields_array)
|
49
|
+
for i in 0 .. datas.length - 1 do
|
50
|
+
datas[i] = @codec.decode(datas[i])
|
51
|
+
end
|
52
|
+
return datas
|
53
|
+
end
|
54
|
+
|
55
|
+
def multi_put(values)
|
56
|
+
multi_putex(values,@options[:expire_time])
|
57
|
+
end
|
58
|
+
|
59
|
+
def multi_putex(values,ttl)
|
60
|
+
kvs = Hash.new
|
61
|
+
values.each { | value |
|
62
|
+
if value == nil
|
63
|
+
next
|
64
|
+
end
|
65
|
+
key = getCacheObjectKey(value)
|
66
|
+
redis_key = assembleKey(key);
|
67
|
+
kvs[redis_key] = @codec.encode(value);
|
68
|
+
}
|
69
|
+
@shard_redis.hmsetall(kvs, ttl);
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_with_field(key, fields)
|
73
|
+
redis_key = assembleKey(key)
|
74
|
+
data = @shard_redis.mapped_hget(redis_key,fields)
|
75
|
+
@codec.decode_fields(data,fields)
|
76
|
+
end
|
77
|
+
|
78
|
+
def put_with_field(value, fields)
|
79
|
+
put_with_field_ex(value,@options[:expire_time],fields)
|
80
|
+
end
|
81
|
+
|
82
|
+
def put_with_field_ex(value, ttl, fields)
|
83
|
+
if(value == nil)
|
84
|
+
return
|
85
|
+
end
|
86
|
+
key = getCacheObjectKey(value)
|
87
|
+
key = assembleKey(key)
|
88
|
+
data = @codec.encode_fields(value,fields)
|
89
|
+
@shard_redis.hsetall(key,data,ttl)
|
90
|
+
end
|
91
|
+
|
92
|
+
def multi_put_with_field_ex(values, ttl, fields)
|
93
|
+
kvs = Hash.new
|
94
|
+
values.each { | value |
|
95
|
+
if value == nil
|
96
|
+
next
|
97
|
+
end
|
98
|
+
key = getCacheObjectKey(value)
|
99
|
+
key = assembleKey(key);
|
100
|
+
kvs[key] = @codec.encode_fields(value,fields);
|
101
|
+
}
|
102
|
+
@shard_redis.hmsetall(kvs, ttl);
|
103
|
+
end
|
104
|
+
|
105
|
+
def multi_put_with_field(values, fields)
|
106
|
+
multi_put_with_field_ex(values,@options[:expire_time],fields)
|
107
|
+
end
|
108
|
+
|
109
|
+
def multi_get_with_field(keys, fields)
|
110
|
+
for i in 0 .. keys.length - 1 do
|
111
|
+
keys[i] = assembleKey(keys[i])
|
112
|
+
end
|
113
|
+
datas = @shard_redis.mapped_hmget(keys,fields)
|
114
|
+
for i in 0 .. datas.length - 1 do
|
115
|
+
datas[i] = @codec.decode_fields(datas[i],fields)
|
116
|
+
end
|
117
|
+
return datas
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Xunch
|
2
|
+
#列表缓存目前不支持并发写入,未来也不打算支持并发
|
3
|
+
#主要的使用场景是发现页热门的单线程写入和并发的读取
|
4
|
+
#并且提供remove接口,帮助从列表中移除已经不存在的声音,用户,专辑
|
5
|
+
class ListFieldObjectCache < Cache
|
6
|
+
|
7
|
+
def initialize(options, shard_infos, object_cache)
|
8
|
+
super(options,shard_infos)
|
9
|
+
@delegate = object_cache
|
10
|
+
end
|
11
|
+
|
12
|
+
# 查询接口
|
13
|
+
# @key 列表的key
|
14
|
+
# @page 页码
|
15
|
+
# @size 页大小
|
16
|
+
#
|
17
|
+
def get(key, page, size)
|
18
|
+
raise "key can not be nil." unless key != nil
|
19
|
+
raise "page must be a positive number." unless page > 0
|
20
|
+
raise "size must be a positive number and less than 100." unless page != nil or size < 100
|
21
|
+
start = (page - 1) * size;
|
22
|
+
stop = page * size - 1;
|
23
|
+
new_key = assembleKey(key)
|
24
|
+
object_keys = @shard_redis.lrange(new_key,start,stop)
|
25
|
+
hash = {}
|
26
|
+
hash["keys"] = object_keys
|
27
|
+
hash["values"] = @delegate.multi_get(object_keys)
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def put(key, values)
|
32
|
+
raise "key can not be nil." unless key != nil
|
33
|
+
raise "values can not be nil." unless values != nil
|
34
|
+
sub_keys = []
|
35
|
+
values.each { | value |
|
36
|
+
raise "value in values can not be nil." unless value != nil
|
37
|
+
sub_keys.push(@delegate.getCacheObjectKey(value))
|
38
|
+
}
|
39
|
+
temp_key = assembleTempKey(key)
|
40
|
+
new_key = assembleKey(key)
|
41
|
+
@delegate.multi_putex(values,@options[:expire_time])
|
42
|
+
@shard_redis.lset(temp_key,new_key,sub_keys,@options[:expire_time])
|
43
|
+
end
|
44
|
+
|
45
|
+
def remove(key, sub_key)
|
46
|
+
raise "key can not be nil." unless key != nil
|
47
|
+
raise "sub_key can not be nil." unless sub_key != nil
|
48
|
+
new_key = assembleKey(key)
|
49
|
+
@shard_redis.lremove(new_key,sub_key)
|
50
|
+
end
|
51
|
+
|
52
|
+
def size(key)
|
53
|
+
raise "key can not be nil." unless key != nil
|
54
|
+
new_key = assembleKey(key)
|
55
|
+
@shard_redis.llen(new_key)
|
56
|
+
end
|
57
|
+
|
58
|
+
def delegate
|
59
|
+
@delegate
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Xunch
|
2
|
+
#列表缓存目前不支持并发写入,未来也不打算支持并发
|
3
|
+
#主要的使用场景是发现页热门的单线程写入和并发的读取
|
4
|
+
#并且提供remove接口,帮助从列表中移除已经不存在的声音,用户,专辑
|
5
|
+
class ListObjectCache < Cache
|
6
|
+
|
7
|
+
def initialize(options, shard_infos, object_cache)
|
8
|
+
super(options,shard_infos)
|
9
|
+
@delegate = object_cache
|
10
|
+
end
|
11
|
+
|
12
|
+
# 查询接口
|
13
|
+
# @key 列表的key
|
14
|
+
# @page 页码
|
15
|
+
# @size 页大小
|
16
|
+
#
|
17
|
+
def get(key, page, size)
|
18
|
+
raise "key can not be nil." unless key != nil
|
19
|
+
raise "page must be a positive number." unless page > 0
|
20
|
+
raise "size must be a positive number and less than 100." unless page != nil or size < 100
|
21
|
+
start = (page - 1) * size;
|
22
|
+
stop = page * size - 1;
|
23
|
+
new_key = assembleKey(key)
|
24
|
+
object_keys = @shard_redis.lrange(new_key,start,stop)
|
25
|
+
hash = {}
|
26
|
+
hash["keys"] = object_keys
|
27
|
+
hash["values"] = @delegate.multi_get(object_keys)
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def put(key, values)
|
32
|
+
raise "key can not be nil." unless key != nil
|
33
|
+
raise "values can not be nil." unless values != nil
|
34
|
+
sub_keys = []
|
35
|
+
values.each { | value |
|
36
|
+
raise "value in values can not be nil." unless value != nil
|
37
|
+
sub_keys.push(@delegate.getCacheObjectKey(value))
|
38
|
+
}
|
39
|
+
temp_key = assembleTempKey(key)
|
40
|
+
new_key = assembleKey(key)
|
41
|
+
@delegate.multi_putex(values,@options[:expire_time])
|
42
|
+
@shard_redis.lset(temp_key,new_key,sub_keys,@options[:expire_time])
|
43
|
+
end
|
44
|
+
|
45
|
+
def remove(key, sub_key)
|
46
|
+
raise "key can not be nil." unless key != nil
|
47
|
+
raise "sub_key can not be nil." unless sub_key != nil
|
48
|
+
new_key = assembleKey(key)
|
49
|
+
@shard_redis.lremove(new_key,sub_key)
|
50
|
+
end
|
51
|
+
|
52
|
+
def size(key)
|
53
|
+
raise "key can not be nil." unless key != nil
|
54
|
+
new_key = assembleKey(key)
|
55
|
+
@shard_redis.llen(new_key)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Xunch
|
2
|
+
class ObjectCache < Cache
|
3
|
+
|
4
|
+
def initialize(options, shard_infos)
|
5
|
+
super
|
6
|
+
@codec = JsonCodec.new(@options[:cache_class])
|
7
|
+
end
|
8
|
+
|
9
|
+
def get(key)
|
10
|
+
redis_key = assembleKey(key)
|
11
|
+
data = @shard_redis.get(redis_key)
|
12
|
+
if data != nil
|
13
|
+
@codec.decode(data)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def put(value)
|
18
|
+
putex(value,@options[:expire_time])
|
19
|
+
end
|
20
|
+
|
21
|
+
def putex(value, ttl)
|
22
|
+
if(value == nil)
|
23
|
+
return
|
24
|
+
end
|
25
|
+
key = getCacheObjectKey(value)
|
26
|
+
key = assembleKey(key)
|
27
|
+
data = @codec.encode(value)
|
28
|
+
@shard_redis.set(key,data,ttl.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
def multi_get(keys)
|
32
|
+
redis_keys = Array.new(keys.length)
|
33
|
+
for i in 0 .. keys.length - 1 do
|
34
|
+
redis_keys[i] = assembleKey(keys[i])
|
35
|
+
end
|
36
|
+
datas = @shard_redis.mget(redis_keys)
|
37
|
+
for i in 0 .. datas.length - 1 do
|
38
|
+
if datas[i] != nil
|
39
|
+
datas[i] = @codec.decode(datas[i])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
datas
|
43
|
+
end
|
44
|
+
|
45
|
+
def multi_put(values)
|
46
|
+
multi_putex(values,@options[:expire_time])
|
47
|
+
end
|
48
|
+
|
49
|
+
def multi_putex(values,ttl)
|
50
|
+
kvs = Hash.new
|
51
|
+
values.each { | value |
|
52
|
+
if value == nil
|
53
|
+
next
|
54
|
+
end
|
55
|
+
key = getCacheObjectKey(value)
|
56
|
+
key = assembleKey(key);
|
57
|
+
kvs[key] = @codec.encode(value);
|
58
|
+
}
|
59
|
+
@shard_redis.mset(kvs, ttl);
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|