@keyv/redis 3.0.1 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,15 +9,35 @@
9
9
 
10
10
  Redis storage adapter for [Keyv](https://github.com/jaredwray/keyv).
11
11
 
12
- TTL functionality is handled directly by Redis so no timestamps are stored and expired keys are cleaned up internally.
13
-
14
- ## Install
15
-
16
- ```shell
17
- npm install --save keyv @keyv/redis
18
- ```
19
-
20
- ## Usage
12
+ # Features
13
+ * Built on top of [redis](https://npmjs.com/package/redis).
14
+ * TTL is handled directly by Redis.
15
+ * Supports Redis Clusters.
16
+ * Url connection string support or pass in your Redis Options
17
+ * Easily add in your own Redis client.
18
+ * Namespace support for key management.
19
+ * Unlink as default delete method for performance.
20
+ * Access to the Redis client for advanced use cases.
21
+ * Keyv and Redis Libraries are exported for advanced use cases.
22
+ * `createKeyv` function for easy creation of Keyv instances.
23
+ * jsDoc comments for easy documentation.
24
+ * CJS / ESM and TypeScript supported out of the box.
25
+
26
+ # Table of Contents
27
+ * [Usage](#usage)
28
+ * [Namespaces](#namespaces)
29
+ * [Performance Considerations](#performance-considerations)
30
+ * [High Memory Usage on Redis Server](#high-memory-usage-on-redis-server)
31
+ * [Using Cacheable with Redis](#using-cacheable-with-redis)
32
+ * [Clustering and TLS Support](#clustering-and-tls-support)
33
+ * [API](#api)
34
+ * [Migrating from v3 to v4](#migrating-from-v3-to-v4)
35
+ * [About Redis Sets and its Support in v4](#about-redis-sets-and-its-support-in-v4)
36
+ * [License](#license)
37
+
38
+ # Usage
39
+
40
+ Here is a standard use case where we implement `Keyv` and `@keyv/redis`:
21
41
 
22
42
  ```js
23
43
  import Keyv from 'keyv';
@@ -27,75 +47,212 @@ const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379'));
27
47
  keyv.on('error', handleConnectionError);
28
48
  ```
29
49
 
30
- Any valid [`Redis`](https://github.com/luin/ioredis#connect-to-redis) options will be passed directly through.
31
-
32
- e.g:
50
+ Here is the same example but with the `Keyv` instance created with the `createKeyv` function:
33
51
 
34
52
  ```js
35
- const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379', { disable_resubscribing: true }));
53
+ import { createKeyv } from '@keyv/redis';
54
+
55
+ const keyv = createKeyv('redis://user:pass@localhost:6379', { namespace: 'my-namespace' });
36
56
  ```
37
57
 
38
- Or you can manually create a storage adapter instance and pass it to Keyv:
58
+ You only have to import the `@keyv/redis` library if you are using the `createKeyv` function. 🎉 Otherwise, you can import `Keyv` and `@keyv/redis` independently.
59
+
60
+ Here you can pass in the Redis options directly:
39
61
 
40
62
  ```js
41
63
  import Keyv from 'keyv';
42
64
  import KeyvRedis from '@keyv/redis';
43
65
 
44
- const keyvRedis = new KeyvRedis('redis://user:pass@localhost:6379');
45
- const keyv = new Keyv({ store: keyvRedis });
66
+ const redisOptions = {
67
+ url: 'redis://localhost:6379', // The Redis server URL (use 'rediss' for TLS)
68
+ password: 'your_password', // Optional password if Redis has authentication enabled
69
+
70
+ socket: {
71
+ host: 'localhost', // Hostname of the Redis server
72
+ port: 6379, // Port number
73
+ reconnectStrategy: (retries) => Math.min(retries * 50, 2000), // Custom reconnect logic
74
+
75
+ tls: false, // Enable TLS if you need to connect over SSL
76
+ keepAlive: 30000, // Keep-alive timeout (in milliseconds)
77
+ }
78
+ };
79
+
80
+ const keyv = new Keyv(new KeyvRedis(redisOptions));
46
81
  ```
47
82
 
48
- Or reuse a previous Redis instance:
83
+ Or you can create a new Redis instance and pass it in with `KeyvOptions`:
49
84
 
50
85
  ```js
51
86
  import Keyv from 'keyv';
52
- import Redis from 'ioredis';
53
- import KeyvRedis from '@keyv/redis';
87
+ import KeyvRedis, { createClient } from '@keyv/redis';
54
88
 
55
- const redis = new Redis('redis://user:pass@localhost:6379');
89
+ const redis = createClient('redis://user:pass@localhost:6379', { namespace: 'my-namespace'});
56
90
  const keyvRedis = new KeyvRedis(redis);
57
91
  const keyv = new Keyv({ store: keyvRedis });
58
92
  ```
59
93
 
60
- Or reuse a previous Redis cluster:
94
+ # Namespaces
95
+
96
+ You can set a namespace for your keys. This is useful if you want to manage your keys in a more organized way. Here is an example of how to set a namespace:
61
97
 
62
98
  ```js
63
99
  import Keyv from 'keyv';
64
- import Redis from 'ioredis';
65
100
  import KeyvRedis from '@keyv/redis';
66
101
 
67
- const redis = new Redis.Cluster('redis://user:pass@localhost:6379');
68
- const keyvRedis = new KeyvRedis(redis);
69
- const keyv = new Keyv({ store: keyvRedis });
102
+ const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379', { namespace: 'my-namespace' }));
103
+ ```
104
+
105
+ This will prefix all keys with `my-namespace:`. You can also set the namespace after the fact:
106
+
107
+ ```js
108
+ keyv.namespace = 'my-namespace';
109
+ ```
110
+
111
+ NOTE: If you plan to do many clears or deletes, it is recommended to read the [Performance Considerations](#performance-considerations) section.
112
+
113
+ # Performance Considerations
114
+
115
+ With namespaces being prefix based it is critical to understand some of the performance considerations we have made:
116
+ * `clear()` - We use the `SCAN` command to iterate over keys. This is a non-blocking command that is more efficient than `KEYS`. In addition we are using `UNLINK` by default instead of `DEL`. Even with that if you are iterating over a large dataset it can still be slow. It is highly recommended to use the `namespace` option to limit the keys that are being cleared and if possible to not use the `clear()` method in high performance environments.
117
+
118
+ * `delete()` - By default we are now using `UNLINK` instead of `DEL` for deleting keys. This is a non-blocking command that is more efficient than `DEL`. If you are deleting a large number of keys it is recommended to use the `deleteMany()` method instead of `delete()`.
119
+
120
+ * `clearBatchSize` - The `clearBatchSize` option is set to `1000` by default. This is because Redis has a limit of 1000 keys that can be deleted in a single batch.
121
+
122
+ * `useUnlink` - This option is set to `true` by default. This is because `UNLINK` is a non-blocking command that is more efficient than `DEL`. If you are not using `UNLINK` and are doing a lot of deletes it is recommended to set this option to `true`.
123
+
124
+ * `setMany`, `getMany`, `deleteMany` - These methods are more efficient than their singular counterparts. These will be used by default in the `Keyv` library such as when using `keyv.delete(string[])` it will use `deleteMany()`.
125
+
126
+ If you want to see even better performance please see the [Using Cacheable with Redis](#using-cacheable-with-redis) section as it has non-blocking and in-memory primary caching that goes along well with this library and Keyv.
127
+
128
+ # High Memory Usage on Redis Server
129
+
130
+ This is because we are using `UNLINK` by default instead of `DEL`. This is a non-blocking command that is more efficient than `DEL` but will slowly remove the memory allocation.
131
+
132
+ If you are deleting or clearing a large number of keys you can disable this by setting the `useUnlink` option to `false`. This will use `DEL` instead of `UNLINK` and should reduce the memory usage.
133
+
134
+ ```js
135
+ const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379', { useUnlink: false }));
136
+ // Or
137
+ keyv.useUnlink = false;
70
138
  ```
71
- ## Options
72
139
 
73
- ### useRedisSets
140
+ # Using Cacheable with Redis
74
141
 
75
- The `useRedisSets` option lets you decide whether to use Redis sets for key management. By default, this option is set to `true`.
142
+ If you are wanting to see even better performance with Redis, you can use [Cacheable](https://npmjs.org/package/cacheable) which is a multi-layered cache library that has in-memory primary caching and non-blocking secondary caching. Here is an example of how to use it with Redis:
76
143
 
77
- When `useRedisSets` is enabled (`true`):
144
+ ```js
145
+ import KeyvRedis from '@keyv/redis';
146
+ import Cacheable from 'cacheable';
78
147
 
79
- - A namespace for the Redis sets is created, and all created keys are added to this. This allows for group management of keys.
80
- - When a key is deleted, it's removed not only from the main storage but also from the Redis set.
81
- - When clearing all keys (using the `clear` function), all keys in the Redis set are looked up for deletion. The set itself is also deleted.
148
+ const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
82
149
 
83
- **Note**: In high-performance scenarios, enabling `useRedisSets` might lead to memory leaks. If you're running a high-performance application or service, it is recommended to set `useRedisSets` to `false`.
150
+ const cache = new Cacheable( { secondary } );
151
+ ```
84
152
 
85
- If you decide to set `useRedisSets` as `false`, keys will be handled individually and Redis sets won't be utilized.
153
+ For even higher performance you can set the `nonBlocking` option to `true`:
86
154
 
87
- However, please note that setting `useRedisSets` to `false` could lead to performance issues in production when using the `clear` function, as it will need to iterate over all keys to delete them.
155
+ ```js
156
+ const cache = new Cacheable( { secondary, nonBlocking: true } );
157
+ ```
158
+
159
+ This will make it so that the secondary does not block the primary cache and will be very fast. 🚀
88
160
 
89
- #### Example
161
+ # Clustering and TLS Support
90
162
 
91
- Here's how you can use the `useRedisSets` option:
163
+ If you are using a Redis Cluster or need to use TLS, you can pass in the `redisOptions` directly. Here is an example of how to do that:
92
164
 
93
165
  ```js
94
166
  import Keyv from 'keyv';
167
+ import KeyvRedis, { createCluster } from '@keyv/redis';
168
+
169
+ const cluster = createCluster({
170
+ rootNodes: [
171
+ {
172
+ url: 'redis://127.0.0.1:7000',
173
+ },
174
+ {
175
+ url: 'redis://127.0.0.1:7001',
176
+ },
177
+ {
178
+ url: 'redis://127.0.0.1:7002',
179
+ },
180
+ ],
181
+ });
182
+
183
+ const keyv = new Keyv({ store: new KeyvRedis(cluster) });
184
+ ```
185
+
186
+ You can learn more about the `createCluster` function in the [documentation](https://github.com/redis/node-redis/blob/master/docs/clustering.md) at https://github.com/redis/node-redis/tree/master/docs.
95
187
 
96
- const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379', { useRedisSets: false }));
188
+ Here is an example of how to use TLS:
189
+
190
+ ```js
191
+ import Keyv from 'keyv';
192
+ import KeyvRedis from '@keyv/redis';
193
+
194
+ const tlsOptions = {
195
+ socket: {
196
+ host: 'localhost',
197
+ port: 6379,
198
+ tls: true, // Enable TLS connection
199
+ rejectUnauthorized: false, // Ignore self-signed certificate errors (for testing)
200
+
201
+ // Alternatively, provide CA, key, and cert for mutual authentication
202
+ ca: fs.readFileSync('/path/to/ca-cert.pem'),
203
+ cert: fs.readFileSync('/path/to/client-cert.pem'), // Optional for client auth
204
+ key: fs.readFileSync('/path/to/client-key.pem'), // Optional for client auth
205
+ }
206
+ };
207
+
208
+ const keyv = new Keyv({ store: new KeyvRedis(tlsOptions) });
209
+ ```
210
+
211
+ # API
212
+ * **constructor([connection], [options])**
213
+ * **namespace** - The namespace to use for the keys.
214
+ * **client** - The Redis client instance.
215
+ * **keyPrefixSeparator** - The separator to use between the namespace and key.
216
+ * **clearBatchSize** - The number of keys to delete in a single batch.
217
+ * **useUnlink** - Use the `UNLINK` command for deleting keys isntead of `DEL`.
218
+ * **set** - Set a key.
219
+ * **setMany** - Set multiple keys.
220
+ * **get** - Get a key.
221
+ * **getMany** - Get multiple keys.
222
+ * **has** - Check if a key exists.
223
+ * **hasMany** - Check if multiple keys exist.
224
+ * **delete** - Delete a key.
225
+ * **deleteMany** - Delete multiple keys.
226
+ * **clear** - Clear all keys. If the `namespace` is set it will only clear keys with that namespace.
227
+ * **disconnect** - Disconnect from the Redis server.
228
+ * **iterator** - Create a new iterator for the keys.
229
+
230
+ # Migrating from v3 to v4
231
+
232
+ Overall the API is the same as v3 with additional options and performance improvements. Here are the main changes:
233
+ * The `ioredis` library has been removed in favor of the `redis` aka `node-redis` library. If you want to use ioredis you can use `@keyv/keyval`
234
+ * The `useUnlink` option has been added to use `UNLINK` instead of `DEL` and set to true by default.
235
+ * The `clearBatchSize` option has been added to set the number of keys to delete in a single batch.
236
+ * The `clear()` and `delete()` methods now use `UNLINK` instead of `DEL`. If you want to use `DEL` you can set the `useUnlink` option to `false`.
237
+ * BREAKING: We no longer support redis sets. This is due to the fact that it caused significant performance issues and was not a good fit for the library.
238
+ * BREAKING: YOUR PREVIOUS KEYS WILL NOT BE VALID. This is because of the fixe of the namespace support and how it is handled. Now, when using `keyv` with `@keyv/redis` as the storage adapter you can do the following:
239
+
240
+ ```js
241
+ import Keyv from 'keyv';
242
+ import KeyvRedis from '@keyv/redis';
243
+
244
+ const redis = new KeyvRedis('redis://user:pass@localhost:6379');
245
+ const keyv = new Keyv({ store: redis, namespace: 'my-namespace', useKeyPrefix: false });
97
246
  ```
98
247
 
99
- ## License
248
+ This will make it so the storage adapter `@keyv/redis` will handle the namespace and not the `keyv` instance. If you leave it on it will just look duplicated like `my-namespace:my-namespace:key`.
249
+
250
+
251
+
252
+ # About Redis Sets and its Support in v4
253
+
254
+ We no longer support redis sets. This is due to the fact that it caused significant performance issues and was not a good fit for the library.
255
+
256
+ # License
100
257
 
101
258
  [MIT © Jared Wray](LISCENCE)