@@ -9,6 +9,69 @@ import (
99 intl "github.com/redis/rueidis/internal/cmds"
1010)
1111
12+ var crc16tab = [256 ]uint16 {
13+ 0x0000 , 0x1021 , 0x2042 , 0x3063 , 0x4084 , 0x50a5 , 0x60c6 , 0x70e7 ,
14+ 0x8108 , 0x9129 , 0xa14a , 0xb16b , 0xc18c , 0xd1ad , 0xe1ce , 0xf1ef ,
15+ 0x1231 , 0x0210 , 0x3273 , 0x2252 , 0x52b5 , 0x4294 , 0x72f7 , 0x62d6 ,
16+ 0x9339 , 0x8318 , 0xb37b , 0xa35a , 0xd3bd , 0xc39c , 0xf3ff , 0xe3de ,
17+ 0x2462 , 0x3443 , 0x0420 , 0x1401 , 0x64e6 , 0x74c7 , 0x44a4 , 0x5485 ,
18+ 0xa56a , 0xb54b , 0x8528 , 0x9509 , 0xe5ee , 0xf5cf , 0xc5ac , 0xd58d ,
19+ 0x3653 , 0x2672 , 0x1611 , 0x0630 , 0x76d7 , 0x66f6 , 0x5695 , 0x46b4 ,
20+ 0xb75b , 0xa77a , 0x9719 , 0x8738 , 0xf7df , 0xe7fe , 0xd79d , 0xc7bc ,
21+ 0x48c4 , 0x58e5 , 0x6886 , 0x78a7 , 0x0840 , 0x1861 , 0x2802 , 0x3823 ,
22+ 0xc9cc , 0xd9ed , 0xe98e , 0xf9af , 0x8948 , 0x9969 , 0xa90a , 0xb92b ,
23+ 0x5af5 , 0x4ad4 , 0x7ab7 , 0x6a96 , 0x1a71 , 0x0a50 , 0x3a33 , 0x2a12 ,
24+ 0xdbfd , 0xcbdc , 0xfbbf , 0xeb9e , 0x9b79 , 0x8b58 , 0xbb3b , 0xab1a ,
25+ 0x6ca6 , 0x7c87 , 0x4ce4 , 0x5cc5 , 0x2c22 , 0x3c03 , 0x0c60 , 0x1c41 ,
26+ 0xedae , 0xfd8f , 0xcdec , 0xddcd , 0xad2a , 0xbd0b , 0x8d68 , 0x9d49 ,
27+ 0x7e97 , 0x6eb6 , 0x5ed5 , 0x4ef4 , 0x3e13 , 0x2e32 , 0x1e51 , 0x0e70 ,
28+ 0xff9f , 0xefbe , 0xdfdd , 0xcffc , 0xbf1b , 0xaf3a , 0x9f59 , 0x8f78 ,
29+ 0x9188 , 0x81a9 , 0xb1ca , 0xa1eb , 0xd10c , 0xc12d , 0xf14e , 0xe16f ,
30+ 0x1080 , 0x00a1 , 0x30c2 , 0x20e3 , 0x5004 , 0x4025 , 0x7046 , 0x6067 ,
31+ 0x83b9 , 0x9398 , 0xa3fb , 0xb3da , 0xc33d , 0xd31c , 0xe37f , 0xf35e ,
32+ 0x02b1 , 0x1290 , 0x22f3 , 0x32d2 , 0x4235 , 0x5214 , 0x6277 , 0x7256 ,
33+ 0xb5ea , 0xa5cb , 0x95a8 , 0x8589 , 0xf56e , 0xe54f , 0xd52c , 0xc50d ,
34+ 0x34e2 , 0x24c3 , 0x14a0 , 0x0481 , 0x7466 , 0x6447 , 0x5424 , 0x4405 ,
35+ 0xa7db , 0xb7fa , 0x8799 , 0x97b8 , 0xe75f , 0xf77e , 0xc71d , 0xd73c ,
36+ 0x26d3 , 0x36f2 , 0x0691 , 0x16b0 , 0x6657 , 0x7676 , 0x4615 , 0x5634 ,
37+ 0xd94c , 0xc96d , 0xf90e , 0xe92f , 0x99c8 , 0x89e9 , 0xb98a , 0xa9ab ,
38+ 0x5844 , 0x4865 , 0x7806 , 0x6827 , 0x18c0 , 0x08e1 , 0x3882 , 0x28a3 ,
39+ 0xcb7d , 0xdb5c , 0xeb3f , 0xfb1e , 0x8bf9 , 0x9bd8 , 0xabbb , 0xbb9a ,
40+ 0x4a75 , 0x5a54 , 0x6a37 , 0x7a16 , 0x0af1 , 0x1ad0 , 0x2ab3 , 0x3a92 ,
41+ 0xfd2e , 0xed0f , 0xdd6c , 0xcd4d , 0xbdaa , 0xad8b , 0x9de8 , 0x8dc9 ,
42+ 0x7c26 , 0x6c07 , 0x5c64 , 0x4c45 , 0x3ca2 , 0x2c83 , 0x1ce0 , 0x0cc1 ,
43+ 0xef1f , 0xff3e , 0xcf5d , 0xdf7c , 0xaf9b , 0xbfba , 0x8fd9 , 0x9ff8 ,
44+ 0x6e17 , 0x7e36 , 0x4e55 , 0x5e74 , 0x2e93 , 0x3eb2 , 0x0ed1 , 0x1ef0 ,
45+ }
46+
47+ func crc16 (key string ) (crc uint16 ) {
48+ for i := 0 ; i < len (key ); i ++ {
49+ crc = (crc << 8 ) ^ crc16tab [(uint8 (crc >> 8 )^ key [i ])& 0x00FF ]
50+ }
51+ return crc
52+ }
53+
54+ func slot (key string ) uint16 {
55+ var s , e int
56+ for ; s < len (key ); s ++ {
57+ if key [s ] == '{' {
58+ break
59+ }
60+ }
61+ if s == len (key ) {
62+ return crc16 (key ) & 16383
63+ }
64+ for e = s + 1 ; e < len (key ); e ++ {
65+ if key [e ] == '}' {
66+ break
67+ }
68+ }
69+ if e == len (key ) || e == s + 1 {
70+ return crc16 (key ) & 16383
71+ }
72+ return crc16 (key [s + 1 :e ]) & 16383
73+ }
74+
1275// MGetCache is a helper that consults the client-side caches with multiple keys by grouping keys within the same slot into multiple GETs
1376func MGetCache (client Client , ctx context.Context , ttl time.Duration , keys []string ) (ret map [string ]RedisMessage , err error ) {
1477 if len (keys ) == 0 {
@@ -269,16 +332,18 @@ func arrayToKV(m map[string]RedisMessage, arr []RedisMessage, keys []string) map
269332
270333func clusterMGet (client Client , ctx context.Context , keys []string ) (ret map [string ]RedisMessage , err error ) {
271334 ret = make (map [string ]RedisMessage , len (keys ))
272- slotCmds := intl .MGets (keys )
273- if len (slotCmds ) == 0 {
274- return ret , nil
335+ slotGroups := make (map [uint16 ][]string )
336+ for _ , key := range keys {
337+ ks := slot (key )
338+ slotGroups [ks ] = append (slotGroups [ks ], key )
275339 }
276- cmds := mgetcmdsp .Get (len ( slotCmds ) , len (slotCmds ))
340+ cmds := mgetcmdsp .Get (0 , len (slotGroups ))
277341 defer mgetcmdsp .Put (cmds )
278- i := 0
279- for _ , cmd := range slotCmds {
280- cmds .s [i ] = cmd .Pin ()
281- i ++
342+ var cmdKeys [][]string
343+ for _ , group := range slotGroups {
344+ cmd := client .B ().Mget ().Key (group ... ).Build ().Pin ()
345+ cmds .s = append (cmds .s , cmd )
346+ cmdKeys = append (cmdKeys , group )
282347 }
283348 resps := client .DoMulti (ctx , cmds .s ... )
284349 defer resultsp .Put (& redisresults {s : resps })
@@ -287,9 +352,7 @@ func clusterMGet(client Client, ctx context.Context, keys []string) (ret map[str
287352 if err != nil {
288353 return nil , err
289354 }
290- commands := cmds .s [i ].Commands ()
291- cmdKeys := commands [1 :]
292- ret = arrayToKV (ret , arr , cmdKeys )
355+ ret = arrayToKV (ret , arr , cmdKeys [i ])
293356 }
294357 for i := range cmds .s {
295358 intl .PutCompletedForce (cmds .s [i ])
@@ -299,16 +362,21 @@ func clusterMGet(client Client, ctx context.Context, keys []string) (ret map[str
299362
300363func clusterJsonMGet (client Client , ctx context.Context , keys []string , path string ) (ret map [string ]RedisMessage , err error ) {
301364 ret = make (map [string ]RedisMessage , len (keys ))
302- slotCmds := intl .JsonMGets (keys , path )
303- if len (slotCmds ) == 0 {
365+ slotGroups := make (map [uint16 ][]string )
366+ for _ , key := range keys {
367+ ks := slot (key )
368+ slotGroups [ks ] = append (slotGroups [ks ], key )
369+ }
370+ if len (slotGroups ) == 0 {
304371 return ret , nil
305372 }
306- cmds := mgetcmdsp .Get (len ( slotCmds ) , len (slotCmds ))
373+ cmds := mgetcmdsp .Get (0 , len (slotGroups ))
307374 defer mgetcmdsp .Put (cmds )
308- i := 0
309- for _ , cmd := range slotCmds {
310- cmds .s [i ] = cmd .Pin ()
311- i ++
375+ var cmdKeys [][]string
376+ for _ , group := range slotGroups {
377+ cmd := client .B ().JsonMget ().Key (group ... ).Path (path ).Build ().Pin ()
378+ cmds .s = append (cmds .s , cmd )
379+ cmdKeys = append (cmdKeys , group )
312380 }
313381 resps := client .DoMulti (ctx , cmds .s ... )
314382 defer resultsp .Put (& redisresults {s : resps })
@@ -317,9 +385,7 @@ func clusterJsonMGet(client Client, ctx context.Context, keys []string, path str
317385 if err != nil {
318386 return nil , err
319387 }
320- commands := cmds .s [i ].Commands ()
321- cmdKeys := commands [1 : len (commands )- 1 ]
322- ret = arrayToKV (ret , arr , cmdKeys )
388+ ret = arrayToKV (ret , arr , cmdKeys [i ])
323389 }
324390 for i := range cmds .s {
325391 intl .PutCompletedForce (cmds .s [i ])
0 commit comments