kedis-python 0.1.0__py3-none-any.whl
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.
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kedis-python
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Redis-inspired in-memory store in Python
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# 🚀 Kedis-Python
|
|
12
|
+
|
|
13
|
+
**A Redis-inspired in-memory datastore built in pure Python to explore storage engines, networking, persistence, caching, and systems architecture.**
|
|
14
|
+
|
|
15
|
+
> Built to understand systems, not just use them.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# 📖 Overview
|
|
20
|
+
|
|
21
|
+
Kedis-Python is a Redis-inspired in-memory datastore implemented from scratch in Python.
|
|
22
|
+
|
|
23
|
+
The project was created to explore how modern in-memory databases work internally by implementing core components such as:
|
|
24
|
+
|
|
25
|
+
* storage engines
|
|
26
|
+
* command routing
|
|
27
|
+
* networking
|
|
28
|
+
* persistence
|
|
29
|
+
* memory management
|
|
30
|
+
* transactions
|
|
31
|
+
* data structures
|
|
32
|
+
* replication
|
|
33
|
+
|
|
34
|
+
Rather than focusing on Redis compatibility, Kedis focuses on understanding the architectural and engineering principles behind high-performance backend systems.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## 📚 Engine Documentation
|
|
40
|
+
|
|
41
|
+
Dive into the internal grimoire to understand how Kedis achieves microsecond latency:
|
|
42
|
+
* [Architecture & Pipeline](docs/architecture.md)
|
|
43
|
+
* [KESP Wire Protocol](docs/protocol.md)
|
|
44
|
+
* [Networking & Surge Tank](docs/networking.md)
|
|
45
|
+
* [Persistence & I/O Drivetrain](docs/persistence.md)
|
|
46
|
+
* [Command Spellbook](docs/commands.md)
|
|
47
|
+
* [TTL & Lifespan Mechanics](docs/ttl.md)
|
|
48
|
+
* [Pub/Sub Broadcasts](docs/pubsub.md)
|
|
49
|
+
* [Benchmarks & Telemetry](docs/benchmarks.md)
|
|
50
|
+
* [Future Roadmap](docs/roadmap.md)
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# ✨ Features
|
|
55
|
+
|
|
56
|
+
## 🔑 Core Key-Value Operations
|
|
57
|
+
|
|
58
|
+
* SET
|
|
59
|
+
* GET
|
|
60
|
+
* DEL
|
|
61
|
+
* EXISTS
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 📦 Multiple Data Structures
|
|
66
|
+
|
|
67
|
+
### Strings
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
SET user karthik
|
|
71
|
+
GET user
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Lists
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
LPUSH tasks coding
|
|
78
|
+
RPUSH tasks testing
|
|
79
|
+
LPOP tasks
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Sets
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
SADD skills python
|
|
86
|
+
SADD skills systems
|
|
87
|
+
SMEMBERS skills
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Hashes
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
HSET user name karthik
|
|
94
|
+
HGET user name
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Sorted Sets (Skip Lists)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
ZADD leaderboard 100 karthik
|
|
101
|
+
ZRANGE leaderboard
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Implemented using a custom Skip List inspired by Redis sorted set internals, with rank-aware span tracking for fast positional queries.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## ⏳ Expiration Support
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
EXPIRE session 60
|
|
112
|
+
TTL session
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Supports automatic key expiration.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 💾 Persistence
|
|
120
|
+
|
|
121
|
+
Append-Only File (AOF) persistence:
|
|
122
|
+
|
|
123
|
+
* durable write logging
|
|
124
|
+
* automatic recovery on startup
|
|
125
|
+
* AOF compaction support
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🧠 Memory Management
|
|
130
|
+
|
|
131
|
+
LRU-based eviction support:
|
|
132
|
+
|
|
133
|
+
* tracks key usage
|
|
134
|
+
* evicts least recently used entries when limits are reached
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 🔄 Transactions
|
|
139
|
+
|
|
140
|
+
Supports transactional execution:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
MULTI
|
|
144
|
+
SET a 1
|
|
145
|
+
SET b 2
|
|
146
|
+
EXEC
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Optimistic locking via `WATCH` / `UNWATCH`:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
WATCH balance
|
|
153
|
+
MULTI
|
|
154
|
+
DECR balance
|
|
155
|
+
EXEC
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If a watched key is modified by another client before `EXEC`, the transaction is aborted instead of committing against stale state — preventing race conditions on concurrent read-modify-write operations.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 🔌 Custom Wire Protocol (KESP)
|
|
163
|
+
|
|
164
|
+
Kedis implements its own binary-safe wire protocol, KESP, rather than adopting RESP.
|
|
165
|
+
|
|
166
|
+
* Requests and responses are framed with explicit byte-length prefixes, so the parser never has to guess where one message ends and the next begins — the bug class that affects naive `recv()`-based servers
|
|
167
|
+
* Implemented in `parser.py` as a dedicated encoder/decoder, decoupled from the networking layer
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 🔁 Replication
|
|
172
|
+
|
|
173
|
+
Kedis supports master-replica replication:
|
|
174
|
+
|
|
175
|
+
* Replicas connect to a master and perform a `SYNC` handshake to receive the initial dataset
|
|
176
|
+
* The master streams subsequent writes to connected replicas in real time
|
|
177
|
+
* Replicas are read-only — writes issued directly to a replica are rejected
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 🌐 Networking
|
|
182
|
+
|
|
183
|
+
Asyncio-based server implementation supporting:
|
|
184
|
+
|
|
185
|
+
* many concurrent client connections on a single event loop
|
|
186
|
+
* command execution over sockets via the KESP protocol
|
|
187
|
+
* standalone local mode fallback
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 📊 Observability
|
|
192
|
+
|
|
193
|
+
Built-in INFO command exposing:
|
|
194
|
+
|
|
195
|
+
* key counts
|
|
196
|
+
* data type statistics
|
|
197
|
+
* persistence information
|
|
198
|
+
* expiration information
|
|
199
|
+
* runtime metadata
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 📴 Offline / Standalone Mode
|
|
204
|
+
|
|
205
|
+
When the server becomes unavailable:
|
|
206
|
+
|
|
207
|
+
* users can switch to standalone mode
|
|
208
|
+
* local operations continue
|
|
209
|
+
* users are warned about possible state divergence
|
|
210
|
+
* reconnection remains user-controlled
|
|
211
|
+
|
|
212
|
+
This feature was added to explore failure handling and graceful degradation.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
# 🏗️ Architecture
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
Client
|
|
220
|
+
│
|
|
221
|
+
▼
|
|
222
|
+
Asyncio Server
|
|
223
|
+
│
|
|
224
|
+
▼
|
|
225
|
+
KESP Parser
|
|
226
|
+
│
|
|
227
|
+
▼
|
|
228
|
+
Command Router
|
|
229
|
+
│
|
|
230
|
+
▼
|
|
231
|
+
Storage Engine
|
|
232
|
+
├── Strings
|
|
233
|
+
├── Lists
|
|
234
|
+
├── Sets
|
|
235
|
+
├── Hashes
|
|
236
|
+
└── Sorted Sets (Skip Lists)
|
|
237
|
+
│
|
|
238
|
+
├──────────────┐
|
|
239
|
+
▼ ▼
|
|
240
|
+
Persistence Replication
|
|
241
|
+
Layer (AOF) (Master → Replica)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The architecture is intentionally modular to make experimentation and future rewrites easier.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
# ⚡ Benchmark
|
|
249
|
+
Single-thread localhost benchmark
|
|
250
|
+
100,000 total operations (50,000 SET + 50,000 GET)
|
|
251
|
+
```
|
|
252
|
+
| AOF Mode | Throughput |
|
|
253
|
+
|-----------|------------|
|
|
254
|
+
| appendfsync always | ~1,081 req/sec |
|
|
255
|
+
| appendfsync everysec | ~13,898 req/sec |
|
|
256
|
+
```
|
|
257
|
+
### Observation
|
|
258
|
+
|
|
259
|
+
Persistence strategy has a significant impact on throughput.
|
|
260
|
+
|
|
261
|
+
`appendfsync always` prioritizes durability by forcing a disk sync after every write.
|
|
262
|
+
|
|
263
|
+
`appendfsync everysec` batches synchronization operations, significantly improving throughput while accepting up to one second of potential data loss during unexpected crashes.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### Benchmark Configuration
|
|
268
|
+
|
|
269
|
+
- Host: localhost
|
|
270
|
+
- Threads: 1
|
|
271
|
+
- Operations: 100,000
|
|
272
|
+
- Workload:
|
|
273
|
+
- SET
|
|
274
|
+
- GET
|
|
275
|
+
- Persistence:
|
|
276
|
+
- appendfsync always
|
|
277
|
+
- appendfsync everysec
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
# 🧪 Testing
|
|
282
|
+
|
|
283
|
+
The project includes automated tests covering:
|
|
284
|
+
|
|
285
|
+
* command execution
|
|
286
|
+
* data structures
|
|
287
|
+
* persistence recovery
|
|
288
|
+
* expiration behavior
|
|
289
|
+
|
|
290
|
+
Additional coverage is actively being expanded as the project evolves.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
# 🎯 Design Goals
|
|
295
|
+
|
|
296
|
+
Kedis was created to explore:
|
|
297
|
+
|
|
298
|
+
* storage engine design
|
|
299
|
+
* command-driven architectures
|
|
300
|
+
* networking fundamentals
|
|
301
|
+
* persistence strategies
|
|
302
|
+
* memory management
|
|
303
|
+
* data structure implementation
|
|
304
|
+
* systems engineering tradeoffs
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
# 🤔 Why Skip Lists?
|
|
309
|
+
|
|
310
|
+
Sorted Sets are implemented using Skip Lists.
|
|
311
|
+
|
|
312
|
+
Reasons:
|
|
313
|
+
|
|
314
|
+
* expected O(log N) insertion
|
|
315
|
+
* expected O(log N) lookup
|
|
316
|
+
* natural ordered traversal
|
|
317
|
+
* simpler implementation than self-balancing trees
|
|
318
|
+
|
|
319
|
+
This mirrors the design approach used by Redis for sorted sets.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
# 🏎️ Concurrency Ceiling: GIL Contention Analysis
|
|
324
|
+
|
|
325
|
+
This benchmark characterizes Kedis's original threading limitations under the GIL, and was the direct motivation for moving the networking layer to asyncio.
|
|
326
|
+
|
|
327
|
+
<img width="600" height="390" alt="image" src="https://github.com/user-attachments/assets/a9caa7f5-2390-4fc0-a9d4-96c1f36f6800" />
|
|
328
|
+
|
|
329
|
+
### The Dyno Sheet (Hardware Limits)
|
|
330
|
+
|
|
331
|
+
| Active Threads | Throughput (Requests/Sec) |
|
|
332
|
+
| :--- | :--- |
|
|
333
|
+
| **1 Thread** | 13,898 RPS |
|
|
334
|
+
| **2 Threads** | 15,631 RPS |
|
|
335
|
+
| **5 Threads** | 18,390 RPS |
|
|
336
|
+
| **10 Threads** | **21,492 RPS** |
|
|
337
|
+
| **20 Threads** | 13,984 RPS |
|
|
338
|
+
| **50 Threads** | 10,977 RPS |
|
|
339
|
+
|
|
340
|
+
### Systems Analysis: The Python GIL & Global Mutex Lock
|
|
341
|
+
The original Kedis core routing engine used a Global Mutex Lock to serialize access to shared state. No data corruption was observed across stress tests up to 50 threads.
|
|
342
|
+
|
|
343
|
+
* **Parallel I/O Scaling (1-10 Threads):** Throughput actually *increased* under multi-threading. While Thread A held the lock to execute a memory write, the other threads efficiently read packets off the TCP socket in parallel, perfectly masking the network overhead.
|
|
344
|
+
* **Lock Contention (15+ Threads):** As concurrent connections scaled beyond the optimal window, the overhead of the Python Global Interpreter Lock (GIL) thrashing—constantly pausing and waking dozens of threads fighting for the single Mutex lock—created significant context-switching overhead, stabilizing the throughput floor around ~10,000 RPS.
|
|
345
|
+
|
|
346
|
+
**Takeaway:** Throughput peaked at ~10 concurrent connections (21.4k RPS) and degraded past that point as GIL contention dominated — dropping to ~11k RPS at 50 threads. This was a hard ceiling imposed by CPython's threading model, not a tunable parameter — and the direct motivation for the move to asyncio networking, now shipped.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
# ⚠ Known Limitations
|
|
351
|
+
|
|
352
|
+
Kedis is an educational systems project and is **not intended for production use**.
|
|
353
|
+
|
|
354
|
+
Current limitations include:
|
|
355
|
+
|
|
356
|
+
* simplified memory accounting
|
|
357
|
+
* limited fault tolerance compared to production databases
|
|
358
|
+
* no memory-based eviction ceiling (LRU tracks usage, but isn't yet tied to a hard memory limit)
|
|
359
|
+
* AOF persistence is not buffered — writes can trigger a sync depending on config
|
|
360
|
+
|
|
361
|
+
These limitations are intentional learning opportunities and areas of active development.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
# 🛣️ Roadmap
|
|
366
|
+
|
|
367
|
+
Planned improvements:
|
|
368
|
+
|
|
369
|
+
* Buffered AOF persistence
|
|
370
|
+
* Improved observability
|
|
371
|
+
* Memory-based eviction
|
|
372
|
+
* Enhanced benchmark tooling
|
|
373
|
+
* Additional persistence optimizations
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
# 📚 Learning Outcomes
|
|
378
|
+
|
|
379
|
+
This project explores concepts commonly found in modern backend systems:
|
|
380
|
+
|
|
381
|
+
* Redis-style architecture
|
|
382
|
+
* command dispatch systems
|
|
383
|
+
* persistence mechanisms
|
|
384
|
+
* cache eviction policies
|
|
385
|
+
* asyncio networking
|
|
386
|
+
* custom wire protocol design
|
|
387
|
+
* replication
|
|
388
|
+
* transaction processing and optimistic locking
|
|
389
|
+
* skip lists
|
|
390
|
+
* systems performance analysis
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
# 🚀 Future Direction
|
|
395
|
+
|
|
396
|
+
Kedis serves as an architecture and systems-design exploration platform before moving toward lower-level implementations and more advanced storage engine designs.
|
|
397
|
+
|
|
398
|
+
The long-term goal is to understand how production systems are engineered, optimized, and maintained.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
# 🤝 Contributing
|
|
403
|
+
|
|
404
|
+
Suggestions, issues, and discussions are welcome.
|
|
405
|
+
|
|
406
|
+
This project is primarily a learning and exploration platform, but contributions are appreciated.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
# 👨💻 Author
|
|
411
|
+
|
|
412
|
+
**V SS Karthik**
|
|
413
|
+
|
|
414
|
+
AI/ML Student • Systems Enthusiast • Builder of developer tools and infrastructure projects
|
|
415
|
+
|
|
416
|
+
> "Built to understand systems, not just use them."
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
kedis_python-0.1.0.dist-info/licenses/LICENSE,sha256=TVakTxcGxIWZsizXhkYNLrWqfX3xh8n6NVvMv92WNOo,1069
|
|
2
|
+
kedis_python-0.1.0.dist-info/METADATA,sha256=T1qESMRUfZTrhFQaOdTwsbxBdJO_Nwz1PwvYkbxn_gg,10014
|
|
3
|
+
kedis_python-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
4
|
+
kedis_python-0.1.0.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
5
|
+
kedis_python-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 V SS Karthik
|
|
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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|