Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

1. Introduction介绍

本也描述了一个针对 Redis的适配器实现This page describes the implementation of an adapter to Redis.
2. Related Documents相关文档
Redis website网站http://redis.io/
Redis Data Types 数据类型 http://redis.io/topics/data-types
3. Terminology术语
Redis -  an open-source, networked, in-memory, key-value data store一个开源的, 网络化, 内存级, 键值数据存储

4. Requirements需求



5. Architectural 架构描述 Description

The adapter本适配器, called GemFireRedisServer称为GemFireRedisServer, understands the Redis protocol but uses Geode underneath as the data store. This allows Redis clients to seamlessly switch to Geode allowing them to obtain the same functionality as before but now on a distributed system. The point of emphasis in this server adapter is to handle all of the data types normally implemented in Redis. This includes 与 Redis 协议兼容, 但是使用 Geode 作为底层的数据存储引擎. 它允许 Redis 客户端无缝地切换到 Geode 上, 允许它们拥有和以前一样相同的功能, 但是是分布式系统. 这个服务器适配器的重点是处理所有的数据类型, 正常在 Redis 服务器上实现的. 这包括 Strings, Lists, Hashes, Sets and , SortedSets and HyperLogLogs. It is important to note that these terms are Redis specific and the server's handling of the data types will be as such. The specifics of each type will be detailed below这些术语都是 Redis 特定的, 服务器的数据类型处理也相同. 每个类型的规范详细描述如下.

5.1 Strings
Redis Strings are just strings of data. These are binary safe implying that they can be used to store any kind of data and have a maximum size of 512MB. All Strings of a cache will be stored in one Geode region.是数据字符串. 它是二进制安全型, 暗示着它们能够保存任意类型的数据, 最大的大小可以是 512MB. 一个 Cache 所有的字符串都可以使用一个Geode region来保存.
已支持的 Redis 字符串命令Supported Redis Strings commands: APPEND, BITCOUNT, BITOP, BITPOS, DECR, DECRBY, GET, GETBIT, GETRANGE, GETSET, INCR, INCRBY, INCRBYFLOAT, MGET, MSET, MSETNX, PSETEX, SET, SETBIT, SETEX, SETNX, STRLEN

5.2 Lists
Redis Lists are generally linked lists of Strings and the operations for the lists are designed around heavy access at the extremities of the list. Lists are stored in Geode by loose indexing and retrieved by querying. It is important to understand the limitations of Lists as they are implemented in this adapter. Geode has no implicit notion of lists and therefore lists are simulated in Regions. For this reason lists become data scalable at the expense of increased latency. As opposed to Sets or Hashes, which have no notion of order, Lists require extra care to ensure order and consistency which takes a heavy toll on performance. For example, the LPUSH command requires to determine the left most index of the list, append to the beginning of the list and update the index of the list. In Redis, lists do not scale and therefore these tasks are trivial but in Geode, even a simple pop/push on a distributed list can introduce multiple network hops. Also, because indexes are mapped to list elements, shifting list elements is unrealistic and LINSERT is not supportedLists 是一个字符串的Linked Lists,  此列表的操作被设计成可以进行达到 List 极限的重度访问. Lists 保存在 Geode 中, 通过松耦合的索引进行保存, 通过Query 进行查询. 理解 List 限制就显得十分重要. Geode 没有 Lists 的内隐观念, 因此 List 是在 Regions 中模拟出来的. 由于这个原因, lists 是数据弹性扩展的, 以增加延时为代价. 与Sets 或 Hashes相反, 它是无序的, Lists 需要格外地小心排序和一致性问题,  在性能上会有很大代价. 举个例子, LPUSH 命令需要确定 List 最左边的索引, 追加到 List 起始处, 同时更新 List 索引. 而在 Redis 中, lists 并不是可扩展的, 因此这些任务是不重要的, 但是在 Geode 中, 在分布式 List 中, 一个简单的 pop/push 操作都能够引入多个网络跳. 因为索引被映射到 List 元素中, 移动 list elements 是不现实的, LINSERT 是不支持的.

Supported Redis Lists commands: LINDEX, LLEN, LPOP, LPUSH, LPUSHX, LRANGE, LREM, LSET, LTRIM, RPOP, RPUSH, RPUSHX
5.3 Hashes
Redis Hashes are String to String maps. This is the most straightforward implementation of the group because a region in a Geode cache is a map so the data can be added without any reconfiguration是字符串到字符串的映射. 是 Group 最直接的实现, 因为一个 Region 就是一个 Map, 因此数据能够被添加进去, 不需要任何重新配置.
Supported Hashes commands: HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HMGET, HMSET, HSCAN, HSETNX, HLEN, HSET, HVALS
5.4 Sets
Redis Sets are unordered sets of Strings. This will be implemented in Geode by holding the set data as keys in the region which will implicitly perform the necessary actions to simulate a 是无序的字符串集合. 它将在 Geode 中实现, 通过保存 set data 作为 keys, 在这个 region 中将执行必要的动作来模拟一个 set.
Supported Sets commands: SADD, SCARD, SDIFF, SDIFFSTORE, SINTER, SINTERSTORE, SISMEMBER, SMEMBERS, SMOVE, SREM, SPOP, SRANDMEMBER, SSCAN, SUNION, SUNIONSTORE
5.5 SortedSets
Redis SortedSets are Sets that are ordered by an explicit 是一个 Sets , 通过一个显式的 "score" . The ordering does not take into account ordering such as lexicographical or hashing functionality but instead uses the score for sorting. Members of the SortedSet are unique but scores are not, therefore sorted sets are member to score mappings in Geode来进行排序. 排序不考虑帐号排序, 例如 lexicographical 或 hashing 功能, 而不是使用"score" 评分. SortedSet 的成员是唯一的, 但是评分不是唯一的, 因此在Geode中,  sorted sets 是成员的评分映射.

Supported SortedSets commands: ZADD, ZCARD, ZCOUNT, ZINCRBY, ZLEXCOUNT, ZRANGE, ZRANGEBYLEX, ZRANGEBYSCORE, ZRANK, ZREM, ZREMRANGEBYLEX, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYSCORE, ZREVRANK, ZSCAN, ZSCORE

...

5.6 HyperLogLogs
Redis HyperLogLog 's are C implementations of the data structure, whereas this implementation is done in Java within Geode. The only difference is that Geode implementation does not utilize the sparse implementation for small cardinalities but is otherwise the same是 C语言实现的数据结构, 而在 Geode 中通过 Java 来实现这个. 唯一的区别是对于小基数, Geode 实现并没有利用稀疏实现.

Supported HyperLogLog commands: PFADD, PFCOUNT, PFMERGE
5.6 Additional Information额外的信息
The GemFire Redis Server will also implement other commands to be a full fledged Redis server. However it is worth noting that while Redis has 160+ commands in their protocol, the GemFireRedisServer will support roughly 110 of them. These will cover all basic commands as well and other practical ones that should not be left out. Redis has many commands for server configurations that are set up differently for Geode as well as scripting that isn't supported.服务器也实现了其他的命令成为了逐渐丰满的 Redis 服务器. 而 Redis 有160+ 个命令, 不用全部实现, GemFireRedisServer 将支持大约110左右. 这些将覆盖所有的基本命令, 而其他的命令也不能忽略. 对于服务器配置, Redis 有许多命令, 在 Geode 中以不同的方式来设置, 脚本不支持.
另外一个值得注意的事情是 keys 是在GemFireRedisServer所支持的key, 与 Redis 不相同. 而所有的值是二进制安全的, 大多数 keys 不是, 它们有自己的 Regions. Region 命令空间通过 Java Strings来定义, 同时 Geode's OQL 引擎不支持所有的字符. 因此一些 keys 可能会导致失败, 如果使用创建一个key (使用非打印字符如 UTFAnother important note about keys is that key support within GemFireRedisServer is not the same as Redis. While all values are binary safe, most keys are not as they will have their own Regions in Geode. The Region namespace is defined by Java Strings, and Geode's OQL engine does not support all characters. Therefore some keys may cause failures with Geode if attempting to create a key using non printable characters such as UTF-8 0x01, 0x02, etc等).
The backing Regions for each key are partitioned by default, but the default region type can be configured by system property. If different keys are desired to have different types of Regions, these Regions must be defined in cache.xml. The other configuration to strongly consider per use case is defining the number of worker threads to use for Redis clients. This is also defined by system property and more information can be found in the GemFireRedisServer javadoc. To put it all together, this adapter can be instantiated through invoking 对于每个 key, 后面的 Regions 默认情况下是分区的, 但是默认的 region 类型能够通过系统属性来配置. 如果不同的 keys 被要求有不同的 Region 类型, 这些Regions 必须被定义在 cache.xml中. 其他配置需要考虑应用场景 定义了 worker 线程的数量为 Redis客户端使用. 它也能够通过系统属性来定义, 更多的信息将在 GemFireRedisServer javadoc中描述. 为了将它们放到一起, 此适配器能够被实例化, 通过独立调用 com.gemstone.gemfire.redis.GemFireRedisServer independently or programmatically, or through GFSH when the property 或者通过 GFSH,  当属性 redis-port is set被设置.
Supported Key commands: DEL, DBSIZE, EXISTS, EXPIRE, EXPIREAT, FLUSHALL, FLUSHDB, KEYS, PERSIST, PEXPIRE, PEXPIREAT, PTTL, SCAN, TTL

...

Supported Transaction commands: DISCARD, EXEC, MULTI

6. Comparison to Redis 进行比较
如下点是 The following points are the main differentiators between Geode/GemFireRedisServer and Redis和 Redis的主要区别
6.1 Concurrency并发性
  • Redis is a single-threaded server. It is not designed to benefit from multiple CPU cores. People are supposed to launch several Redis instances to scale out on several cores if needed. It is not really fair to compare one single Redis instance to a multi-threaded data store.是单线程服务器.它并没有设计成多核CPU的执行服务器. 通常情况下, 大家启动多个 Redis 实例, 如果需要的话. 当然, 一个 Redis单实例和一个多线程数据存储比较是不公平的.
我们已经利用了Geode高并发地特性来使 GemFireRedisServer 获得了高并发的能力. 每个服务器实例将启动 4 * (CPU 核数) 线程来响应客户端请求,  但是它能够通过系统属性来配置,每个连接一个线程被创建, 或者一个特定数量的客户端处理器线程能够被请求We have leveraged the highly concurrent nature of Geode to make GemFireRedisServer concurrent. Each server instance will start 4 * (number of processor cores) threads for processing client requests,  but this can be configured by system property where either one thread per connection can be created or a specific number of client handler threads can be requested.
6.2 Scalability可扩展性
在 Redis中, 一个单数据结构不能扩展, 超过了内存可用大小In Redis, a single data structure cannot scale beyond the memory available on a single box. From: http://redis.io/topics/partitioning
  • The partitioning granuliary is the key, so it is not possible to shard a dataset with a single huge key like a very big 分区粒度是按 key, 因此它不可能分片一个带有大 key 的数据集, 如一个很大的 sorted set.
(In Redis在 Redis中, key is the name of the data structure, so a 是数据结构的名称, 因此一个 hashmap.get() take the form 以 HGET key fieldfield的形式出现)
This limitation is not expected to go away even with the introduction of redis-cluster (which is going to partition the key space i.e. data structure name space). So, with Redis cluster you can scale up the number of data structures, not the data structures themselves.
随着 redis 集群引入, 这些限制也没有随之消失, 按照 key space(数据结构命名空间) 进行分区. 因此, 在 Redis 集群中你能够扩展数据结构的数量, 但是不能够扩展数据结构本身.
在 GemFireRedisServer中, 所有 Redis 数据结构通过PartitionedRegions支持, 因此每个 Redis 数据结构是水平扩展的In GemFireRedisServer, all Redis data structures are backed by PartitionedRegions, so each Redis data structure is horizontally scalable
6.3 Replication复制
In Redis, you can have any number of slaves for a master server. Replication from master to slave is always asynchronous, which may lead to data loss when master crashes before replicating.
When a slave is started, it gets entire data set from the master (even though the salve was persistent). It does, however, support a "Partial resynchronization" from master to slave, if the link between master and slave goes down.
Slaves can be used for scaling read operations.
在 Redis中, 对于一个 master 服务器, 你能够有任意的slaves数量. 从 master 复制到slave 经常是异步的, 在复制之前, 当 master 故障时导致了数据丢失.
当一个slave 启动时, 它从master获得整个数据集 (虽然 salve 是持久化的). 它支持一个 "Partial resynchronization" 从 master 到 slave, 如果在master 和 slave之间 link 断掉后.
Slaves  被用于扩展读操作.
在 Geode中, 你能够配置3个冗余拷贝 (对于分区Regions).  当持久化时, 这些复制节点先从本地磁盘中恢复, 只从主节点上获得delta.  这些拷贝被用于读取操作In Geode, you can have upto 3 redundant copies (for partitioned regions). When persistent, these replicas will first recover from local disk and only get the delta from the primary.  These copies can be used for read operations
6.4 Persistence持久化
Redis supports Snapshots as well as 支持快照, 如 AOF (Append Only)  persistence持久化. AOF is a log of all the operations, which needs to be rebuilt on re-starts. AOF is automatically re-written when it gets too large.是所有操作的日志, 在重启的时候需要重新构建. 当太大的时候, AOF 被自动重写.
Geode 持久化也是 append only, 而 keys 和 values 保存在磁盘上的单独文件中. 在重启时, 只有 key 文件需要读取Geode persistence is also append only, however keys and values are kept in separate files on disk. On restarts, only the key's file needs to be read.
6.5 HA
Redis uses Sentinel for managing HA. User starts a number of sentinel processes by providing them a list of all the masters (the slaves are automatically detected). When a primary crashes, the sentinels gossip and elect a new primary from among the slaves.使用 Sentinel 来管理 HA高可用. 用户开启一些 sentinel processes 通过提供它们在所有的masters列表上 (slaves 被自动检测到). 当主节点出现故障时, sentinels gossip 和 从 slaves 中选举新的主节点成员.
在Geode中, 所有成员都与其他成员连接, 故障切换是自动的. (不需要提供所有的成员列表In Geode, all members are connected to all other members, failover is automatic. (no need to provide a list of all members, which is error prone)
6.6 Network Partition网络分区
With the sentinel approach, there is no real protection from network partition. The documentation mentions that write quorum should be used to guard against writing to a primary on the loosing side, however, since the replication is asynchronous, there will still be some amount of data loss. (This will be fixed with redis-cluster, no more need of sentinels for partition detection)
Geode has network partition detection built in. The loosing side servers will shutdown/fence themselves, so that clients cannot connect to them.
7. Performance and Scalability
到达时, 网络分区其实并没有真正的保护. 写Quorum 将被用于防护写入到主节点, 然而, 复制是异步的, 仍然有一定量的数据丢失. (这将在edis-cluster中修复, 在分区检测上不需要太多的 sentinels 帮助)
Geode 内置了网络分区检测机制. 松耦合的服务器将停机, 因此客户端不能连接到它们.
7. 性能和扩展性
 redis-benchmark 可以对 Redis 进行压力性能测试. 所有的测试都使用'裸金属'方式部署每个节点和客户端These are some performance numbers acquired using the redis-benchmark utility. All these tests are run using separate bare metal machines for each node and client.
Run using no pipelining and 1KB payloads

Redis

SET: 100894.94 requests per second

GET: 103504.02 requests per second

INCR: 99662.14 requests per second

SADD: 99559.35 requests per second 

GemFireRedisServer

SET: 87627.06 requests per second

GET: 102988.52 requests per second

INCR: 92251.61 requests per second

SADD: 92254.50 requests per second

 

Pipelining 16 requests at a time

SET: 109277.91 requests per second

GET: 113583.70 requests per second

INCR: 1061300.75 requests per second

SADD: 989119.69 requests per second

GemFireRedisServer

SET: 109109.55 requests per second

GET: 113523.87 requests per second

INCR: 575023.25 requests per second

SADD: 644678.81 requests per second

Scalability is not within the framework of this specification as Geode handles the scaling independently of this implementation扩展性并不在本规范的讨论范围, Geode 处理扩展性独立于此实现.
8. Testing
TBD
9. Documentation

...