Scan a Cluster
GLIDE Cluster Scan API is built on top of the SCAN command, making it easier to setup and use in a cluster.
It also adds support for slot migration, failovers, and cluster rebalancing.
cursor = ClusterScanCursor()all_keys = []while not cursor.is_finished(): cursor, keys = await client.scan(cursor) all_keys.extend(keys)String key = "key:test_cluster_scan_simple" + UUID.randomUUID();Map<String, String> expectedData = new LinkedHashMap<>();for (int i = 0; i < 100; i++) { expectedData.put(key + ":" + i, "value " + i);}
Set<String> result = new LinkedHashSet<>();ClusterScanCursor cursor = ClusterScanCursor.initalCursor();while (!cursor.isFinished()) { final Object[] response = clusterClient.scan(cursor).get(); cursor.releaseCursorHandle();
cursor = (ClusterScanCursor) response[0]; final Object[] data = (Object[]) response[1]; for (Object datum : data) { result.add(datum.toString()); }}cursor.releaseCursorHandle();let cursor = new ClusterScanCursor();const allKeys: string[] = [];let keys: string[] = [];
while (!cursor.isFinished()) { [cursor, keys] = await client.scan(cursor); allKeys.push(...keys);}cursor := models.NewClusterScanCursor()allKeys := []string{}
for !cursor.IsFinished() { result, err := client.Scan(context.Background(), cursor) if err != nil { break } allKeys = append(allKeys, result.Keys...) cursor = result.Cursor}$cursor = new ClusterScanCursor();$allKeys = [];
while (true) { $keys = $client->scan($cursor); if ($keys) { $allKeys = array_merge($allKeys, $keys); }
// Create new cursor with updated cursor ID $cursor = new ClusterScanCursor($cursor->getNextCursor());
if ($cursor->isFinished()) { break; }}Scan Using Patterns
Section titled “Scan Using Patterns”await client.mset({b'my_key1': b'value1', b'my_key2': b'value2', b'not_my_key': b'value3', b'something_else': b'value4'})cursor = ClusterScanCursor()await client.scan(cursor, match=b"*key*")# Returns matching keys such as [b'my_key1', b'my_key2', b'not_my_key']Set<String> result = new LinkedHashSet<>();ClusterScanCursor cursor = ClusterScanCursor.initalCursor();while (!cursor.isFinished()) { final Object[] response = clusterClient .scan( cursor, ScanOptions.builder() .matchPattern("key:*") .type(ScanOptions.ObjectType.STRING) .build()) .get(); cursor.releaseCursorHandle();
cursor = (ClusterScanCursor) response[0]; final Object[] data = (Object[]) response[1]; for (Object datum : data) { result.add(datum.toString()); }}cursor.releaseCursorHandle();await client.mset([ { key: "my_key1", value: "value1" }, { key: "my_key2", value: "value2" }, { key: "not_my_key", value: "value3" }, { key: "something_else", value: "value4" }]);let cursor = new ClusterScanCursor();const matchedKeys: string[] = [];
while (!cursor.isFinished()) { [cursor, keys] = await client.scan(cursor, { match: "*key*" }); matchedKeys.push(...keys);}// Returns matching keys such as ["my_key1", "my_key2", "not_my_key"]keysToSet := map[string]string{ "my_key1": "value1", "my_key2": "value2", "not_my_key": "value3", "something_else": "value4",}client.MSet(context.Background(), keysToSet)
cursor := models.NewClusterScanCursor()opts := options.NewClusterScanOptions().SetMatch("*key*")matchedKeys := []string{}
for !cursor.IsFinished() { result, err := client.ScanWithOptions(context.Background(), cursor, *opts) if err != nil { break } matchedKeys = append(matchedKeys, result.Keys...) cursor = result.Cursor}// Returns matching keys such as ["my_key1", "my_key2", "not_my_key"]$client->mset(['my_key1' => 'value1', 'my_key2' => 'value2', 'not_my_key' => 'value3', 'something_else' => 'value4']);
$cursor = new ClusterScanCursor();$matchingKeys = [];
while (true) { $keys = $client->scan($cursor, '*key*'); if ($keys) { $matchingKeys = array_merge($matchingKeys, $keys); }
$cursor = new ClusterScanCursor($cursor->getNextCursor());
if ($cursor->isFinished()) { break; }}// Returns matching keys such as ['my_key1', 'my_key2', 'not_my_key']Scan With The Count Option
Section titled “Scan With The Count Option”await client.mset({b'my_key1': b'value1', b'my_key2': b'value2', b'not_my_key': b'value3', b'something_else': b'value4'})cursor = ClusterScanCursor()await client.scan(cursor, count=1)# Returns around `count` amount of keys: [b'my_key1']Set<String> result = new LinkedHashSet<>();ClusterScanCursor cursor = ClusterScanCursor.initalCursor();while (!cursor.isFinished()) { final Object[] response = clusterClient.scan(cursor, ScanOptions.builder().count(100L).build()).get(); cursor.releaseCursorHandle();
cursor = (ClusterScanCursor) response[0]; final Object[] data = (Object[]) response[1]; for (Object datum : data) { result.add(datum.toString()); }}cursor.releaseCursorHandle();await client.mset([ { key: "my_key1", value: "value1" }, { key: "my_key2", value: "value2" }, { key: "not_my_key", value: "value3" }, { key: "something_else", value: "value4" }]);let cursor = new ClusterScanCursor();const allKeys: string[] = [];
while (!cursor.isFinished()) { [cursor, keys] = await client.scan(cursor, { count: 10 }); allKeys.push(...keys);}// Returns around `count` amount of keys per iterationkeysToSet := map[string]string{ "my_key1": "value1", "my_key2": "value2", "not_my_key": "value3", "something_else": "value4",}client.MSet(context.Background(), keysToSet)
cursor := models.NewClusterScanCursor()opts := options.NewClusterScanOptions().SetCount(10)allKeys := []string{}
for !cursor.IsFinished() { result, err := client.ScanWithOptions(context.Background(), cursor, *opts) if err != nil { break } allKeys = append(allKeys, result.Keys...) cursor = result.Cursor}// Returns around `count` amount of keys per iteration$client->mset(['my_key1' => 'value1', 'my_key2' => 'value2', 'not_my_key' => 'value3', 'something_else' => 'value4']);
$cursor = new ClusterScanCursor();$keys = $client->scan($cursor, null, 1); // 1 is the count parameter// Returns around `count` amount of keys: ['my_key1']Scan For a Specific Data Type.
Section titled “Scan For a Specific Data Type.”await client.mset({b'key1': b'value1', b'key2': b'value2', b'key3': b'value3'})await client.sadd(b"this_is_a_set", [b"value4"])cursor = ClusterScanCursor()all_keys = []while not cursor.is_finished(): cursor, keys = await client.scan(cursor, type=ObjectType.STRING) all_keys.extend(keys)print(all_keys) # Output: [b'key1', b'key2', b'key3']Set<String> result = new LinkedHashSet<>();ClusterScanCursor cursor = ClusterScanCursor.initalCursor();while (!cursor.isFinished()) { final Object[] response = clusterClient .scan( cursor, ScanOptions.builder() .type(ScanOptions.ObjectType.STRING) .build()) .get(); cursor.releaseCursorHandle();
cursor = (ClusterScanCursor) response[0]; final Object[] data = (Object[]) response[1]; for (Object datum : data) { result.add(datum.toString()); }}cursor.releaseCursorHandle();await client.mset([ { key: "key1", value: "value1" }, { key: "key2", value: "value2" }, { key: "key3", value: "value3" }]);await client.sadd("thisIsASet", ["value4"]);let cursor = new ClusterScanCursor();const stringKeys: string[] = [];
while (!cursor.isFinished()) { [cursor, keys] = await client.scan(cursor, { type: ObjectType.STRING }); stringKeys.push(...keys);}// Output: ["key1", "key2", "key3"]keysToSet := map[string]string{ "key1": "value1", "key2": "value2", "key3": "value3",}client.MSet(context.Background(), keysToSet)client.SAdd(context.Background(), "thisIsASet", []string{"value4"})
cursor := models.NewClusterScanCursor()opts := options.NewClusterScanOptions().SetType(constants.ObjectTypeString)stringKeys := []string{}
for !cursor.IsFinished() { result, err := client.ScanWithOptions(context.Background(), cursor, *opts) if err != nil { break } stringKeys = append(stringKeys, result.Keys...) cursor = result.Cursor}// Output: ["key1", "key2", "key3"]$client->mset(['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3']);$client->sadd('this_is_a_set', 'value4');
$cursor = new ClusterScanCursor();$allKeys = [];
while (true) { $keys = $client->scan($cursor, null, 0, 'string'); if ($keys) { $allKeys = array_merge($allKeys, $keys); }
$cursor = new ClusterScanCursor($cursor->getNextCursor());
if ($cursor->isFinished()) { break; }}// Output: ['key1', 'key2', 'key3']