All Redis string functions have been implemented except SETEX (set with expiry), specifically
APPEND, BITCOUNT, BITOP, BITPOS, DECR, DECRBY, FLUSHDB, GET, GETBIT, GETRANGE, GETSET, INCR, INCRBY, INCRBYFLOAT, MGET, MSET, MSETNX, PING, SET, SETBIT, SETNX, SETRANGE, STRLEN
Fredis.net uses the same RESP protocol used by Redis, so tools such as redis-cli and redis-benchmark will work with Fredis.net.
Redis features not supported
- multiple db’s indexed by number
- master/slave instances
Fredis.net uses F# async workflows, and therefore IO Completion ports and the .Net threadpool, to convert RESP messages received from clients into Redis commands. Commands from different threadpool threads are multiplexed down to a single command executing thread by sending them to an F# mailbox. Replies are sent back to the client using only async socket calls. This is all vanilla F#, I did not need to go to extreme lengths to coax performance out of Fredis.net.
Client input can be received in either a partially or fully async manner. ‘Partially’ in the sense that Fredis.net waits for new input on a Stream.ReadAsync call (so no thread blocking), subsequent reads are synchronous until the current RESP message has been read. Partially async input message processing is more performant than fully async. This may be due to the multiple nested callbacks associated with many fine grained async actions.
Client input is encoded in the Redis RESP protocol, some elements of which are length prefixed, others are delimited by CRLF. Reading delimited RESP from streams is done one byte at a time while searching for the delimiter, which could be inefficient, so a BufferedStream is used to wrap the sockets network stream.
Fredis.net is written in F# 4.0, and where possible in a functional style e.g. with algebraic data types instead of classes.
Fredis.net is a vehicle for scalability experiments (and not a replacement for Redis), please feel free to point out any mistakes or things which could be improved.