redis 3.0.0 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +269 -0
  3. data/README.md +295 -58
  4. data/lib/redis.rb +1760 -451
  5. data/lib/redis/client.rb +355 -88
  6. data/lib/redis/cluster.rb +295 -0
  7. data/lib/redis/cluster/command.rb +81 -0
  8. data/lib/redis/cluster/command_loader.rb +34 -0
  9. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  10. data/lib/redis/cluster/node.rb +107 -0
  11. data/lib/redis/cluster/node_key.rb +31 -0
  12. data/lib/redis/cluster/node_loader.rb +37 -0
  13. data/lib/redis/cluster/option.rb +90 -0
  14. data/lib/redis/cluster/slot.rb +86 -0
  15. data/lib/redis/cluster/slot_loader.rb +49 -0
  16. data/lib/redis/connection.rb +4 -2
  17. data/lib/redis/connection/command_helper.rb +5 -10
  18. data/lib/redis/connection/hiredis.rb +12 -8
  19. data/lib/redis/connection/registry.rb +2 -1
  20. data/lib/redis/connection/ruby.rb +232 -63
  21. data/lib/redis/connection/synchrony.rb +41 -14
  22. data/lib/redis/distributed.rb +205 -70
  23. data/lib/redis/errors.rb +48 -0
  24. data/lib/redis/hash_ring.rb +31 -73
  25. data/lib/redis/pipeline.rb +74 -18
  26. data/lib/redis/subscribe.rb +24 -13
  27. data/lib/redis/version.rb +3 -1
  28. metadata +63 -160
  29. data/.gitignore +0 -10
  30. data/.order +0 -169
  31. data/.travis.yml +0 -50
  32. data/.travis/Gemfile +0 -11
  33. data/.yardopts +0 -3
  34. data/Rakefile +0 -392
  35. data/benchmarking/logging.rb +0 -62
  36. data/benchmarking/pipeline.rb +0 -51
  37. data/benchmarking/speed.rb +0 -21
  38. data/benchmarking/suite.rb +0 -24
  39. data/benchmarking/worker.rb +0 -71
  40. data/examples/basic.rb +0 -15
  41. data/examples/dist_redis.rb +0 -43
  42. data/examples/incr-decr.rb +0 -17
  43. data/examples/list.rb +0 -26
  44. data/examples/pubsub.rb +0 -31
  45. data/examples/sets.rb +0 -36
  46. data/examples/unicorn/config.ru +0 -3
  47. data/examples/unicorn/unicorn.rb +0 -20
  48. data/redis.gemspec +0 -41
  49. data/test/blocking_commands_test.rb +0 -42
  50. data/test/command_map_test.rb +0 -30
  51. data/test/commands_on_hashes_test.rb +0 -21
  52. data/test/commands_on_lists_test.rb +0 -20
  53. data/test/commands_on_sets_test.rb +0 -77
  54. data/test/commands_on_sorted_sets_test.rb +0 -109
  55. data/test/commands_on_strings_test.rb +0 -83
  56. data/test/commands_on_value_types_test.rb +0 -99
  57. data/test/connection_handling_test.rb +0 -189
  58. data/test/db/.gitignore +0 -1
  59. data/test/distributed_blocking_commands_test.rb +0 -46
  60. data/test/distributed_commands_on_hashes_test.rb +0 -10
  61. data/test/distributed_commands_on_lists_test.rb +0 -22
  62. data/test/distributed_commands_on_sets_test.rb +0 -83
  63. data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
  64. data/test/distributed_commands_on_strings_test.rb +0 -48
  65. data/test/distributed_commands_on_value_types_test.rb +0 -87
  66. data/test/distributed_commands_requiring_clustering_test.rb +0 -148
  67. data/test/distributed_connection_handling_test.rb +0 -23
  68. data/test/distributed_internals_test.rb +0 -15
  69. data/test/distributed_key_tags_test.rb +0 -52
  70. data/test/distributed_persistence_control_commands_test.rb +0 -26
  71. data/test/distributed_publish_subscribe_test.rb +0 -92
  72. data/test/distributed_remote_server_control_commands_test.rb +0 -53
  73. data/test/distributed_scripting_test.rb +0 -102
  74. data/test/distributed_sorting_test.rb +0 -20
  75. data/test/distributed_test.rb +0 -58
  76. data/test/distributed_transactions_test.rb +0 -32
  77. data/test/encoding_test.rb +0 -18
  78. data/test/error_replies_test.rb +0 -59
  79. data/test/helper.rb +0 -188
  80. data/test/helper_test.rb +0 -22
  81. data/test/internals_test.rb +0 -214
  82. data/test/lint/blocking_commands.rb +0 -124
  83. data/test/lint/hashes.rb +0 -162
  84. data/test/lint/lists.rb +0 -143
  85. data/test/lint/sets.rb +0 -96
  86. data/test/lint/sorted_sets.rb +0 -201
  87. data/test/lint/strings.rb +0 -157
  88. data/test/lint/value_types.rb +0 -106
  89. data/test/persistence_control_commands_test.rb +0 -26
  90. data/test/pipelining_commands_test.rb +0 -195
  91. data/test/publish_subscribe_test.rb +0 -153
  92. data/test/remote_server_control_commands_test.rb +0 -104
  93. data/test/scripting_test.rb +0 -78
  94. data/test/sorting_test.rb +0 -45
  95. data/test/support/connection/hiredis.rb +0 -1
  96. data/test/support/connection/ruby.rb +0 -1
  97. data/test/support/connection/synchrony.rb +0 -17
  98. data/test/support/redis_mock.rb +0 -92
  99. data/test/support/wire/synchrony.rb +0 -24
  100. data/test/support/wire/thread.rb +0 -5
  101. data/test/synchrony_driver.rb +0 -57
  102. data/test/test.conf +0 -9
  103. data/test/thread_safety_test.rb +0 -32
  104. data/test/transactions_test.rb +0 -244
  105. data/test/unknown_commands_test.rb +0 -14
  106. data/test/url_param_test.rb +0 -64
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 28eb23d20152436fc47f334f517c6fa62855e8e4711b44979cb05d86f8dcdd34
4
+ data.tar.gz: 46d01b3f5539800142582aeb7ebeabe4327bce970e31ce2048dcba027dfe6eb1
5
+ SHA512:
6
+ metadata.gz: f2f11269c6a3a030231eeb93dfa6bee54b340ff5ad244df6d79074c95f111e3d2081f49f77756576cb8225640e8b8cad144884c8519bcf1b0e7bedea3ca1b00f
7
+ data.tar.gz: 44ec06531632060b497cf1d02e6678c3d087ec3371cba86f53f9687848f73bb4e02c166b11d4db9e6b531b62ba2ca830649d71114063560f6dd764ca2ef10f07
@@ -1,3 +1,272 @@
1
+ # Unreleased
2
+
3
+ # 4.2.2
4
+
5
+ * Fix `WATCH` support for `Redis::Distributed`. See #941.
6
+ * Fix handling of empty stream responses. See #905, #929.
7
+
8
+ # 4.2.1
9
+
10
+ * Fix `exists?` returning an actual boolean when called with multiple keys. See #918.
11
+ * Setting `Redis.exists_returns_integer = false` disables warning message about new behaviour. See #920.
12
+
13
+ # 4.2.0
14
+
15
+ * Convert commands to accept keyword arguments rather than option hashes. This both help catching typos, and reduce needless allocations.
16
+ * Deprecate the synchrony driver. It will be removed in 5.0 and hopefully maintained as a separate gem. See #915.
17
+ * Make `Redis#exists` variadic, will return an Integer if called with multiple keys.
18
+ * Add `Redis#exists?` to get a Boolean if any of the keys exists.
19
+ * `Redis#exists` when called with a single key will warn that future versions will return an Integer.
20
+ Set `Redis.exists_returns_integer = true` to opt-in to the new behavior.
21
+ * Support `keepttl` ooption in `set`. See #913.
22
+ * Optimized initialization of Redis::Cluster. See #912.
23
+ * Accept sentinel options even with string key. See #599.
24
+ * Verify TLS connections by default. See #900.
25
+ * Make `Redis#hset` variadic. It now returns an integer, not a boolean. See #910.
26
+
27
+ # 4.1.4
28
+
29
+ * Alias `Redis#disconnect` as `#close`. See #901.
30
+ * Handle clusters with multiple slot ranges. See #894.
31
+ * Fix password authentication to a redis cluster. See #889.
32
+ * Handle recursive MOVED responses. See #882.
33
+ * Increase buffer size in the ruby connector. See #880.
34
+ * Fix thread safety of `Redis.queue`. See #878.
35
+ * Deprecate `Redis::Future#==` as it's likely to be a mistake. See #876.
36
+ * Support `KEEPTTL` option for SET command. See #913.
37
+
38
+ # 4.1.3
39
+
40
+ * Fix the client hanging forever when connecting with SSL to a non-SSL server. See #835.
41
+
42
+ # 4.1.2
43
+
44
+ * Fix several authentication problems with sentinel. See #850 and #856.
45
+ * Explicitly drop Ruby 2.2 support.
46
+
47
+
48
+ # 4.1.1
49
+
50
+ * Fix error handling in multi blocks. See #754.
51
+ * Fix geoadd to accept arrays like georadius and georadiusbymember. See #841.
52
+ * Fix georadius command failing when long == lat. See #841.
53
+ * Fix timeout error in xread block: 0. See #837.
54
+ * Fix incompatibility issue with redis-objects. See #834.
55
+ * Properly handle Errno::EADDRNOTAVAIL on connect.
56
+ * Fix password authentication to sentinel instances. See #813.
57
+
58
+ # 4.1.0
59
+
60
+ * Add Redis Cluster support. See #716.
61
+ * Add streams support. See #799 and #811.
62
+ * Add ZPOP* support. See #812.
63
+ * Fix issues with integer-like objects as BPOP timeout
64
+
65
+ # 4.0.3
66
+
67
+ * Fix raising command error for first command in pipeline. See #788.
68
+ * Fix the gemspec to stop exposing a `build` executable. See #785.
69
+ * Add `:reconnect_delay` and `:reconnect_delay_max` options. See #778.
70
+
71
+ # 4.0.2
72
+
73
+ * Added `Redis#unlink`. See #766.
74
+
75
+ * `Redis.new` now accept a custom connector via `:connector`. See #591.
76
+
77
+ * `Redis#multi` no longer perform empty transactions. See #747.
78
+
79
+ * `Redis#hdel` now accepts hash keys as multiple arguments like `#del`. See #755.
80
+
81
+ * Allow to skip SSL verification. See #745.
82
+
83
+ * Add Geo commands: `geoadd`, `geohash`, `georadius`, `georadiusbymember`, `geopos`, `geodist`. See #730.
84
+
85
+ # 4.0.1
86
+
87
+ * `Redis::Distributed` now supports `mget` and `mapped_mget`. See #687.
88
+
89
+ * `Redis::Distributed` now supports `sscan` and `sscan_each`. See #572.
90
+
91
+ * `Redis#connection` returns a hash with connection information.
92
+ You shouldn't need to call `Redis#_client`, ever.
93
+
94
+ * `Redis#flushdb` and `Redis#flushall` now support the `:async` option. See #706.
95
+
96
+
97
+ # 4.0
98
+
99
+ * Removed `Redis.connect`. Use `Redis.new`.
100
+
101
+ * Removed `Redis#[]` and `Redis#[]=` aliases.
102
+
103
+ * Added support for `CLIENT` commands. The lower-level client can be
104
+ accessed via `Redis#_client`.
105
+
106
+ * Dropped official support for Ruby < 2.2.2.
107
+
108
+ # 3.3.5
109
+
110
+ * Fixed Ruby 1.8 compatibility after backporting `Redis#connection`. See #719.
111
+
112
+ # 3.3.4 (yanked)
113
+
114
+ * `Redis#connection` returns a hash with connection information.
115
+ You shouldn't need to call `Redis#_client`, ever.
116
+
117
+ # 3.3.3
118
+
119
+ * Improved timeout handling after dropping Timeout module.
120
+
121
+ # 3.3.2
122
+
123
+ * Added support for `SPOP` with COUNT. See #628.
124
+
125
+ * Fixed connection glitches when using SSL. See #644.
126
+
127
+ # 3.3.1
128
+
129
+ * Remove usage of Timeout::timeout, refactor into using low level non-blocking writes.
130
+ This fixes a memory leak due to Timeout creating threads on each invocation.
131
+
132
+ # 3.3.0
133
+
134
+ * Added support for SSL/TLS. Redis doesn't support SSL natively, so you still
135
+ need to run a terminating proxy on Redis' side. See #496.
136
+
137
+ * Added `read_timeout` and `write_timeout` options. See #437, #482.
138
+
139
+ * Added support for pub/sub with timeouts. See #329.
140
+
141
+ * Added `Redis#call`, `Redis#queue` and `Redis#commit` as a more minimal API to
142
+ the client.
143
+
144
+ * Deprecated `Redis#disconnect!` in favor of `Redis#close`.
145
+
146
+ # 3.2.2
147
+
148
+ * Added support for `ZADD` options `NX`, `XX`, `CH`, `INCR`. See #547.
149
+
150
+ * Added support for sentinel commands. See #556.
151
+
152
+ * New `:id` option allows you to identify the client against Redis. See #510.
153
+
154
+ * `Redis::Distributed` will raise when adding two nodes with the same ID.
155
+ See #354.
156
+
157
+ # 3.2.1
158
+
159
+ * Added support for `PUBSUB` command.
160
+
161
+ * More low-level socket errors are now raised as `CannotConnectError`.
162
+
163
+ * Added `:connect_timeout` option.
164
+
165
+ * Added support for `:limit` option for `ZREVRANGEBYLEX`.
166
+
167
+ * Fixed an issue where connections become inconsistent when using Ruby's
168
+ Timeout module outside of the client (see #501, #502).
169
+
170
+ * Added `Redis#disconnect!` as a public-API way of disconnecting the client
171
+ (without needing to use `QUIT`). See #506.
172
+
173
+ * Fixed Sentinel support with Hiredis.
174
+
175
+ * Fixed Sentinel support when using authentication and databases.
176
+
177
+ * Improved resilience when trying to contact sentinels.
178
+
179
+ # 3.2.0
180
+
181
+ * Redis Sentinel support.
182
+
183
+ # 3.1.0
184
+
185
+ * Added debug log sanitization (#428).
186
+
187
+ * Added support for HyperLogLog commands (Redis 2.8.9, #432).
188
+
189
+ * Added support for `BITPOS` command (Redis 2.9.11, #412).
190
+
191
+ * The client will now automatically reconnect after a fork (#414).
192
+
193
+ * If you want to disable the fork-safety check and prefer to share the
194
+ connection across child processes, you can now pass the `inherit_socket`
195
+ option (#409).
196
+
197
+ * If you want the client to attempt to reconnect more than once, you can now
198
+ pass the `reconnect_attempts` option (#347)
199
+
200
+ # 3.0.7
201
+
202
+ * Added method `Redis#dup` to duplicate a Redis connection.
203
+
204
+ * IPv6 support.
205
+
206
+ # 3.0.6
207
+
208
+ * Added support for `SCAN` and variants.
209
+
210
+ # 3.0.5
211
+
212
+ * Fix calling #select from a pipeline (#309).
213
+
214
+ * Added method `Redis#connected?`.
215
+
216
+ * Added support for `MIGRATE` (Redis 2.6).
217
+
218
+ * Support extended SET command (#343, thanks to @benubois).
219
+
220
+ # 3.0.4
221
+
222
+ * Ensure #watch without a block returns "OK" (#332).
223
+
224
+ * Make futures identifiable (#330).
225
+
226
+ * Fix an issue preventing STORE in a SORT with multiple GETs (#328).
227
+
228
+ # 3.0.3
229
+
230
+ * Blocking list commands (`BLPOP`, `BRPOP`, `BRPOPLPUSH`) use a socket
231
+ timeout equal to the sum of the command's timeout and the Redis
232
+ client's timeout, instead of disabling socket timeout altogether.
233
+
234
+ * Ruby 2.0 compatibility.
235
+
236
+ * Added support for `DUMP` and `RESTORE` (Redis 2.6).
237
+
238
+ * Added support for `BITCOUNT` and `BITOP` (Redis 2.6).
239
+
240
+ * Call `#to_s` on value argument for `SET`, `SETEX`, `PSETEX`, `GETSET`,
241
+ `SETNX`, and `SETRANGE`.
242
+
243
+ # 3.0.2
244
+
245
+ * Unescape CGI escaped password in URL.
246
+
247
+ * Fix test to check availability of `UNIXSocket`.
248
+
249
+ * Fix handling of score = +/- infinity for sorted set commands.
250
+
251
+ * Replace array splats with concatenation where possible.
252
+
253
+ * Raise if `EXEC` returns an error.
254
+
255
+ * Passing a nil value in options hash no longer overwrites the default.
256
+
257
+ * Allow string keys in options hash passed to `Redis.new` or
258
+ `Redis.connect`.
259
+
260
+ * Fix uncaught error triggering unrelated error (synchrony driver).
261
+
262
+ See f7ffd5f1a628029691084de69e5b46699bb8b96d and #248.
263
+
264
+ # 3.0.1
265
+
266
+ * Fix reconnect logic not kicking in on a write error.
267
+
268
+ See 427dbd52928af452f35aa0a57b621bee56cdcb18 and #238.
269
+
1
270
  # 3.0.0
2
271
 
3
272
  ### Upgrading from 2.x to 3.0
data/README.md CHANGED
@@ -1,29 +1,17 @@
1
- # redis-rb [![Build Status][travis-image]][travis-link]
1
+ # redis-rb [![Build Status][travis-image]][travis-link] [![Inline docs][inchpages-image]][inchpages-link] ![](https://github.com/redis/redis-rb/workflows/Test/badge.svg?branch=master)
2
2
 
3
- [travis-image]: https://secure.travis-ci.org/redis/redis-rb.png?branch=master
4
- [travis-link]: http://travis-ci.org/redis/redis-rb
5
- [travis-home]: http://travis-ci.org/
3
+ A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still
4
+ providing an idiomatic interface.
6
5
 
7
- A Ruby client library for [Redis][redis-home].
8
-
9
- [redis-home]: http://redis.io
10
-
11
- A Ruby client that tries to match Redis' API one-to-one, while still
12
- providing an idiomatic interface. It features thread-safety, client-side
13
- sharding, pipelining, and an obsession for performance.
14
-
15
- ## Upgrading from 2.x to 3.0
16
-
17
- Please refer to the [CHANGELOG][changelog-3.0.0] for a summary of the
18
- most important changes, as well as a full list of changes.
19
-
20
- [changelog-3.0.0]: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#300
6
+ See [RubyDoc.info][rubydoc] for the API docs of the latest published gem.
21
7
 
22
8
  ## Getting started
23
9
 
24
- As of version 2.0 this client only targets Redis version 2.0 and higher.
25
- You can use an older version of this client if you need to interface
26
- with a Redis instance older than 2.0, but this is no longer supported.
10
+ Install with:
11
+
12
+ ```
13
+ $ gem install redis
14
+ ```
27
15
 
28
16
  You can connect to Redis by instantiating the `Redis` class:
29
17
 
@@ -33,18 +21,37 @@ require "redis"
33
21
  redis = Redis.new
34
22
  ```
35
23
 
36
- This assumes Redis was started with a default configuration, and it
24
+ This assumes Redis was started with a default configuration, and is
37
25
  listening on `localhost`, port 6379. If you need to connect to a remote
38
26
  server or a different port, try:
39
27
 
40
28
  ```ruby
41
- redis = Redis.new(:host => "10.0.1.1", :port => 6380)
29
+ redis = Redis.new(host: "10.0.1.1", port: 6380, db: 15)
30
+ ```
31
+
32
+ You can also specify connection options as a [`redis://` URL][redis-url]:
33
+
34
+ ```ruby
35
+ redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
42
36
  ```
43
37
 
38
+ The client expects passwords with special chracters to be URL-encoded (i.e.
39
+ `CGI.escape(password)`).
40
+
41
+ By default, the client will try to read the `REDIS_URL` environment variable
42
+ and use that as URL to connect to. The above statement is therefore equivalent
43
+ to setting this environment variable and calling `Redis.new` without arguments.
44
+
44
45
  To connect to Redis listening on a Unix socket, try:
45
46
 
46
47
  ```ruby
47
- redis = Redis.new(:path => "/tmp/redis.sock")
48
+ redis = Redis.new(path: "/tmp/redis.sock")
49
+ ```
50
+
51
+ To connect to a password protected Redis instance, use:
52
+
53
+ ```ruby
54
+ redis = Redis.new(password: "mysecret")
48
55
  ```
49
56
 
50
57
  The Redis class exports methods that are named identical to the commands
@@ -52,8 +59,6 @@ they execute. The arguments these methods accept are often identical to
52
59
  the arguments specified on the [Redis website][redis-commands]. For
53
60
  instance, the `SET` and `GET` commands can be called like this:
54
61
 
55
- [redis-commands]: http://redis.io/commands
56
-
57
62
  ```ruby
58
63
  redis.set("mykey", "hello world")
59
64
  # => "OK"
@@ -62,15 +67,92 @@ redis.get("mykey")
62
67
  # => "hello world"
63
68
  ```
64
69
 
65
- All commands, their arguments and return values are documented, and
66
- available on [rdoc.info][rdoc].
70
+ All commands, their arguments, and return values are documented and
71
+ available on [RubyDoc.info][rubydoc].
72
+
73
+ ## Sentinel support
74
+
75
+ The client is able to perform automatic failover by using [Redis
76
+ Sentinel](http://redis.io/topics/sentinel). Make sure to run Redis 2.8+
77
+ if you want to use this feature.
78
+
79
+ To connect using Sentinel, use:
80
+
81
+ ```ruby
82
+ SENTINELS = [{ host: "127.0.0.1", port: 26380 },
83
+ { host: "127.0.0.1", port: 26381 }]
84
+
85
+ redis = Redis.new(url: "redis://mymaster", sentinels: SENTINELS, role: :master)
86
+ ```
87
+
88
+ * The master name identifies a group of Redis instances composed of a master
89
+ and one or more slaves (`mymaster` in the example).
90
+
91
+ * It is possible to optionally provide a role. The allowed roles are `master`
92
+ and `slave`. When the role is `slave`, the client will try to connect to a
93
+ random slave of the specified master. If a role is not specified, the client
94
+ will connect to the master.
95
+
96
+ * When using the Sentinel support you need to specify a list of sentinels to
97
+ connect to. The list does not need to enumerate all your Sentinel instances,
98
+ but a few so that if one is down the client will try the next one. The client
99
+ is able to remember the last Sentinel that was able to reply correctly and will
100
+ use it for the next requests.
101
+
102
+ If you want to [authenticate](https://redis.io/topics/sentinel#configuring-sentinel-instances-with-authentication) Sentinel itself, you must specify the `password` option per instance.
103
+
104
+ ```ruby
105
+ SENTINELS = [{ host: '127.0.0.1', port: 26380, password: 'mysecret' },
106
+ { host: '127.0.0.1', port: 26381, password: 'mysecret' }]
107
+
108
+ redis = Redis.new(host: 'mymaster', sentinels: SENTINELS, role: :master)
109
+ ```
110
+
111
+ ## Cluster support
112
+
113
+ `redis-rb` supports [clustering](https://redis.io/topics/cluster-spec).
114
+
115
+ ```ruby
116
+ # Nodes can be passed to the client as an array of connection URLs.
117
+ nodes = (7000..7005).map { |port| "redis://127.0.0.1:#{port}" }
118
+ redis = Redis.new(cluster: nodes)
119
+
120
+ # You can also specify the options as a Hash. The options are the same as for a single server connection.
121
+ (7000..7005).map { |port| { host: '127.0.0.1', port: port } }
122
+ ```
123
+
124
+ You can also specify only a subset of the nodes, and the client will discover the missing ones using the [CLUSTER NODES](https://redis.io/commands/cluster-nodes) command.
125
+
126
+ ```ruby
127
+ Redis.new(cluster: %w[redis://127.0.0.1:7000])
128
+ ```
129
+
130
+ If you want [the connection to be able to read from any replica](https://redis.io/commands/readonly), you must pass the `replica: true`. Note that this connection won't be usable to write keys.
131
+
132
+ ```ruby
133
+ Redis.new(cluster: nodes, replica: true)
134
+ ```
135
+
136
+ The calling code is responsible for [avoiding cross slot commands](https://redis.io/topics/cluster-spec#keys-distribution-model).
137
+
138
+ ```ruby
139
+ redis = Redis.new(cluster: %w[redis://127.0.0.1:7000])
140
+
141
+ redis.mget('key1', 'key2')
142
+ #=> Redis::CommandError (CROSSSLOT Keys in request don't hash to the same slot)
67
143
 
68
- [rdoc]: http://rdoc.info/github/redis/redis-rb/
144
+ redis.mget('{key}1', '{key}2')
145
+ #=> [nil, nil]
146
+ ```
147
+
148
+ * The client automatically reconnects after a failover occurred, but the caller is responsible for handling errors while it is happening.
149
+ * The client support permanent node failures, and will reroute requests to promoted slaves.
150
+ * The client supports `MOVED` and `ASK` redirections transparently.
69
151
 
70
152
  ## Storing objects
71
153
 
72
- Redis only stores strings as values. If you want to store an object, you
73
- can use a serialization mechanism such as JSON:
154
+ Redis "string" types can be used to store serialized Ruby objects, for
155
+ example with JSON:
74
156
 
75
157
  ```ruby
76
158
  require "json"
@@ -124,7 +206,7 @@ end
124
206
  Replies to commands in a pipeline can be accessed via the *futures* they
125
207
  emit (since redis-rb 3.0). All calls inside a pipeline block return a
126
208
  `Future` object, which responds to the `#value` method. When the
127
- pipeline has succesfully executed, all futures are assigned their
209
+ pipeline has successfully executed, all futures are assigned their
128
210
  respective replies and can be used.
129
211
 
130
212
  ```ruby
@@ -140,6 +222,163 @@ end
140
222
  # => 1
141
223
  ```
142
224
 
225
+ ## Error Handling
226
+
227
+ In general, if something goes wrong you'll get an exception. For example, if
228
+ it can't connect to the server a `Redis::CannotConnectError` error will be raised.
229
+
230
+ ```ruby
231
+ begin
232
+ redis.ping
233
+ rescue StandardError => e
234
+ e.inspect
235
+ # => #<Redis::CannotConnectError: Timed out connecting to Redis on 10.0.1.1:6380>
236
+
237
+ e.message
238
+ # => Timed out connecting to Redis on 10.0.1.1:6380
239
+ end
240
+ ```
241
+
242
+ See lib/redis/errors.rb for information about what exceptions are possible.
243
+
244
+ ## Timeouts
245
+
246
+ The client allows you to configure connect, read, and write timeouts.
247
+ Passing a single `timeout` option will set all three values:
248
+
249
+ ```ruby
250
+ Redis.new(:timeout => 1)
251
+ ```
252
+
253
+ But you can use specific values for each of them:
254
+
255
+ ```ruby
256
+ Redis.new(
257
+ :connect_timeout => 0.2,
258
+ :read_timeout => 1.0,
259
+ :write_timeout => 0.5
260
+ )
261
+ ```
262
+
263
+ All timeout values are specified in seconds.
264
+
265
+ When using pub/sub, you can subscribe to a channel using a timeout as well:
266
+
267
+ ```ruby
268
+ redis.subscribe_with_timeout(5, "news") do |on|
269
+ on.message do |channel, message|
270
+ # ...
271
+ end
272
+ end
273
+ ```
274
+
275
+ If no message is received after 5 seconds, the client will unsubscribe.
276
+
277
+ ## Reconnections
278
+
279
+ The client allows you to configure how many `reconnect_attempts` it should
280
+ complete before declaring a connection as failed. Furthermore, you may want
281
+ to control the maximum duration between reconnection attempts with
282
+ `reconnect_delay` and `reconnect_delay_max`.
283
+
284
+ ```ruby
285
+ Redis.new(
286
+ :reconnect_attempts => 10,
287
+ :reconnect_delay => 1.5,
288
+ :reconnect_delay_max => 10.0,
289
+ )
290
+ ```
291
+
292
+ The delay values are specified in seconds. With the above configuration, the
293
+ client would attempt 10 reconnections, exponentially increasing the duration
294
+ between each attempt but it never waits longer than `reconnect_delay_max`.
295
+
296
+ This is the retry algorithm:
297
+
298
+ ```ruby
299
+ attempt_wait_time = [(reconnect_delay * 2**(attempt-1)), reconnect_delay_max].min
300
+ ```
301
+
302
+ **By default**, this gem will only **retry a connection once** and then fail, but with the
303
+ above configuration the reconnection attempt would look like this:
304
+
305
+ #|Attempt wait time|Total wait time
306
+ :-:|:-:|:-:
307
+ 1|1.5s|1.5s
308
+ 2|3.0s|4.5s
309
+ 3|6.0s|10.5s
310
+ 4|10.0s|20.5s
311
+ 5|10.0s|30.5s
312
+ 6|10.0s|40.5s
313
+ 7|10.0s|50.5s
314
+ 8|10.0s|60.5s
315
+ 9|10.0s|70.5s
316
+ 10|10.0s|80.5s
317
+
318
+ So if the reconnection attempt #10 succeeds 70 seconds have elapsed trying
319
+ to reconnect, this is likely fine in long-running background processes, but if
320
+ you use Redis to drive your website you might want to have a lower
321
+ `reconnect_delay_max` or have less `reconnect_attempts`.
322
+
323
+ ## SSL/TLS Support
324
+
325
+ This library supports natively terminating client side SSL/TLS connections
326
+ when talking to Redis via a server-side proxy such as [stunnel], [hitch],
327
+ or [ghostunnel].
328
+
329
+ To enable SSL support, pass the `:ssl => true` option when configuring the
330
+ Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
331
+ You will also need to pass in an `:ssl_params => { ... }` hash used to
332
+ configure the `OpenSSL::SSL::SSLContext` object used for the connection:
333
+
334
+ ```ruby
335
+ redis = Redis.new(
336
+ :url => "rediss://:p4ssw0rd@10.0.1.1:6381/15",
337
+ :ssl_params => {
338
+ :ca_file => "/path/to/ca.crt"
339
+ }
340
+ )
341
+ ```
342
+
343
+ The options given to `:ssl_params` are passed directly to the
344
+ `OpenSSL::SSL::SSLContext#set_params` method and can be any valid attribute
345
+ of the SSL context. Please see the [OpenSSL::SSL::SSLContext documentation]
346
+ for all of the available attributes.
347
+
348
+ Here is an example of passing in params that can be used for SSL client
349
+ certificate authentication (a.k.a. mutual TLS):
350
+
351
+ ```ruby
352
+ redis = Redis.new(
353
+ :url => "rediss://:p4ssw0rd@10.0.1.1:6381/15",
354
+ :ssl_params => {
355
+ :ca_file => "/path/to/ca.crt",
356
+ :cert => OpenSSL::X509::Certificate.new(File.read("client.crt")),
357
+ :key => OpenSSL::PKey::RSA.new(File.read("client.key"))
358
+ }
359
+ )
360
+ ```
361
+
362
+ [stunnel]: https://www.stunnel.org/
363
+ [hitch]: https://hitch-tls.org/
364
+ [ghostunnel]: https://github.com/square/ghostunnel
365
+ [OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.3.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
366
+
367
+ *NOTE:* SSL is only supported by the default "Ruby" driver
368
+
369
+
370
+ ## Expert-Mode Options
371
+
372
+ - `inherit_socket: true`: disable safety check that prevents a forked child
373
+ from sharing a socket with its parent; this is potentially useful in order to mitigate connection churn when:
374
+ - many short-lived forked children of one process need to talk
375
+ to redis, AND
376
+ - your own code prevents the parent process from using the redis
377
+ connection while a child is alive
378
+
379
+ Improper use of `inherit_socket` will result in corrupted and/or incorrect
380
+ responses.
381
+
143
382
  ## Alternate drivers
144
383
 
145
384
  By default, redis-rb uses Ruby's socket library to talk with Redis.
@@ -163,7 +402,7 @@ It is best to use hiredis when you have large replies (for example:
163
402
  In your Gemfile, include hiredis:
164
403
 
165
404
  ```ruby
166
- gem "redis", "~> 3.0.0.rc2"
405
+ gem "redis", "~> 3.0.1"
167
406
  gem "hiredis", "~> 0.4.5"
168
407
  ```
169
408
 
@@ -186,12 +425,12 @@ protocol.
186
425
  In your Gemfile, include em-synchrony and hiredis:
187
426
 
188
427
  ```ruby
189
- gem "redis", "~> 3.0.0.rc2"
428
+ gem "redis", "~> 3.0.1"
190
429
  gem "hiredis", "~> 0.4.5"
191
430
  gem "em-synchrony"
192
431
  ```
193
432
 
194
- When instantiating the client object, specify hiredis:
433
+ When instantiating the client object, specify synchrony:
195
434
 
196
435
  ```ruby
197
436
  redis = Redis.new(:driver => :synchrony)
@@ -199,34 +438,32 @@ redis = Redis.new(:driver => :synchrony)
199
438
 
200
439
  ## Testing
201
440
 
202
- This library is tested using [Travis][travis-home], where it is tested
203
- against the following interpreters and drivers:
441
+ This library is tested against recent Ruby and Redis versions.
442
+ Check [Travis][travis-link] for the exact versions supported.
443
+
444
+ ## See Also
204
445
 
205
- * MRI 1.8.7 (drivers: ruby, hiredis)
206
- * MRI 1.9.2 (drivers: ruby, hiredis, synchrony)
207
- * MRI 1.9.3 (drivers: ruby, hiredis, synchrony)
208
- * JRuby 1.6 (1.8 mode) (drivers: ruby)
209
- * JRuby 1.6 (1.9 mode) (drivers: ruby)
446
+ - [async-redis](https://github.com/socketry/async-redis) — An [async](https://github.com/socketry/async) compatible Redis client.
210
447
 
211
448
  ## Contributors
212
449
 
213
- (ordered chronologically with more than 5 commits, see `git shortlog -sn` for
214
- all contributors)
215
-
216
- * Ezra Zygmuntowicz
217
- * Taylor Weibley
218
- * Matthew Clark
219
- * Brian McKinney
220
- * Luca Guidi
221
- * Salvatore Sanfillipo
222
- * Chris Wanstrath
223
- * Damian Janowski
224
- * Michel Martens
225
- * Nick Quaranto
226
- * Pieter Noordhuis
227
- * Ilya Grigorik
450
+ Several people contributed to redis-rb, but we would like to especially
451
+ mention Ezra Zygmuntowicz. Ezra introduced the Ruby community to many
452
+ new cool technologies, like Redis. He wrote the first version of this
453
+ client and evangelized Redis in Rubyland. Thank you, Ezra.
228
454
 
229
455
  ## Contributing
230
456
 
231
457
  [Fork the project](https://github.com/redis/redis-rb) and send pull
232
- requests. You can also ask for help at `#redis-rb` on Freenode.
458
+ requests.
459
+
460
+
461
+ [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
462
+ [inchpages-link]: https://inch-ci.org/github/redis/redis-rb
463
+ [redis-commands]: https://redis.io/commands
464
+ [redis-home]: https://redis.io
465
+ [redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
466
+ [travis-home]: https://travis-ci.org/
467
+ [travis-image]: https://secure.travis-ci.org/redis/redis-rb.svg?branch=master
468
+ [travis-link]: https://travis-ci.org/redis/redis-rb
469
+ [rubydoc]: http://www.rubydoc.info/gems/redis