A lightweight, in-memory Database implemented in C# that provides a subset of Redis functionality with a similar API.
RedisClone is a .NET implementation of a Redis-like key-value store that supports various data types and operations. It's designed to be used as a local cache or for testing purposes where a full Redis instance isn't required.
RedisClone/
├── src/
│ ├── RedisClone.Core/ # Core interfaces and models
│ ├── RedisClone.Infrastructure/ # Implementation of Redis operations
│ └── RedisClone.API/ # REST API layer
└── tests/
├── RedisClone.UnitTests/ # Unit tests for individual components
└── RedisClone.IntegrationTests/ # Integration tests for the entire system
- Strings: Basic key-value storage with support for bit operations
- Lists: Ordered collections of strings with operations on both ends
- Sets: Unordered collections of unique strings with set operations
- Hashes: Field-value pairs with atomic operations
- Sorted Sets: Ordered collections of unique strings with associated scores
- Pub/Sub: Publish/Subscribe messaging system
- Transactions: Support for atomic operations
SetAsync
: Store a string value with optional expirationGetAsync
: Retrieve a string valueDeleteAsync
: Remove a keyExistsAsync
: Check if a key existsTTLAsync
: Get time to live for a keySetExpirationAsync
: Set expiration time for a keyRemoveExpirationAsync
: Remove expiration time from a keyIncrementAsync
/DecrementAsync
: Atomic counter operationsAppendAsync
: Append to string valueGetRangeAsync
/SetRangeAsync
: String manipulationStrLenAsync
: Get string length- Bit operations:
SetBitAsync
,GetBitAsync
,BitCountAsync
,BitOpAsync
,BitPosAsync
LPushAsync
: Add elements to the head of a listRPushAsync
: Add elements to the tail of a listLPopAsync
: Remove and return the first element of a listRPopAsync
: Remove and return the last element of a listLRangeAsync
: Get a range of elements from a listLIndexAsync
: Get an element from a list by indexLLenAsync
: Get the length of a listLSetAsync
: Set element at indexLRemAsync
: Remove elements from listLTrimAsync
: Trim list to specified range
SAddAsync
: Add members to a setSRemAsync
: Remove members from a setSMembersAsync
: Get all members of a setSIsMemberAsync
: Check if a value is a member of a setSCardAsync
: Get set cardinalitySPopAsync
: Remove and return random memberSRandMemberAsync
: Get random member(s)- Set operations:
SInterStoreAsync
,SUnionStoreAsync
,SDiffStoreAsync
HSetAsync
: Set a hash fieldHGetAsync
: Get a hash fieldHGetAllAsync
: Get all fields and values in a hashHDelAsync
: Delete hash field(s)HExistsAsync
: Check if field existsHIncrementByAsync
: Increment field valueHKeysAsync
: Get all hash fieldsHLenAsync
: Get number of fieldsHValsAsync
: Get all hash values
ZAddAsync
: Add members to a sorted setZRemAsync
: Remove members from a sorted setZScoreAsync
: Get member scoreZIncrementByAsync
: Increment member scoreZCardAsync
: Get set cardinalityZCountAsync
: Count members in score rangeZRangeAsync
/ZRevRangeAsync
: Get range of membersZRangeByScoreAsync
/ZRevRangeByScoreAsync
: Get members by score rangeZRankAsync
/ZRevRankAsync
: Get member rankZRemRangeByRankAsync
/ZRemRangeByScoreAsync
: Remove members by rank/score- Set operations:
ZUnionStoreAsync
,ZInterStoreAsync
PublishAsync
: Publish a message to a channelSubscribeAsync
: Subscribe to a channelUnsubscribeAsync
: Unsubscribe from a channel
BeginTransactionAsync
: Start a transactionCommitTransactionAsync
: Commit the transactionRollbackTransactionAsync
: Rollback the transaction
The project follows a clean architecture pattern with clear separation of concerns:
- Contains interfaces and models
- Defines the contract for Redis operations
- Includes data models like
RedisValue
for storing different types of data - Provides the public API that users interact with
- Implements the core functionality
- Contains specialized operation classes:
KeyOperations
: Basic key-value operationsListOperations
: List-specific operationsSetOperations
: Set-specific operationsHashOperations
: Hash-specific operationsSortedSetOperations
: Sorted set-specific operations
RedisStore
: Main class that coordinates all operations- Uses
ConcurrentDictionary
for thread-safe storage - Implements proper locking mechanisms for atomic operations
- Provides a REST API interface to the Redis functionality
- Handles HTTP requests and responses
- Maps API endpoints to Redis operations
RedisClone is designed to be thread-safe:
- Uses
ConcurrentDictionary
for the main store - Implements proper locking mechanisms for operations
- Handles concurrent access to shared resources
- All operations are atomic where required
- Uses async/await for non-blocking operations
The project includes comprehensive testing:
- Tests individual components in isolation
- Covers all data types and operations
- Tests edge cases and error conditions
- Verifies thread safety
- Tests transaction behavior
- Tests the entire system working together
- Verifies API endpoints
- Tests real-world scenarios
- Ensures proper interaction between components
using RedisClone.Core;
using RedisClone.Infrastructure;
// Create a new Redis store
IRedisStore redis = new RedisStore();
// Store a value
await redis.SetAsync("mykey", "myvalue");
// Retrieve the value
string? value = await redis.GetAsync("mykey");
// Add items to a list
await redis.RPushAsync("mylist", "item1", "item2", "item3");
// Get items from the list
var items = await redis.LRangeAsync("mylist", 0, -1);
// Set hash fields
await redis.HSetAsync("myhash", "field1", "value1");
await redis.HSetAsync("myhash", "field2", "value2");
// Get all hash fields and values
var hash = await redis.HGetAllAsync("myhash");
// Add items to a sorted set
await redis.ZAddAsync("myset", ("member1", 1.0), ("member2", 2.0));
// Get items in score range
var items = await redis.ZRangeByScoreAsync("myset", 0, 2);
// Subscribe to a channel
await redis.SubscribeAsync("mychannel", async (message) => {
Console.WriteLine($"Received: {message}");
});
// Publish a message
await redis.PublishAsync("mychannel", "Hello, Redis!");
- All operations are designed to be efficient
- Uses in-memory storage for fast access
- Implements proper locking to minimize contention
- Supports atomic operations for consistency
- Uses async/await for non-blocking operations
- Data is not persisted (in-memory only)
- No replication support
- Limited subset of Redis commands
- No authentication/authorization
- No clustering support
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.