├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── slock.c
├── slock.h
└── tests
├── golang
├── go.mod
├── go.sum
└── main.go
└── php
├── client.php
├── client1.php
└── rlock_client.php
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.xo
9 | *.elf
10 |
11 | # Linker output
12 | *.ilk
13 | *.map
14 | *.exp
15 |
16 | # Precompiled Headers
17 | *.gch
18 | *.pch
19 |
20 | # Libraries
21 | *.lib
22 | *.a
23 | *.la
24 | *.lo
25 |
26 | # Shared objects (inc. Windows DLLs)
27 | *.dll
28 | *.so
29 | *.so.*
30 | *.dylib
31 |
32 | # Executables
33 | *.exe
34 | *.out
35 | *.app
36 | *.i*86
37 | *.x86_64
38 | *.hex
39 |
40 | # Debug files
41 | *.dSYM/
42 | *.su
43 | *.idb
44 | *.pdb
45 |
46 | # Kernel Module Compile Results
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 | .idea/
54 | /cmake-build-debug
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
2 | project(slock C)
3 |
4 |
5 | AUX_SOURCE_DIRECTORY(. SRC_LIST)
6 | add_library(slock SHARED ${SRC_LIST})
7 | set_target_properties(slock PROPERTIES output_name "slock")
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Adam
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | # find the OS
3 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
4 |
5 | # Compile flags for linux / osx
6 | ifeq ($(uname_S),Linux)
7 | SHOBJ_CFLAGS ?= -W -Wall -fno-common -g -ggdb -std=c99 -O2
8 | SHOBJ_LDFLAGS ?= -shared
9 | else
10 | SHOBJ_CFLAGS ?= -W -Wall -dynamic -fno-common -g -ggdb -std=c99 -O2
11 | SHOBJ_LDFLAGS ?= -bundle -undefined dynamic_lookup
12 | endif
13 |
14 | .SUFFIXES: .c .so .xo .o
15 |
16 | all: slock.so
17 |
18 | .c.xo:
19 | $(CC) -I. $(CFLAGS) $(SHOBJ_CFLAGS) -fPIC -c $< -o $@
20 |
21 | slock.xo: ../src/redismodule.h
22 |
23 | slock.so: slock.xo
24 | $(LD) -o $@ $< $(SHOBJ_LDFLAGS) $(LIBS) -lc
25 |
26 | clean:
27 | rm -rf *.xo *.so
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/wujunwei/redlock)
2 | [](https://github.com/wujunwei/redlock)
3 | [](https://github.com/wujunwei/redlock)
4 | []()
5 |
6 | # redlock
7 | a way to achieve distributed lock by redis module
8 |
9 |
10 |
11 |
12 | ### build
13 |
14 | ```
15 | git clone --depth=1 git@github.com:redis/redis.git
16 | cd redis
17 | git clone https://github.com/wujunwei/redlock
18 | cd redlock
19 | make
20 | ```
21 |
22 | ### install
23 |
24 | ```
25 | //run it in redis cli or add it into the conf
26 | module load redlock.so
27 | ```
28 | ### How to use
29 |
30 | * **slock.lock lock_key (expire_time)**
31 |
The command will return result immediately ,you shall call lock in a while or give up locking
32 | * **slock.unlock key**
33 |
Release the write-lock, if the lock wasn't been created by the same client, it will fail with 0.
34 | * **slock.rlock key (expire_time)**
35 |
Acquire the read-lock(share lock), if the lock wasn't been created by the same client, it will fail with 0.
36 | * **slock.runlock key**
37 |
Reduce the readers count of read-lock(share lock), if the readers count equal to 0 ,it will be released.
38 |
This command won't be limited by the different client. if the lock isn't created by the command "slock.rlock", it will fail with 0.
39 | * **slock.info key**
40 |
This command will return an array with four integers, first is the client id , second is the time when lock was created , the third one is whether the lock is write-lock or not (reply with 0 present lock fail, and otherwise success) and the last one is the count of require the read lock(about the lock command ,it 's always 0).
41 |
42 | **PLEASE NOTE:** The module recommend to be used for stand-alone or Sharding mode,use it carefully.
43 |
--------------------------------------------------------------------------------
/slock.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by adam on 2018-11-28.
3 | //
4 | #include "slock.h"
5 |
6 | /**
7 | * slock.lock lock_key expire
8 | * the command lock will return result immediately ,
9 | * you shall call lock in a while or give up locking
10 | * @param ctx
11 | * @param argv
12 | * @param argc
13 | * @return int
14 | */
15 | SLock *createSlock(RedisModuleCtx *ctx, int is_write) {
16 | SLock *lock = RedisModule_Alloc(sizeof(*lock));
17 | lock->write_client_id = RedisModule_GetClientId(ctx);
18 | lock->reader_count = 0;
19 | lock->lock_time = RedisModule_Milliseconds();
20 | lock->is_write = is_write ? TRUE : FALSE;
21 | return lock;
22 | }
23 |
24 | int SlockLock_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
25 | RedisModule_AutoMemory(ctx);
26 | if (argc < 2) {
27 | return RedisModule_WrongArity(ctx);
28 | }
29 | RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE);
30 | int keyType = RedisModule_KeyType(key);
31 | if (keyType == REDISMODULE_KEYTYPE_EMPTY) {
32 | SLock *lock = createSlock(ctx, TRUE);
33 | RedisModule_ModuleTypeSetValue(key, SLockType, lock);
34 | if (argc == 3) {
35 | long long expire_time;
36 | if (RedisModule_StringToLongLong(argv[2], &expire_time) != REDISMODULE_OK) {
37 | return RedisModule_ReplyWithError(ctx, ERR_INVALID_EXPIRE_TIME);
38 | }
39 | RedisModule_SetExpire(key, expire_time);
40 | }
41 | RedisModule_ReplyWithLongLong(ctx, 1);
42 | } else {
43 | if (RedisModule_ModuleTypeGetType(key) != SLockType) {
44 | return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
45 | }
46 | RedisModule_ReplyWithLongLong(ctx, 0);
47 | }
48 | RedisModule_CloseKey(key);
49 | return REDISMODULE_OK;
50 | }
51 |
52 | /**
53 | * Slock.unlock key
54 | * @param ctx
55 | * @param argv
56 | * @param argc
57 | * @return int
58 | */
59 | int SlockUnLock_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
60 | RedisModule_AutoMemory(ctx);
61 | if (argc != 2) {
62 | return RedisModule_WrongArity(ctx);
63 | }
64 |
65 | RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE | REDISMODULE_READ);
66 | if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
67 | return RedisModule_ReplyWithNull(ctx);
68 | }
69 | if (RedisModule_ModuleTypeGetType(key) != SLockType) {
70 | return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
71 | } else {
72 | SLock *lock = RedisModule_ModuleTypeGetValue(key);
73 | if (lock->write_client_id == RedisModule_GetClientId(ctx) && lock->is_write) {
74 | RedisModule_DeleteKey(key);
75 | RedisModule_ReplyWithLongLong(ctx, 1);
76 | } else {
77 | RedisModule_ReplyWithLongLong(ctx, 0);
78 | }
79 | }
80 | RedisModule_CloseKey(key);
81 | return REDISMODULE_OK;
82 | }
83 |
84 |
85 | /**
86 | * slock.rlock lock_key expire
87 | * the command lock will return result immediately ,
88 | * you shall call lock in a while or give up locking
89 | * @param ctx
90 | * @param argv
91 | * @param argc
92 | * @return int
93 | */
94 | int SlockRLock_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
95 | RedisModule_AutoMemory(ctx);
96 | if (argc < 2) {
97 | return RedisModule_WrongArity(ctx);
98 | }
99 | RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE);
100 | int keyType = RedisModule_KeyType(key);
101 | if (keyType == REDISMODULE_KEYTYPE_EMPTY) {
102 | SLock *lock = createSlock(ctx, FALSE);
103 | RedisModule_ModuleTypeSetValue(key, SLockType, lock);
104 | } else {
105 | // Exclude write-lock
106 | if (RedisModule_ModuleTypeGetType(key) != SLockType) {
107 | return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
108 | }
109 | SLock *lock = RedisModule_ModuleTypeGetValue(key);
110 | if (lock->is_write) {
111 | return RedisModule_ReplyWithLongLong(ctx, 0);
112 | }
113 | lock->reader_count += 1;
114 | }
115 | if (argc == 3) {
116 | long long expire_time;
117 | if (RedisModule_StringToLongLong(argv[2], &expire_time) != REDISMODULE_OK) {
118 | return RedisModule_ReplyWithError(ctx, ERR_INVALID_EXPIRE_TIME);
119 | }
120 | RedisModule_SetExpire(key, expire_time);
121 | }
122 | RedisModule_ReplyWithLongLong(ctx, 1);
123 | RedisModule_CloseKey(key);
124 | return REDISMODULE_OK;
125 | }
126 |
127 | /**
128 | * Slock.unlock key
129 | * @param ctx
130 | * @param argv
131 | * @param argc
132 | * @return int
133 | */
134 | int SlockRUnLock_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
135 | RedisModule_AutoMemory(ctx);
136 | if (argc != 2) {
137 | return RedisModule_WrongArity(ctx);
138 | }
139 |
140 | RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE | REDISMODULE_READ);
141 | if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
142 | return RedisModule_ReplyWithNull(ctx);
143 | }
144 | if (RedisModule_ModuleTypeGetType(key) != SLockType) {
145 | return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
146 | }
147 | SLock *lock;
148 | lock = RedisModule_ModuleTypeGetValue(key);
149 | if (!lock->is_write) {
150 | if (--lock->reader_count <= 0) {
151 | RedisModule_DeleteKey(key);
152 | }
153 | RedisModule_ReplyWithLongLong(ctx, 1);
154 | } else {
155 | RedisModule_ReplyWithLongLong(ctx, 0);
156 | }
157 | RedisModule_CloseKey(key);
158 | return REDISMODULE_OK;
159 | }
160 |
161 | /**
162 | * SLOCK.INFO key
163 | * this command will return an array with four integers, first is the client id , second is the time when lock was created , the third one is whether the lock is write-lock or not (reply with 0 present lock fail, and otherwise success) and the last one is the count of require the read lock(about the lock command ,it 's always 0).
164 | * @param ctx
165 | * @param argv
166 | * @param agrc
167 | * @return int
168 | */
169 | int SlockInfo_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
170 | RedisModule_AutoMemory(ctx);
171 | if (argc != 2) {
172 | return RedisModule_WrongArity(ctx);
173 | }
174 |
175 | RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
176 | if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
177 | return RedisModule_ReplyWithNull(ctx);
178 | }
179 | //判断键类型
180 | if (RedisModule_ModuleTypeGetType(key) != SLockType) {
181 | return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
182 | } else {
183 | SLock *lock = RedisModule_ModuleTypeGetValue(key);
184 | RedisModule_ReplyWithArray(ctx, 4);
185 | RedisModule_ReplyWithLongLong(ctx, lock->write_client_id);
186 | RedisModule_ReplyWithLongLong(ctx, lock->lock_time);
187 | RedisModule_ReplyWithLongLong(ctx, lock->is_write);
188 | RedisModule_ReplyWithLongLong(ctx, lock->reader_count);
189 | }
190 | RedisModule_CloseKey(key);
191 | return REDISMODULE_OK;
192 | }
193 |
194 | /* ========================== type methods ======================= */
195 |
196 | void *SLockRdbLoad(RedisModuleIO *rdb, int encver) {
197 | if (encver != 0) {
198 | /* RedisModule_Log("warning","Can't load data with version %d", encver);*/
199 | return NULL;
200 | }
201 | SLock *sl = RedisModule_Alloc(sizeof(sl));
202 | sl->write_client_id = RedisModule_LoadUnsigned(rdb);
203 | sl->lock_time = RedisModule_LoadSigned(rdb);
204 | sl->is_write = RedisModule_LoadSigned(rdb);
205 | sl->reader_count = RedisModule_LoadUnsigned(rdb);
206 | return sl;
207 | }
208 |
209 | void SLockRdbSave(RedisModuleIO *rdb, void *value) {
210 | SLock *sl = value;
211 | RedisModule_SaveUnsigned(rdb, sl->write_client_id);
212 | RedisModule_SaveSigned(rdb, sl->lock_time);
213 | RedisModule_SaveSigned(rdb, sl->is_write);
214 | RedisModule_SaveUnsigned(rdb, sl->reader_count);
215 | }
216 |
217 | void SLockAofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) {
218 | SLock *sl = value;
219 | if (sl->is_write) {
220 | RedisModule_EmitAOF(aof, "SLOCK.LOCK", "s", key);
221 | return;
222 | }
223 |
224 | unsigned long long count = sl->reader_count;
225 | while (count--){
226 | RedisModule_EmitAOF(aof, "SLOCK.rLOCK", "s", key);
227 | }
228 |
229 | }
230 |
231 | /* The goal of this function is to return the amount of memory used by
232 | * the HelloType value. */
233 | size_t SLockMemUsage(const void *value) {
234 | const SLock *hto = value;
235 | return sizeof(*hto);
236 | }
237 |
238 | void SLockFree(void *value) {
239 | RedisModule_Free(value);
240 | }
241 |
242 | void SLockDigest(RedisModuleDigest *md, void *value) {
243 | SLock *sl = value;
244 | RedisModule_DigestAddLongLong(md, sl->write_client_id);
245 | RedisModule_DigestAddLongLong(md, sl->is_write);
246 | RedisModule_DigestAddLongLong(md, sl->reader_count);
247 | RedisModule_DigestAddLongLong(md, sl->lock_time);
248 | RedisModule_DigestEndSequence(md);
249 | }
250 |
251 | /* This function must be present on each Redis module. It is used in order to
252 | * register the commands into the Redis server. */
253 | int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
254 | REDISMODULE_NOT_USED(argv);
255 | REDISMODULE_NOT_USED(argc);
256 |
257 | if (RedisModule_Init(ctx, MODULE_NAME, MODULE_VERSION, REDISMODULE_APIVER_1)
258 | == REDISMODULE_ERR)
259 | return REDISMODULE_ERR;
260 | RedisModuleTypeMethods tm = {
261 | .version = REDISMODULE_TYPE_METHOD_VERSION,
262 | .rdb_load = SLockRdbLoad,
263 | .rdb_save = SLockRdbSave,
264 | .aof_rewrite = SLockAofRewrite,
265 | .mem_usage = SLockMemUsage,
266 | .free = SLockFree,
267 | .digest = SLockDigest
268 | };
269 |
270 | SLockType = RedisModule_CreateDataType(ctx, "slocktype", 0, &tm);
271 | if (SLockType == NULL) return REDISMODULE_ERR;
272 |
273 | if (RedisModule_CreateCommand(ctx, COMMAND_SLOCK_UNLOCK, SlockUnLock_RedisCommand, "write", 1, 1, 1) ==
274 | REDISMODULE_ERR)
275 | return REDISMODULE_ERR;
276 |
277 | if (RedisModule_CreateCommand(ctx, COMMAND_SLOCK_LOCK, SlockLock_RedisCommand, "write", 1, 1, 1) == REDISMODULE_ERR)
278 | return REDISMODULE_ERR;
279 |
280 |
281 | if (RedisModule_CreateCommand(ctx, COMMAND_SLOCK_RLOCK, SlockRLock_RedisCommand, "write", 1, 1, 1) ==
282 | REDISMODULE_ERR)
283 | return REDISMODULE_ERR;
284 |
285 | if (RedisModule_CreateCommand(ctx, COMMAND_SLOCK_RUNLOCK, SlockRUnLock_RedisCommand, "write", 1, 1, 1) ==
286 | REDISMODULE_ERR)
287 | return REDISMODULE_ERR;
288 |
289 | if (RedisModule_CreateCommand(ctx, COMMAND_SLOCK_INFO, SlockInfo_RedisCommand, "readonly", 1, 1, 1) ==
290 | REDISMODULE_ERR)
291 | return REDISMODULE_ERR;
292 |
293 | return REDISMODULE_OK;
294 | }
295 |
--------------------------------------------------------------------------------
/slock.h:
--------------------------------------------------------------------------------
1 | #ifndef SLOCK_H
2 | #define SLOCK_H
3 |
4 | #include "../src/redismodule.h"
5 | #include
6 |
7 | static RedisModuleType *SLockType;
8 |
9 | #define TRUE 1
10 | #define FALSE 0
11 |
12 | typedef struct slock {
13 | mstime_t lock_time;
14 | int is_write;
15 | unsigned long long reader_count;
16 | unsigned long long write_client_id;
17 | } SLock;
18 |
19 |
20 | //Error message definition
21 | #define ERR_INVALID_EXPIRE_TIME "ERR invalid expireTime"
22 |
23 | //COMMAND TYPE
24 | #define COMMAND_SLOCK_UNLOCK "slock.unlock"
25 | #define COMMAND_SLOCK_LOCK "slock.lock"
26 | #define COMMAND_SLOCK_INFO "slock.info"
27 | #define COMMAND_SLOCK_RLOCK "slock.rlock"
28 | #define COMMAND_SLOCK_RUNLOCK "slock.runlock"
29 |
30 | //MODULE INFO
31 | #define MODULE_NAME "slock"
32 | #define MODULE_VERSION 1
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/tests/golang/go.mod:
--------------------------------------------------------------------------------
1 | module test
2 |
3 | go 1.19
4 |
5 | require github.com/go-redis/redis/v8 v8.11.5
6 |
7 | require (
8 | github.com/cespare/xxhash/v2 v2.1.2 // indirect
9 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
10 | )
11 |
--------------------------------------------------------------------------------
/tests/golang/go.sum:
--------------------------------------------------------------------------------
1 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
2 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
3 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
4 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
5 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
6 | github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
7 | github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
8 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
9 | github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
10 | github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
11 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
12 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
13 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
14 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
15 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
16 |
--------------------------------------------------------------------------------
/tests/golang/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "github.com/go-redis/redis/v8"
7 | )
8 |
9 | var ctx = context.Background()
10 |
11 | func main() {
12 | rdb := redis.NewClient(&redis.Options{
13 | Addr: "localhost:6379",
14 | Password: "", // no password set
15 | DB: 0, // use default DB
16 | })
17 | defer func(rdb *redis.Client) {
18 | err := rdb.Close()
19 | if err != nil {
20 | fmt.Println(err)
21 | }
22 | }(rdb)
23 | //lock test
24 | fmt.Println(rdb.Do(ctx , "slock.lock","test",10000).String())
25 | //try unlock
26 | fmt.Println(rdb.Do(ctx, "slock.info","test").String())
27 | fmt.Println(rdb.Do(ctx, "slock.unlock","test").String())
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/tests/php/client.php:
--------------------------------------------------------------------------------
1 | connect("127.0.0.1", "6379");
5 | //try lock
6 | var_dump($a->rawCommand("slock.lock", ...["test", 10000]));
7 | var_dump($a->rawCommand("slock.lock", ...["test", 10000]));
8 | //try unlock
9 | var_dump($a->rawCommand("slock.info", "test"));
10 | var_dump($a->rawCommand("slock.unlock", "test"));
11 | $a->close();
12 |
--------------------------------------------------------------------------------
/tests/php/client1.php:
--------------------------------------------------------------------------------
1 | connect("127.0.0.1", "6379");
6 | //try lock,it will fail
7 | var_dump($a->rawCommand("slock.lock", ["test", 10000]));
8 | //try unlock it will fail too when the lock was locked by client.php
9 | var_dump($a->rawCommand("slock.unlock", "test"));
10 | $a->close();
11 |
--------------------------------------------------------------------------------
/tests/php/rlock_client.php:
--------------------------------------------------------------------------------
1 | connect("127.0.0.1", "6379");
6 | //try lock,it will fail
7 | var_dump($a->rawCommand("slock.rlock", ["test", 10000]));
8 | sleep(5);
9 | var_dump($a->rawCommand("slock.rlock", ["test", 10000]));
10 | var_dump($a->ttl("slock.rlock"));
11 | // the expired time will be refresh.
12 | var_dump($a->rawCommand("slock.unlock", "test"));
13 | $a->close();
14 |
--------------------------------------------------------------------------------