Redis on Windows (redis在window上面的使用说明)
MSOpenTech’s Redis on Windows
We strive to have a stable, functionally equivalent and comparably performing version of Redis on Windows. We have achieved performance nearly identical to the POSIX version running head-to-head on identical hardware across the network. Aside from feature differences that help Redis take advantage of the Windows infrastructure, our version of Redis should work in most situations with the identical setup and configuration that one would use on a POSIX operating system.
MSOpenTech版本的redis运行在windows上
我们力求有一个稳定的redis在windows上面功能相当于发展版,我们已经实现了在POSIX上面运行在相同硬件的网络上,除了功能上帮助redis利用windows的设施,我们的版本的redis应该工作在大多数具有相同的安装和配置,将在posix操作系统上使用。
How is Redis on Windows implemented?
Redis is a C code base that compiles under Visual Studio. Most of the code compiles with only minor changes to the code due to syntactical differences between compilers and low level API differences on Windows. There are a few areas where there are significant differences in how efficient Windows programs operate relative to POSIX programs. We have encapsulated most these differences in a platform specific library. The areas where there are significant differences are:
- Networking APIs
- POSIX File Descriptors
- POSIX fork()
- Logging
- Windows Services API
Reids怎么在windows执行的?
Redis是一个C语言基础,可以在Visual Studio编译,大部分编译成功仅仅是轻微的修改代码,由于编译器和Windows API之间的语法差异,怎么有效的使用windows程序相当于运作posix程序有显著的差异有几个方面.我们已经封装了大部分在平台的库之间的差异,存在下面以下不同的特点:
网络API
POSIX文件描述
POSIX叉
日志
Windows 服务 API
Networking Differences
The Windows networking stack is split between user mode code and kernel mode code. Transitions between user and kernel mode are expensive operations. The POSIX networking APIs on Windows utilize a programming model that incurs significant performance loss due to the kernel/user mode transitions. Efficient Windows networking code instead uses the IO Completion Port model to reduce the impact of this behavior. The APIs used and the programming model for IO Completion is different enough that we were forced to implement a new networking layer in in Redis.
网络差异
Windows网络堆栈被分割在用户模式代码和内核模式之间代码。用户和内核模式之间的转换是昂贵的操作。POSIX 网络API利用windows设计来减少性能损失,有效的window网络编写可以被使用IO的端口模型来减少这些行为的影响,这个API使用和编程模型IO的完成完全不同的,我们被迫创建一个新的网络层在redis里面。
File Descriptors
In a POSIX operating system all data sources (files, pipes, sockets, mail slots, etc.) are referenced in code with a handle called a file descriptor. These are low value integers that increment by one with each successive file descriptor created in a given program. All POSIX APIs that work with file descriptors will function without the programmer having to know what kind of data source a file descriptor represents. On Windows generally each kind of data source has a separate kind of HANDLE. APIs that work with one HANDLE type will not work with another kind of HANDLE. In order to make Redis operate with its assumptions about file descriptor values and data source agnosticism, we implemented a Redis File Descriptor API layer.
文件描述:
在POSIX运转系统的所有数据根源(文件,管道,接口,邮件槽等)是引用编码在句柄命令称为一个文件的描述,i这些都是由一个在给定程序中创建的每一个连续的文件描述符所增加的低值整数。在给定程序中创建的文件描述符。所有的POSIX API,使用文件描述符将无需程序员知道什么样的数据源文件描述符代表功能。。
在Windows上通常的各种数据源中有一个单独的一种处理, API对一个句柄类型进行操作会不影响其他的句柄,为了可以使用redis操作假设存在的文件描述的值和数据源不能的操作。我们实现redis文件描述的API层。
fork()
The POSIX version of Redis uses the fork() API. There is no equivalent in Windows, and it is an exceedingly difficult API to completely simulate. For most of the uses of fork() we have used Windows specific programming idioms to bypass the need to use a fork()-like API. The one case where we could not do so was with the point-in-time heap snapshot behavior that the Redis persistence model is based on. We tried several different approaches to work around the need for a fork()-like API, but always ran into significant performance penalties and stability issues.
Our current approach is to simulate the point-in-time snapshot behavior aspect of fork() without doing a complete simulation of fork(). We do this with a memory mapped file that contains the Redis heap. When a fork() operation is required we do the following:
- Mark every page in the memory mapped file with the Copy on Write page protection
- Start a child process and pass it the handle to the memory mapped file
- Signal the child to start the AOF or RDB persistence process on the memory shared via the memory mapped file
- Wait (asynchronously) for the child process to finish
- Map the changes in the Redis heap that occurred during the fork() operation back into the memory mapped file.
The upside with this implementation is that our performance and stability is now on par with the POSIX version of Redis. The down side is that we have a runtime disk space requirement for Redis equal to the size of the Redis memory mapped heap. The disk space requirement defaults to:
- The size specified by the –maxheap flag if present, otherwise
- 50% more than the --maxmemory setting if present, otherwise
- The size of physical RAM
We also have a runtime page file commit requirement that varies depending on the amount data in the Redis heap during the quasi-fork operation. The maximum for this is about 3 times the size of the memory mapped file. This is usually not a problem because the default configuration of Windows allows the page file to grow to 3.5 times the size of physical memory. There are scenarios where 3rd party programs also compete for system swap space at runtime.
分叉
POSIX的Redis版本是用分叉的API,这个在windows系统,没有相应的,它非常困难用API来完全模拟。对大多数使用叉的用途,我们在使用window特定的编程管用方法来绕过需要使用的叉相当于一个API。一般情况下,Redis的持久化永久模型的基础上,我们不能这么做期间堆的快照行为 。我努力的尝试不同的来解决需要的分叉,像API一样,但是总是出现在重要的性能损失和稳定性问题。
我们目前的做法是没有做叉的完整模拟()来模拟fork()的点于点即时快照行为方面,我们这样做是一个内存映射文件,其中包含Redis的堆。当需要fork()的操作,我们做到以下几点:
让内存中的数据中的每一页的复制写入到到保护中。
开启一个子线程并且让其通过句柄在传递给内存映射文件。
子线程释放信号,通过内存镜像文件启动AOF或RDB持久进程对内容共享
等待(异步)子线程操作完成。
地图的变化是在叉子()操作过程中发生回存贮器映射文件Redis的堆之时。
这种实现的好处是,我们现在的性能和稳定性跟posix版本的redis同一水平,我们有一个运行时的Redis要求的磁盘空间等于Redis的内存映射堆的大小,这个磁盘空间默认为:
如果存在着指定大小,则有最大堆来标记,是否则不用。
如果超过50%的内存则有最大内存设置,否则则不用。
这个大小是物理内存。
我们准确的叉的操作过程取决于redis堆的数量量的运行时页文件提交的请求。最大值是在内存映射地址的三倍。这个通常没有问题因为首要的配置在windows上运行页面文件增加到物理内存的3.5倍,有场景的第三方程序也运行时争夺系统交换空间。
Logging
In addition to file based logging, the POSIX version of Redis supports logging via the syslog facility. The equivalent in Windows is the Event Log. With the recent addition of the Windows Service code we have added support for logging to the Event Log. We have mapped the –syslogxxxx flags for this purpose.
日志
在增加日志文件,redis支持日志在系统中的上面的系统接口版本,这个相当于系统中的事件日志。
在最新的windows服务中我们增加了事件日志。我们含有系统日志目录在这个版本、
Windows Service
In version 2.8.9 we are adding support to make Redis operate as a service. See the RedisService.docx file included with the GitHub binary distribution for a description of the service commands available.
windows服务
在2.8.9版本我们添加了让redis作为服务一样运转,请参阅随附GitHub的二进制分发可用的服务命令的说明,RedisService.docx文件。
Redis on Windows Best Practices
Binary Distributions
The GitHub repository should be considered a work in progress until we release the NuGet and Chocolatey packages and tag the repository at that released version.
For instance, the Windows Service feature has taken many iterations with community input to get right. The initial Windows service code was checked in on April 3. Since that time we have added the following to the service based on community input:
- Preshutdown notification in order to clean up the memory mapped file consistently.
- Code to identify and clean up orphaned memory mapped files left behind when a machine running Redis as a service crashes or loses power.
- Self elevation of the Redis executable so that service commands would work from a non-elevated command prompt.
- Service naming so that multiple instances of the Redis service could be installed on one machine.
- Automatically adjusting folder permissions so that when Redis is run under the NETWORK SERVICE account it could modify the files in the installation directory.
- Moved all of the pre-main() error reporting code (service and quasi-fork code) that could write errors to stdout to use the Redis logging code. This allows service initialization errors to reach the Event Log. This required intercepting all of the command line and conf file arguments before main() in order to properly initialize the logging engine. There were several fixes related to the intricacies of how to interpret the arguments passed to Redis.
The final service code has been released as of June 25 in the 2.8.9 Redis-64 packages.
Redis在window上的最佳实践
二进制分发
GitHub库应该考虑一项正在进行中的工作,直到我们释放NuGet和巧克力色包和标记库发布版本。比如说,window服务功能是一些重复社区操作来获取权利。
最初的window服务选择在4月3号以来,我们我们添加了以下基于社区输入服务
预关闭通知为了清除内存映射文件一致。
回收孤立的内存文件数据当redis作为服务器崩溃或者是异常关机的时候。
服务器名称可以使用多个实例安装在同一台机器上面。
当redis在网络服务器下运行,可以修改文件,自动调整文件夹权限。
将所有的错误报告代码为前提(服务和准叉代码),使用Redis的日志代码讲错误写入到文件中。这使得服务初始化错误到达事件日志。这就要求拦截所有之前的主命令行和配置文件的参数,以便正确初始化记录的引擎。有涉及到如何理解传递给Redis的参数的复杂一些修正。最终的服务代码已经发布了截至6月25日,在2.8.9 Redis的-64封装。
Heap Sizing
Native heaps are prone to fragmentation. If we are not able to allocate more heap space due to fragmentation Redis will flag the problem and exit. Unlike the POSIX version of Redis, our heap size is constrained by both by disk space and by swap file space. It is important to consider the how much data you are expecting to put into Redis, and how much fragmentation you are likely to see in the Redis heap. With very high levels of fragmentation the 50% overhead that –maxmemory imposes may not be enough to prevent running out of heap space. In this case, the use of –maxheap will supersede the –maxmemory default heap setting.
堆的大小调整
本地堆容易产生碎片,如果我们不能够分配好大量的堆空间给redis会导致程序问题并退出。不同于POSIX版本的Redis,我们堆的大小受限于磁盘空间和文件空间交换,最重要是考虑怎么把多大的数据存入在redis里,你可能会看到多少redis堆的碎片。超过50%的碎片会导致最大内存都不足与运转堆空间,在这种情况下,使用最大堆将取代最大内存默认堆设置。
Installation and Maintenance
Since Redis uses system swap space, the most stable configurations will only have Redis running on essentially a virgin operating system install.
Redis is xcopy deployable. There should be no problem upgrading versions by simply copying new binaries over old ones (assuming they are not currently in use).
安装于维护
当redis使用windows服务,运行redis在系统的网络服务上仅仅需要在第一次安装的时候配置就可以了。
Redis可以进行复制性部署,简单的复制新的二进制文件来覆盖旧的(假设它们当前未使用)从而升级版本是没有问题的。
Service Account
When using Redis as a Windows service, the default installation configures Redis to run under the system’s NETWORK SERVICE account. There are some environments where another account must be used (perhaps a domain service account). Configuration of this account needs to be done manually at this point with the service control manager. If this is done, it is also important to give read/write/create permission to the folder that the Redis executable is in to this user identity.
服务帐号
当redis作为windows服务使用的时候,,默认安装Redis的配置到系统的网络服务帐户下运行。
还有一些环境中必须采用其他帐户(可能是一个域服务帐户),此帐户的配置需要在服务控制管理器手动允许完成,如果这样,那么这个操作可以允许对文件夹进行读取/写入/创建操作在redis确定身份认证。
浙公网安备 33010602011771号