Class: Memcached
The Memcached client class.
Child modules and classes
Class Memcached::Error
Class Memcached::Rails
Constants
| Name | Value |
|---|---|
| FLAGS | 0x0 |
| DEFAULTS | { :hash => :default, :no_block => false, :distribution => :consistent, :buffer_requests => false, :cache_lookups => true, :support_cas => false, :tcp_nodelay => false, :show_not_found_backtraces => false, :retry_timeout => 60, # :poll_timeout => 5, :connect_timeout => 5, :prefix_key => nil, :sort_hosts => false, :failover => false, :verify_key => true |
| Lib | Rlibmemcached |
| REQUIRED_VERSION | File.read("#{File.dirname(__FILE__)}/../COMPATIBILITY")[/:: ([\d\.]+)/, 1] |
| RECEIVED_VERSION | Lib.memcached_lib_version |
Attributes
| Name | Read/write? |
|---|---|
| options | R |
Public Class Methods
new (servers, opts = {})
Create a new Memcached instance. Accepts a single server string such as ‘localhost:11211’, or an array of such strings, as well an an optional configuration hash.
Valid option parameters are:
| :prefix_key: | A string to prepend to every key, for namespacing. Max length is 11. |
| :hash: | The name of a hash function to use. Possible values are: :crc, :default, :fnv1_32, :fnv1_64, :fnv1a_32, :fnv1a_64, :hsieh, :md5, and :murmur. :default is the fastest. Use :md5 for compatibility with other ketama clients. |
| :distribution: | Either :modula, :consistent, or :consistent_wheel. Defaults to :consistent, which is ketama-compatible. |
| :failover: | Whether to permanently eject failed hosts from the pool. Defaults to false. Note that in the event of a server failure, :failover will remap the entire pool unless :distribution is set to :consistent. |
| :cache_lookups: | Whether to cache hostname lookups for the life of the instance. Defaults to true. |
| :support_cas: | Flag CAS support in the client. Accepts true or false. Defaults to false because it imposes a slight performance penalty. Note that your server must also support CAS or you will trigger Memcached::ProtocolError exceptions. |
| :tcp_nodelay: | Turns on the no-delay feature for connecting sockets. Accepts true or false. Performance may or may not change, depending on your system. |
| :no_block: | Whether to use non-blocking, asynchronous IO for writes. Accepts true or false. |
| :buffer_requests: | Whether to use an internal write buffer. Accepts true or false. Calling get or closing the connection will force the buffer to flush. Note that :buffer_requests might not work well without :no_block also enabled. |
| :show_not_found_backtraces: | Whether Memcached::NotFound exceptions should include backtraces. Generating backtraces is slow, so this is off by default. Turn it on to ease debugging. |
| :sort_hosts: | Whether to force the server list to stay sorted. This defeats consistent hashing and is rarely useful. |
| :verify_key: | Validate keys before accepting them. Never disable this. |
Please note that when non-blocking IO is enabled, setter and deleter methods do not raise on errors. For example, if you try to set an invalid key with :no_block => true, it will appear to succeed. The actual setting of the key occurs after libmemcached has returned control to your program, so there is no way to backtrack and raise the exception.
# File lib/memcached/memcached.rb, line 59 59: def initialize(servers, opts = {}) 60: @struct = Lib::MemcachedSt.new 61: Lib.memcached_create(@struct) 62: 63: # Merge option defaults 64: @options = DEFAULTS.merge(opts) 65: 66: # Force :buffer_requests to use :no_block 67: # XXX Deleting the :no_block key should also work, but libmemcached doesn't seem to set it 68: # consistently 69: options[:no_block] = true if options[:buffer_requests] 70: 71: # Legacy accessor 72: options[:prefix_key] = options.delete(:namespace) if options[:namespace] 73: 74: # Disallow :sort_hosts with consistent hashing 75: if options[:sort_hosts] and options[:distribution] == :consistent 76: raise ArgumentError, ":sort_hosts defeats :consistent hashing" 77: end 78: 79: # Set the behaviors on the struct 80: set_behaviors 81: set_callbacks 82: 83: # Freeze the hash 84: options.freeze 85: 86: # Set the servers on the struct 87: set_servers(servers) 88: 89: # Not found exceptions 90: # Note that these have global effects since the NotFound class itself is modified. You should only 91: # be enabling the backtrace for debugging purposes, so it's not really a big deal. 92: if options[:show_not_found_backtraces] 93: NotFound.restore_backtraces 94: else 95: NotFound.remove_backtraces 96: end 97: end
Public Instance Methods
add (key, value, timeout=0, marshal=true)
Add a key/value pair. Raises Memcached::NotStored if the key already exists on the server. The parameters are the same as set.
# File lib/memcached/memcached.rb, line 164 164: def add(key, value, timeout=0, marshal=true) 165: value = marshal ? Marshal.dump(value) : value.to_s 166: check_return_code( 167: Lib.memcached_add(@struct, key, value, timeout, FLAGS) 168: ) 169: end
append (key, value)
Appends a string to a key‘s value. Accepts a String key and a String value. Raises Memcached::NotFound if the key does not exist on the server.
Note that the key must be initialized to an unmarshalled string first, via set, add, or replace with marshal set to false.
# File lib/memcached/memcached.rb, line 205 205: def append(key, value) 206: # Requires memcached 1.2.4 207: check_return_code( 208: Lib.memcached_append(@struct, key, value.to_s, IGNORED, FLAGS) 209: ) 210: end
cas (key, timeout = 0, marshal = true) {|value| ...}
Reads a key‘s value from the server and yields it to a block. Replaces the key‘s value with the result of the block as long as the key hasn‘t been updated in the meantime, otherwise raises Memcached::NotStored. Accepts a String key and a block.
Also accepts an optional timeout value.
CAS stands for "compare and swap", and avoids the need for manual key mutexing. CAS support must be enabled in Memcached.new or a Memcached::ClientError will be raised. Note that CAS may be buggy in memcached itself.
# File lib/memcached/memcached.rb, line 226 226: def cas(key, timeout = 0, marshal = true) 227: raise ClientError, "CAS not enabled for this Memcached instance" unless options[:support_cas] 228: 229: value = get(key, marshal) 230: value = yield value 231: value = marshal ? Marshal.dump(value) : value.to_s 232: 233: check_return_code( 234: Lib.memcached_cas(@struct, key, value, timeout, FLAGS, @struct.result.cas) 235: ) 236: end
clone ()
Safely copy this instance. Returns a Memcached instance.
clone is useful for threading, since each thread must have its own unshared Memcached object.
# File lib/memcached/memcached.rb, line 111 111: def clone 112: memcached = super 113: memcached.instance_variable_set('@struct', Lib.memcached_clone(nil, @struct)) 114: memcached 115: end
decrement (key, offset=1)
Decrement a key‘s value. The parameters and exception behavior are the same as increment.
# File lib/memcached/memcached.rb, line 183 183: def decrement(key, offset=1) 184: ret, value = Lib.memcached_decrement(@struct, key, offset) 185: check_return_code(ret) 186: value 187: end
delete (key)
Deletes a key/value pair from the server. Accepts a String key. Raises Memcached::NotFound if the key does not exist.
# File lib/memcached/memcached.rb, line 241 241: def delete(key) 242: check_return_code( 243: Lib.memcached_delete(@struct, key, IGNORED) 244: ) 245: end
flush ()
Flushes all key/value pairs from all the servers.
# File lib/memcached/memcached.rb, line 248 248: def flush 249: check_return_code( 250: Lib.memcached_flush(@struct, IGNORED) 251: ) 252: end
get (keys, marshal=true)
Gets a key‘s value from the server. Accepts a String key or array of String keys.
Also accepts a marshal value, which defaults to true. Set marshal to false if you want the value to be returned directly as a String. Otherwise it will be assumed to be a marshalled Ruby object and unmarshalled.
If you pass a String key, and the key does not exist on the server, Memcached::NotFound will be raised. If you pass an array of keys, memcached‘s multiget mode will be used, and a hash of key/value pairs will be returned. The hash will contain only the keys that were found.
The multiget behavior is subject to change in the future; however, for multiple lookups, it is much faster than normal mode.
Note that when you rescue Memcached::NotFound exceptions, you should use a the block rescue syntax instead of the inline syntax. Block rescues are very fast, but inline rescues are very slow.
# File lib/memcached/memcached.rb, line 266 266: def get(keys, marshal=true) 267: if keys.is_a? Array 268: # Multi get 269: keys.map! { |key| key } 270: hash = {} 271: 272: ret = Lib.memcached_mget(@struct, keys); 273: check_return_code(ret) 274: 275: keys.size.times do 276: value, key, flags, ret = Lib.memcached_fetch_rvalue(@struct) 277: break if ret == Lib::MEMCACHED_END 278: check_return_code(ret) 279: value = Marshal.load(value) if marshal 280: # Assign the value 281: hash[key] = value 282: end 283: hash 284: else 285: # Single get 286: value, flags, ret = Lib.memcached_get_rvalue(@struct, keys) 287: check_return_code(ret) 288: value = Marshal.load(value) if marshal 289: value 290: end 291: end
get_multi (keys, marshal=true)
Alias for get
increment (key, offset=1)
Increment a key‘s value. Accepts a String key. Raises Memcached::NotFound if the key does not exist.
Also accepts an optional offset paramater, which defaults to 1. offset must be an integer.
Note that the key must be initialized to an unmarshalled integer first, via set, add, or replace with marshal set to false.
# File lib/memcached/memcached.rb, line 176 176: def increment(key, offset=1) 177: ret, value = Lib.memcached_increment(@struct, key, offset) 178: check_return_code(ret) 179: value 180: end
prepend (key, value)
Prepends a string to a key‘s value. The parameters and exception behavior are the same as append.
# File lib/memcached/memcached.rb, line 213 213: def prepend(key, value) 214: # Requires memcached 1.2.4 215: check_return_code( 216: Lib.memcached_prepend(@struct, key, value.to_s, IGNORED, FLAGS) 217: ) 218: end
replace (key, value, timeout=0, marshal=true)
Replace a key/value pair. Raises Memcached::NotFound if the key does not exist on the server. The parameters are the same as set.
# File lib/memcached/memcached.rb, line 195 195: def replace(key, value, timeout=0, marshal=true) 196: value = marshal ? Marshal.dump(value) : value.to_s 197: check_return_code( 198: Lib.memcached_replace(@struct, key, value, timeout, FLAGS) 199: ) 200: end
reset (current_servers = nil)
Reset the state of the libmemcached struct. This is useful for changing the server list at runtime.
# File lib/memcached/memcached.rb, line 118 118: def reset(current_servers = nil) 119: current_servers ||= servers 120: @struct = Lib::MemcachedSt.new 121: Lib.memcached_create(@struct) 122: set_behaviors 123: set_callbacks 124: set_servers(current_servers) 125: end
servers ()
Return the array of server strings used to configure this instance.
# File lib/memcached/memcached.rb, line 100 100: def servers 101: server_structs.map do |server| 102: "#{server.hostname}:#{server.port}" 103: end 104: end
set (key, value, timeout=0, marshal=true)
Set a key/value pair. Accepts a String key and an arbitrary Ruby object. Overwrites any existing value on the server.
Accepts an optional timeout value to specify the maximum lifetime of the key on the server. timeout can be either an integer number of seconds, or a Time elapsed time object. 0 means no timeout. Note that there is no guarantee that the key will persist as long as the timeout, but it will not persist longer.
Also accepts a marshal value, which defaults to true. Set marshal to false if you want the value to be set directly.
# File lib/memcached/memcached.rb, line 156 156: def set(key, value, timeout=0, marshal=true) 157: value = marshal ? Marshal.dump(value) : value.to_s 158: check_return_code( 159: Lib.memcached_set(@struct, key, value, timeout, FLAGS) 160: ) 161: end
stats ()
Return a Hash of statistics responses from the set of servers. Each value is an array with one entry for each server, in the same order the servers were defined.
# File lib/memcached/memcached.rb, line 296 296: def stats 297: stats = Hash.new([]) 298: 299: stat_struct, ret = Lib.memcached_stat(@struct, "") 300: check_return_code(ret) 301: 302: keys, ret = Lib.memcached_stat_get_keys(@struct, stat_struct) 303: check_return_code(ret) 304: 305: keys.each do |key| 306: server_structs.size.times do |index| 307: 308: value, ret = Lib.memcached_stat_get_rvalue( 309: @struct, 310: Lib.memcached_select_stat_at(@struct, stat_struct, index), 311: key) 312: check_return_code(ret) 313: 314: value = case value 315: when /^\d+\.\d+$/: value.to_f 316: when /^\d+$/: value.to_i 317: else value 318: end 319: 320: stats[key.to_sym] += [value] 321: end 322: end 323: 324: Lib.memcached_stat_free(@struct, stat_struct) 325: stats 326: end
Private Instance Methods
check_return_code (ret)
Checks the return code from Rlibmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code.
# File lib/memcached/memcached.rb, line 333 333: def check_return_code(ret) #:doc: 334: # 0.16 --enable-debug returns 0 for an ActionQueued result but --disable-debug does not 335: return if ret == 0 or ret == 31 336: 337: # SystemError; eject from the pool 338: if ret == 25 and options[:failover] 339: failed = sweep_servers 340: raise EXCEPTIONS[ret], "Server #{failed} failed permanently" 341: else 342: raise EXCEPTIONS[ret], "" 343: end 344: end
set_behavior (behavior, value)
Set a behavior option for this Memcached instance. Accepts a Symbol behavior and either true, false, or a Symbol for value. Arguments are validated and converted into integers for the struct setter method.
# File lib/memcached/behaviors.rb, line 33 33: def set_behavior(behavior, value) #:doc: 34: raise ArgumentError, "No behavior #{behavior.inspect}" unless b_id = BEHAVIORS[behavior] 35: 36: # Scoped validations; annoying 37: msg = "Invalid behavior value #{value.inspect} for #{behavior.inspect}" 38: case behavior 39: when :hash then raise(ArgumentError, msg) unless HASH_VALUES[value] 40: when :distribution then raise(ArgumentError, msg) unless DISTRIBUTION_VALUES[value] 41: when *DIRECT_VALUE_BEHAVIORS then raise(ArgumentError, msg) unless value.is_a? Fixnum and value > 0 42: else 43: raise(ArgumentError, msg) unless BEHAVIOR_VALUES[value] 44: end 45: 46: lib_value = BEHAVIOR_VALUES[value] || value 47: #STDERR.puts "Setting #{behavior}:#{b_id} => #{value} (#{lib_value})" 48: Lib.memcached_behavior_set(@struct, b_id, lib_value) 49: #STDERR.puts " -> set to #{get_behavior(behavior).inspect}" 50: end