本文最后更新于:2015-04-19 14:00:00
原文:http://www.yaosansi.com/post/redis-on-windows

Redis简介

Redis是一个开源的高级key-value(键-值)缓存与存储,以高性能著称。它也常被称为数据结构服务器,因为其中的键可以存各种数据结构包括字符串、散列、列表、集合、有序集合、位图和hyperloglog。Redis的出现,很大程度补偿了memcached这类KV数据库的不足。不仅可以用于缓存,也可以用于一些场景的存储,在很多情况下是关系数据库很好的补充。它提供了Python,Ruby,Erlang,PHP客户端,使用非常方便。

Redis最近出了3.0版本,最重要的新特性是集群(Redis Cluster),提供Redis功能子集(比如不支持多数据库)的分布式、容错的实现(最多支持1000结点)。

本想折腾一下,不过由于官方并不支持windows,目前(2015.4.10) https://github.com/MSOpenTech/redis 的最新版本仍是 Redis 2.8。

redis windows 2.6 版本高并发时出的BUG

redis windows 2.6版的时候在高并发下的BUG

1
2
3
4
lt too large (fd=11112)
[3512] 12 Apr 11:25:53.063 # Error registering fd event for the new client: Resu
lt too large (fd=11144)
[3512] 12 Apr 11:25:53.095 # Error registering fd event for the new client: Resu

博客园的triStoneL给出了问题的原因和相应的解决办法

问题原因

1
2
3
4
5
6
7
Windows版本的redis和原版的redis的实现是一样的,
重要的是accept的返回值和aeWinAccept所返回的socket句柄逻辑不一样
导致windows版本的redis出现了bug.在Linux中,accept的返回是递增的,
因此linux版本的redis是可以处理eventLoop->setsize个连接的,而在windows上socket返回的句柄会以大概12的步进增长,
所以windows版本的redis就只能处理约eventLoop->setsize/12个连接了.

http://www.cnblogs.com/triStoneL/archive/2013/08/23/3277709.html

解决办法

1
2
3
4
解决方法比较hack,我在aeEventLoop中添加一个fd_map的数组,
用于把fd映射到0到eventLoop->setsize的值,
这样每次从events中存取数据就通过查询fd_map来获取index,
从而达到让redis能处理eventLoop->setsize个连接的效果.

redis windows 2.8 版本配置

port

1
# port 6379

port 1345

requirepass

1
requirepass foobared

注意:由于redis的快速响应,即使设置密码的情况下,仍不建议在对外公开使用,因为暴力破解密码的的可能性将会更大,建议在生产环境使用内部IP和网络访问。

requirepass oaSsihr^VGRAnZMa5=W.UH#bWuue[sHs%tC(d@=lwF5lWJF!6^gT]Yi%@D

maxheap & heapdir

默认的2.8版本直接运行,由于硬盘空间的原因在大部分的电脑的都会出错。

redis-server.exe redis.windows.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
redis-2.8.19>redis-server.exe
[16752] 19 Apr 15:41:03.974 #
The Windows version of Redis allocates a large memory mapped file for sharing
the heap with the forked process used in persistence operations. This file
will be created in the current working directory or the directory specified by
the 'heapdir' directive in the .conf file. Windows is reporting that there is
insufficient disk space available for this file (Windows error 0x70).

You may fix this problem by either reducing the size of the Redis heap with
the --maxheap flag, or by moving the heap file to a local drive with sufficient
space.
Please see the documentation included with the binary distributions for more
details on the --maxheap and --heapdir flags.

Redis can not continue. Exiting.

参照提示,是参数maxheap和heapdir有问题。
打开默认的配置文件:redis.windows.conf

maxheap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# The Linux version of Redis relies on the system call fork() to perform
# point-in-time snapshots of the heap. In addition to the AOF and RDB backup
# mechanism, the master-slave synchronization and clustering features are
# dependent on this behavior of fork(). In order for the Windows version to
# perform like the Linux version we had to simulate this aspect of fork().
# Doing so meant moving the Redis heap into a memory mapped file that can
# be shared with a child process.
#
# *** There must be disk space available for this file in order for Redis
# to launch. *** The default configuration places this file in the local
# appdata directory. If you wish to move this file to another local disk,
# use the heapdir flag as described below.
#
# The maxheap flag controls the maximum size of this memory mapped file,
# as well as the total usable space for the Redis heap. Running Redis
# without either maxheap or maxmemory will result in a memory mapped file
# being created that is equal to the size of physical memory. During
# fork() operations the total page file commit will max out at around:
#
# (size of physical memory) + (2 * size of maxheap)
#
# For instance, on a machine with 8GB of physical RAM, the max page file
# commit with the default maxheap size will be (8)+(2*8) GB , or 24GB. The
# default page file sizing of Windows will allow for this without having
# to reconfigure the system. Larger heap sizes are possible, but the maximum
# page file size will have to be increased accordingly.
#
# The Redis heap must be larger than the value specified by the maxmemory
# flag, as the heap allocator has its own memory requirements and
# fragmentation of the heap is inevitable. If only the maxmemory flag is
# specified, maxheap will be set at 1.5*maxmemory. If the maxheap flag is
# specified along with maxmemory, the maxheap flag will be automatically
# increased if it is smaller than 1.5*maxmemory.
#
# maxheap <bytes>

我们看到,Linux版本的redis依赖于系统调用fork()来执行堆的时间快照,windows版本模拟了fork方法。maxheap标志来控制此内存映射文件的最大大小,redis在未设置 maxheap 或 maxmemory时,内存映射文件的大小等于物理内存的大小,fork()操作的总页面文件最大将是(物理内存大小)+(2maxheap)
我们看到如果设置了maxmemory,那么maxheap=1.5
maxmemory,如果maxheap设置的小于1.5*maxmemory,那么maxheap的值将会自动增加。

根据以上原因,我们不难分析出,当redis所用使用的硬盘空间不足时,便会引发上面的错误。

我们设置maxheap参数为4个G,即占用硬盘空间4G.再次运行,发现一切正常。

maxheap 4024000000

heapdir

那么heapdir是做什么用的呢?

1
2
3
4
5
6
7
8
9
10
# The heap memory mapped file must reside on a local path for heap sharing 
# between processes to work. A UNC path will not suffice here. For maximum
# performance this should be located on the fastest local drive available.
# This value defaults to the local application data folder(e.g.,
# "%USERPROFILE%\AppData\Local"). Since this file can be very large, you
# may wish to place this on a drive other than the one the operating system
# is installed on.
#
# Note that you must specify a directory here, not a file name.
# heapdir <directory path(absolute or relative)>

heapdir实际指定了内存映射文件的目录,默认在%USERPROFILE%\AppData\Local,大部分windows都安装在c盘,而c盘空间有限,结合这两个参数,我们才发现最上面的默认错误原来是我们系统硬盘可用空间不足导致的。

注意:heapdir不支持网络路径,只支持本机路径,但支持相对路径和绝对路径。

这里我们把heapdir指定在redis默认路径指定在根目录下:redis_heapdir

heapdir redis_heapdir/

服务

安装服务

--service-install

安装服务的参数必须为redis-server的第一个参数,默认服务会使用帐户NT AUTHORITY\NetworkService,默认不会启动服务。

实例

redis-server --service-install redis.windows.conf --loglevel verbose

卸载服务

--service-uninstall

实例

redis-server --service-uninstall

启动服务

redis-server --service-start

停止服务

redis-server --service-stop

命名服务

--service-name name

用来使用多实例redis服务。
此参数要放在service-install, service-start, service-stop or service-uninstall的后面。

1
2
3
4
5
6
redis-server --service-install –service-name redisService1 –port 10001
redis-server --service-start –service-name redisService1
redis-server --service-install –service-name redisService2 –port 10002
redis-server --service-start –service-name redisService2
redis-server --service-install –service-name redisService3 –port 10003
redis-server --service-start –service-name redisService3

客户端工具

##参考