1.redis简介

     REmote DIctionary Server(Redis)是一个几乎key-value键值对的持久化数据库存储系统。redis和大名鼎鼎的Memcached缓存服务很像,但是redis支持的数据存储类型更丰富,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)等。

     这些数据类型都支持push/pop、add/remove及取交集、并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached缓存服务一样,为了保证效率,数据都是缓存在内存中提供服务。和memcached不同的是,redis持久化服务还会周期的把更新的数据写入到磁盘以及把修改的操作记录追加到文件里记录下来,比memcached更有优势的是,redis还支持master-slave(主从)同步,这点很类似关系型数据库MySQL。

     redis的出现,再一定程度上弥补了memcached这类key-value内存缓存的不足。在部分场合可以对关系型数据库起到很好的补充作用,redis提供了Python、Ruby、Erlang、PHP客户端,使用很方便。redis官方文档如下:

     http://www.redis.io/documentation

     http://www.redis.cn/

  2 Redis 的特点

1)性能很高:redis能支持超过100K+每秒的读写频率

2)丰富的数据类型:redis支持二进制的Strings、Lists、Hashes、Sets及Ordered Sets数据类型操作

3)原子:Redis的所有操作都是原子性的,同时redis还支持对几个操作合并后的原子执行

4)丰富的特性:Redis还支持publish/subscribe,通知,key过期等特性

5)redis支持异机主从复制

6)可以持久化存储数据,与memcached不同

  3 Redis的数据类型

Redis最为常见的数据类型主要为有以下五种:

   1)String

   2)Hash

   3)List

   4)Set

   5)Sorted set

4 redis的应用场景

   传统的MySQL + Memcached 的网站架构遇到的问题:

    MySQL数据库实际上适合进行海量数据存储的,加上通过Memcached将热点数据存放到内存cache里,达到加速数据访问的目的,绝大部分公司曾经使用过这样的架构,但随着业务数据的量的不断增加,和访问量的持续增长,很多问题就会暴露出来:

    1)需要不断的对MySQL进行拆库拆表,Memcached也需要不断跟着扩容,扩容和维护工作占据大量开发运维时间

    2)memcached与MySQL数据库一直性问题是个老大难。

    3)memcached数据命中率低或者down机,会导致大量访问直接穿透到数据库,导致MySQL无法支撑访问

    4)跨机房cache同步一致性问题

redis 的最佳应用场景:

 

1)Redis 最佳使用场景是全部数据in-memory

2)Redis更多场景是作为Memcached的替代品来使用

3)当需要除key/value之外的更多数据类型支持时,使用Redis更合适。

4)当存储的数据不能被剔除时,使用Redis更合适。

5) 需要负载均衡的场景(主从同步)

更多Redis作者谈Redis应用场景:http://blog.nosqlfan.com/html/2235.html

业务场景:

1、使用Redis bitmap进行活跃用户统计

 http://blog.nosqlfan.com/html/3501.html

   

这里对Redis数据库做个小结

1)提高了DB的可扩展性,只需要将新加的数据放到新加的服务器上就开了

2)提高了DB的可用性,只影响到需要访问的shard服务器上的数据用户

3)提高了DB的可维护性,对系统的升级和配置可以按shard一个个来搞,对服务产生的影响较小

4)小的数据库的查询压力小,查询更快,性能更好

使用过程中的一些经验与教训,做个小结:

1)要进行Master-slave配置,出现服务器故障时可以直接切换。

2)在master侧禁用数据持久化,只需要在slave上配置数据持久化

3)物理内存+虚拟内存不足,这个时候dump一直死着,时间久了机器挂掉。这个情况就是灾难

4)当Redis物理内存使用超过内存总量的3/5时就会开始比较危险了,就开始做swap,内存碎片大

5)当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间

6)redis与DB同步写的问题,先写DB,然后再写redis,因为写内存基本上没问题

redis部署环境搭建:

Master:192.168.1.7 Centos6.4

Slave:192.168.1.8 Centos6.4

开始安装redis服务

  在redis的官网(http://www.redis.io)下载最新稳定版redis

操作命令:

mkdir -p /home/oldboy/tools

cd /home/oldboy/tools

wget -q http://download.redis.io/releases/redis-2.8.9.tar.gz

ls redis-2.8.9.tar.gz

tar xf redis-2.8.9.tar.gz

cd redis-2.8.9

make MALLOC=jemalloc

make PREFIX=/application/redis-2.8.9 install

ln -s /application/redis-2.8.9/ /application/redis

LANG=EN

echo 'vm.overcommit_memory = 1' >>/etc/sysctl.conf 

sysctl -p

echo "export PATH=/application/redis/bin:$PATH" >>/etc/profile

source /etc/profile

mkdir -p /application/redis/conf

cp redis.conf /application/redis/conf/

redis-server  /application/redis/conf/redis.conf &


[root@LNMP redis-2.8.9]# tree /application/redis/bin/
/application/redis/bin/
|-- redis-benchmark
|-- redis-check-aof
|-- redis-check-dump
|-- redis-cli
`-- redis-server

0 directories, 5 files
[root@LNMP redis-2.8.9]# 

命令执行完成之后,会在/application/redis/bin下生成5个可执行文件,分别是:

redis-benchmark  redis-check-aof  redis-check-dump  redis-cli  redis-server

它们的作用如下:

redis-server,Redis服务器的daemon启动程序

redis-cli:Redis命令行操作工具,,当然,你也可以通过Telnet根据其纯文本协议来操作

redis-benchmark:Redis性能测试工具,测试Redis在你系统及你的配置下的读写性能

redis-check-aof:更新日志检查

redis-check-dump:用于本地数据库检查

配置并启动redis服务

a、配置环境变量

操作命令:

[root@LNMP redis-2.8.9]# echo 'PATH=/application/redis/bin:$PATH' >>/etc/profile
[root@LNMP redis-2.8.9]# tail -1 /etc/profile
PATH=/application/redis/bin:$PATH
[root@LNMP redis-2.8.9]# source /etc/profile
[root@LNMP redis-2.8.9]# 

b、查看帮助

[root@LNMP redis-2.8.9]# redis-server  --help
Usage: ./redis-server [/path/to/redis.conf] [options]
       ./redis-server - (read config from stdin)
       ./redis-server -v or --version
       ./redis-server -h or --help
       ./redis-server --test-memory <megabytes>

Examples:
       ./redis-server (run the server with default conf)
       ./redis-server /etc/redis/6379.conf
       ./redis-server --port 7777
       ./redis-server --port 7777 --slaveof 127.0.0.1 8888
       ./redis-server /etc/myredis.conf --loglevel verbose

Sentinel mode:
       ./redis-server /etc/sentinel.conf --sentinel

创建配置文件存放目录并将配置文件拷贝到其中:

[root@LNMP redis-2.8.9]# mkdir -p /application/redis/conf
[root@LNMP redis-2.8.9]# cp redis.conf  /application/redis/conf/

启动redis服务:

[root@LNMP redis-2.8.9]# redis-server  /application/redis/conf/redis.conf &

[3017] 11 Jul 23:55:29.906 # Server started, Redis version 2.8.9
[3017] 11 Jul 23:55:29.906 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
[3017] 11 Jul 23:55:29.906 * The server is now ready to accept connections on port 6379

[root@LNMP redis-2.8.9]# 

出现以上警告,将“vm.overcommit_memory = 1”添加到/etc/sysctl.conf中或者在命令行执行

这里直接添加到/etc/sysctl.conf


[root@LNMP redis-2.8.9]# pkill redis-server

[root@LNMP redis-2.8.9]# echo 'vm.overcommit_memory = 1' >>/etc/sysctl.conf
[root@LNMP redis-2.8.9]# tail -1 /etc/sysctl.conf
vm.overcommit_memory = 1
[root@LNMP redis-2.8.9]#

运行sysctl -p使其生效:

[root@LNMP redis-2.8.9]# sysctl -p

再次启动redis

[root@LNMP redis-2.8.9]# redis-server  /application/redis/conf/redis.conf &
[1] 3040
[root@LNMP redis-2.8.9]#                 _._                                                 
           _.-``__ ''-._                                            
      _.-``    `.  `_.  ''-._           Redis 2.8.9 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
(    '      ,       .-`  | `,    )     Running in stand alone mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
|    `-._   `._    /     _.-'    |     PID: 3040
  `-._    `-._  `-./  _.-'    _.-'                                  
|`-._`-._    `-.__.-'    _.-'_.-'|                                 
|    `-._`-._        _.-'_.-'    |           http://redis.io       
  `-._    `-._`-.__.-'_.-'    _.-'                                  
|`-._`-._    `-.__.-'    _.-'_.-'|                                 
|    `-._`-._        _.-'_.-'    |                                 
  `-._    `-._`-.__.-'_.-'    _.-'                                  
      `-._    `-.__.-'    _.-'                                      
          `-._        _.-'                                          
              `-.__.-'                                              

[3040] 12 Jul 00:01:52.043 # Server started, Redis version 2.8.9
[3040] 12 Jul 00:01:52.043 * DB loaded from disk: 0.000 seconds
[3040] 12 Jul 00:01:52.043 * The server is now ready to accept connections on port 6379

[root@LNMP redis-2.8.9]#

从以上启动信息可以看出redis启动监听端口为6379,pid为3040

进一步验证端口和进程:

[root@LNMP redis-2.8.9]# netstat -lnpt|grep redis-server
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      3040/redis-server *
tcp        0      0 :::6379                     :::*                        LISTEN      3040/redis-server *
[root@LNMP redis-2.8.9]#

wKioL1cHo3CjwDBxAAAjwEgKwWI448.png 

redis服务关闭方法:

redis-cli shutdown

[root@LNMP redis-2.8.9]# redis-cli  shutdown
[3040] 12 Jul 00:06:46.122 # User requested shutdown...
[3040] 12 Jul 00:06:46.122 * Saving the final RDB snapshot before exiting.
[3040] 12 Jul 00:06:46.131 * DB saved on disk
[3040] 12 Jul 00:06:46.132 # Redis is now ready to exit, bye bye...
[1]+  Done                    redis-server /application/redis/conf/redis.conf
[root@LNMP redis-2.8.9]# ps -ef|grep redis-server
root      3055  1174  0 00:06 pts/0    00:00:00 grep redis-server
[root@LNMP redis-2.8.9]# 

或者

[root@LNMP redis-2.8.9]# netstat -lnpt|grep redis-server
[root@LNMP redis-2.8.9]# 

redis命令行帮助:

[root@LNMP redis-2.8.9]# redis-cli --help
redis-cli 2.8.9

Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
  -h <hostname>      Server hostname (default: 127.0.0.1).
  -p <port>          Server port (default: 6379).
  -s <socket>        Server socket (overrides hostname and port).
  -a <password>      Password to use when connecting to the server.
  -r <repeat>        Execute specified command N times.
  -i <interval>      When -r is used, waits <interval> seconds per command.
                     It is possible to specify sub-second times like -i 0.1.
  -n <db>            Database number.
  -x                 Read last argument from STDIN.
  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \n).
  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).
  --raw              Use raw formatting for replies (default when STDOUT is
                     not a tty).
  --csv              Output in CSV format.
  --latency          Enter a special mode continuously sampling latency.
  --latency-history  Like --latency but tracking latency changes over time.
                     Default time interval is 15 sec. Change it using -i.
  --slave            Simulate a slave showing commands received from the master.
  --rdb <filename>   Transfer an RDB dump from remote server to local file.
  --pipe             Transfer raw Redis protocol from stdin to server.
  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.
                     no reply is received within <n> seconds.
                     Default timeout: 30. Use 0 to wait forever.
  --bigkeys          Sample Redis keys looking for big keys.
  --scan             List all keys using the SCAN command.
  --pattern <pat>    Useful with --scan to specify a SCAN pattern.
  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.
                     The test will run for the specified amount of seconds.
  --eval <file>      Send an EVAL command using the Lua script at <file>.
  --help             Output this help and exit.
  --version          Output version and exit.

Examples:
  cat /etc/passwd | redis-cli -x set mypasswd
  redis-cli get mypasswd
  redis-cli -r 100 lpush mylist x
  redis-cli -r 100 -i 1 info | grep used_memory_human:
  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
  redis-cli --scan --pattern '*:12345*'

  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)

When no command is given, redis-cli starts in interactive mode.
Type "help" in interactive mode for information on available commands.

[root@LNMP redis-2.8.9]# 

redis-cli命令行操作:

[root@LNMP redis-2.8.9]# redis-cli
127.0.0.1:6379> 

127.0.0.1:6379> help
redis-cli 2.8.9
Type: "help @<group>" to get a list of commands in <group>
      "help <command>" for help on <command>
      "help <tab>" to get a list of possible help topics
      "quit" to exit
127.0.0.1:6379>

127.0.0.1:6379> help set

  SET key value [EX seconds] [PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

127.0.0.1:6379>

设置值,获取值:

提示:前面是键(key),后面是值(value)

127.0.0.1:6379> set no002 oldboy
OK
127.0.0.1:6379> get no002
"oldboy"

127.0.0.1:6379> 

或者直接命令行(非交互模式):

[root@LNMP redis-2.8.9]# redis-cli -h 192.168.1.12 -p 6379 set no001 zhangsan
OK

[root@LNMP redis-2.8.9]# redis-cli -h 192.168.1.12 -p 6379 get no001
"zhangsan"
[root@LNMP redis-2.8.9]#

删除数据(可以省略"-h 192.168.1.12 -p 6379"部分,默认):

[root@LNMP redis-2.8.9]# redis-cli del no001                        
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli get no001 
(nil)

通过Telnet命令连接redis

[root@LNMP redis-2.8.9]# telnet 127.0.0.1 6379
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set 003 test
+OK
get 003
$4
test
set 005 linux
+OK
get 005
$5
linux

^]

quit
+OK
Connection closed by foreign host.
[root@LNMP redis-2.8.9]# 

字符串类型

这是最简单的Redis类型。如果你值用这种类型,Redis就是一个可以持久化的memcached服务器(注:memcached的数据仅保存在内存中,服务器重启后,数据将丢失)

我们来测试一下字符串类型:

[root@LNMP redis-2.8.9]# redis-cli set mykey "my binary safe value"
OK
[root@LNMP redis-2.8.9]# redis-cli get mykey
"my binary safe value"
[root@LNMP redis-2.8.9]#

"my binary safe value"这正如你所见到的,通常用SET和GET来设置和获取字符串值。

值可以是任何类型的字符串(包括二进制数据),例如你可以在一个键下保存几个jpeg图片,值的长度不能超过1GB。

 虽然字符串是Redis的基本类型,但你仍然能通过它完成一些有趣的操作。例如:


原子递增:

[root@LNMP redis-2.8.9]# redis-cli set counter 100
OK
[root@LNMP redis-2.8.9]# redis-cli  incr counter
(integer) 101
[root@LNMP redis-2.8.9]# redis-cli  incr counter
(integer) 102
[root@LNMP redis-2.8.9]# redis-cli  incrby counter 10 
(integer) 112
[root@LNMP redis-2.8.9]# 

    INCR命令将字符串值解析成×××,将其加1,最后将结果保存为新的字符串值,类似的命令有INCRBY,DECR and DECRBY。实际上他们在内部就是一个命令,只是看上去有点不同。

    INCR是原子操作意味什么呢?就是说即使多个客户端对同一个key发出INCR命令,也绝不会导致竞争的情况。例如如下情况永远不可能发生:【客户端1和客户端2同时读出“10”,他们俩都是对其加到11,然后将新值设置为11】,最终的值一定是12,read-increment-set操作完成时,其他客户端不会在同一时间执行任何命令。

   对字符串,另一个的令人感兴趣的操作是GET SET命令,正如其名:它为key设置新值并且返回原值,这有什么用处呢?例如:你的系统每当所有新用户对访问时就用INCR命令操作一个Redis key。你希望每小时对这个信息收集一次,你就可以GET SET这个key并给其赋值0并读取原值。

列表类型:

    要说清楚列表数据类型,最好先讲一点儿理论背景,在信息技术界List这个词常常被使用不当。例如"Python Lists"就是名不副实(Linked Lists),但他们实际上是数组(同样的数据类型在Ruby中叫数组)

   一般意义上讲,列表就是有序元素的序列:10,20,1,2,3就是一个列表,但用数组实现的List和用Linked List实现list,在属性方面大不同。

  Redis lists给予Linked Lists实现。这意味着即使在一个list中有百万个元素,在头部或者尾部添加一个元素操作,其时间复杂度也不是常数级别的,用LPUSH命令在十个元素的list头部添加新元素,和在千万元素list头部添加新元素的速度相同。

   那么,坏消息是什么?在数组实现的list中利用索引访问元素的速度极快,而同样的操作在linked list实现的list上没有那么快。

     Redis Lists are implemented with linked list because for a databases system it is crucial to be able to add elements to a very long list in a very fast way,Another strong advantage is,as you'll see in a moment,that Redis Lists can be taken at constant length in constant time。

   Redis Lists 用linked list 实现的原因是:对于数据来说,之至关重要的特性是:能非常快的在很大的列表上添加元素。另一个重要元素是,正如你将要看到的:Redis lists能在常数时间取得常数长度。

 Redis lists 入门

LPUSH命令可向list的左边(头部)添加一个新元素,而RPUSH命令可向list的右边(尾部)添加一个新元素。最后LRANGE命令可从list中取出一定范围的元素

[root@LNMP redis-2.8.9]# redis-cli rpush messages "Hello how are you?"
(integer) 5
[root@LNMP redis-2.8.9]# redis-cli rpush messages "Fine thanks,I'm having fun with Redis"(integer) 6
[root@LNMP redis-2.8.9]# redis-cli rpush messages "I should look into this NOSQL.thing ASAP"
(integer) 7
[root@LNMP redis-2.8.9]# redis-cli  lrange messages 0 2
1) "Hello how are you?"
2) "Hello how are you?"
3) "Fine thanks,I'm having fun with Redis"
[root@LNMP redis-2.8.9]# redis-cli  lrange messages -2 0
(empty list or set)
[root@LNMP redis-2.8.9]# redis-cli  lrange messages -2 -1
1) "Fine thanks,I'm having fun with Redis"
2) "I should look into this NOSQL.thing ASAP"
[root@LNMP redis-2.8.9]# redis-cli  lrange messages -2 0
(empty list or set)
[root@LNMP redis-2.8.9]# 

注意:LRANGE带有两个索引,一定范围的第一个和最后一个元素。这两个元素都可以为负来告知Redis从尾部开始计数,因此-1表示最后表示一个元素,-2表示list中的倒数第二个元素,以此类推。

Redis 集合是未排序的集合,其他元素是二进制安全的字符串。SADD命令可以向集合添加一个新元素。和sets相关的操作也有许多,iru检查某个元素是否存在,以及实现交集,并集,差集等等。一例胜于千言:

[root@LNMP redis-2.8.9]# redis-cli sadd myset a
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli sadd myset b
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli  sadd myset c
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli  smembers myset
1) "b"
2) "c"
3) "a"
[root@LNMP redis-2.8.9]# 

我向集合中添加了三个元素,并让Redis返回所有元素。如你所见它们是无效的。现在让我们检查某个元素是否存在:

[root@LNMP redis-2.8.9]# redis-cli sismember myset a
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli sismember myset d
(integer) 0
[root@LNMP redis-2.8.9]#

"a"是这个集合的成员,而“d”不是。集合特别适合表现对象之间的关系。例如用Redis集合可以很容易实现标签功能。

     下面是一个简单的方案:对每个想加标签的对象,用一个标签ID集合与之关联,并且对每个已有的标签,一组对象ID与之关联。

    例如假设我们的新闻ID1000被加了三个标签tag 1,2,5和77,就可以设置下面两个集合:

[root@LNMP redis-2.8.9]# redis-cli  sadd names:1000:tags 1
(integer) 0
[root@LNMP redis-2.8.9]# redis-cli  sadd names:1000:tags 2
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli  sadd names:1000:tags 5
(integer) 1
[root@LNMP redis-2.8.9]#

[root@LNMP redis-2.8.9]# redis-cli  sadd names:1000:tags 77
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli  sadd tag:1:objects 1000
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli  sadd tag:2:objects 1000
(integer) 1
[root@LNMP redis-2.8.9]# redis-cli  sadd tag:5:objects 1000
(integer) 1
[root@LNMP redis-2.8.9]#

要获取一个对象的所有标签,如此简单:

 

 6 为PHP安装客户端扩展

获取源码包

wget https://github.com/nicolasff/phpredis/archive/master.zip

安装:

unzip phpredis-master.zip

cd phpredis-master

/application/php/bin/phpize

./configure --with-php-config=/application/php/bin/php-config

make

make install

修改php.ini设置,重启php

7 解读redis默认配置文件2.8.9

修改php配置文件php.ini如下两项:

[root@LNMP extra]# cat /application/php/lib/php.ini 

extension = redis.so

extension_dir = "/application/php5.3.27/lib/php/extensions/no-debug-non-zts-20090626/"

然后通过phpinfo函数检查php程序是否加载了redis模块,如下图:

wKioL1cHo6CAxoduAABZKMicKAo900.png

 

如上图所示,php加载redis.so模块成功

redis主从复制:

在另外一台机器上安装redis(安装方法同上),然后修改配置文件:redis.conf

[root@LAMP redis-2.8.9]# vim /application/redis/conf/redis.conf

--------------------省略部分-------------------

# so for example it is possible to configure the slave to save the DB with a
# different interval, or to listen to another port, and so on.
#
# slaveof <masterip> <masterport>

# If the master is password protected (using the "requirepass" configuration

# directive below) it is possible to tell the slave to authenticate before 

将红色部分修改为:

slaveof 192.168.1.12 6379

其中IP地址192.168.1.12为主服务器IP,端口为主服务器端口

然后启动redis服务

[root@LAMP redis-2.8.9]# redis-server /application/redis/conf/redis.conf  &
[1] 5940
[root@LAMP redis-2.8.9]#                 _._                                                 
           _.-``__ ''-._                                            
      _.-``    `.  `_.  ''-._           Redis 2.8.9 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
(    '      ,       .-`  | `,    )     Running in stand alone mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
|    `-._   `._    /     _.-'    |     PID: 5940
  `-._    `-._  `-./  _.-'    _.-'                                  
|`-._`-._    `-.__.-'    _.-'_.-'|                                 
|    `-._`-._        _.-'_.-'    |           http://redis.io       
  `-._    `-._`-.__.-'_.-'    _.-'                                  
|`-._`-._    `-.__.-'    _.-'_.-'|                                 
|    `-._`-._        _.-'_.-'    |                                 
  `-._    `-._`-.__.-'_.-'    _.-'                                  
      `-._    `-.__.-'    _.-'                                      
          `-._        _.-'                                          
              `-.__.-'                                              

[5940] 13 Jul 00:54:54.591 # Server started, Redis version 2.8.9
[5940] 13 Jul 00:54:54.591 * DB loaded from disk: 0.000 seconds
[5940] 13 Jul 00:54:54.591 * The server is now ready to accept connections on port 6379
[5940] 13 Jul 00:54:54.591 * Connecting to MASTER 192.168.1.12:6379
[5940] 13 Jul 00:54:54.592 * MASTER <-> SLAVE sync started
[5940] 13 Jul 00:54:54.594 * Non blocking connect for SYNC fired the event.
[5940] 13 Jul 00:54:54.642 * Master replied to PING, replication can continue...
[5940] 13 Jul 00:54:54.642 * Partial resynchronization not possible (no cached master)
[5940] 13 Jul 00:54:54.653 * Full resync from master: ffb234a2db473390b99948ae8b9cdb9022aca489:1
[5940] 13 Jul 00:54:54.757 * MASTER <-> SLAVE sync: receiving 358 bytes from master
[5940] 13 Jul 00:54:54.757 * MASTER <-> SLAVE sync: Flushing old data
[5940] 13 Jul 00:54:54.757 * MASTER <-> SLAVE sync: Loading DB in memory
[5940] 13 Jul 00:54:54.757 * MASTER <-> SLAVE sync: Finished with success

[root@LAMP redis-2.8.9]#

再在主服务器这边查看:

[root@LNMP conf]# [3248] 13 Jul 00:54:54.286 * Slave asks for synchronization
[3248] 13 Jul 00:54:54.297 * Full resync requested by slave.
[3248] 13 Jul 00:54:54.297 * Starting BGSAVE for SYNC
[3248] 13 Jul 00:54:54.299 * Background saving started by pid 8601
[8601] 13 Jul 00:54:54.332 * DB saved on disk
[8601] 13 Jul 00:54:54.341 * RDB: 0 MB of memory used by copy-on-write
[3248] 13 Jul 00:54:54.401 * Background saving terminated with success
[3248] 13 Jul 00:54:54.401 * Synchronization with slave succeeded

经过这边的发现主两边已经同步,下面进行测试:

在主服务器端进行写入数据:

[root@LNMP conf]# redis-cli
127.0.0.1:6379> set 001 redistest
OK
127.0.0.1:6379> get 001
"redistest"

127.0.0.1:6379>

然后在从服务器端查看:

[root@LAMP redis-2.8.9]# redis-cli
127.0.0.1:6379> get 001
"redistest"

127.0.0.1:6379>

发现在从服务器端可以获取到值 redistest

再次主服务器写入数据:

spacer.gifwKiom1cHoyWR0c78AAAVwHBl71Y059.png

从库继续查看:

spacer.gifwKiom1cHo0SynfB7AAAMtiCp7Jg185.png

 

现在从库做一个监控:redis-cli -h localhost -p 6379 monitor

spacer.gifwKiom1cHo2_yTuNcAAAqbL3iPGw429.png

然后在主库进行写入数据:

spacer.gifwKioL1cHpFfA8GYcAAAi8W21A7M535.png

再观察从库:

spacer.gifwKioL1cHpGaSx8d1AAC44SGyElg559.png

发现数据已经从主库同步到从库

这里从主库退出,再从主库连接到从库上,进行取数据:

spacer.gifwKiom1cHo9eR28OsAAAy-DIFK2g742.png

发现可以取到刚才主库写入的数据

统计信息:

redis-cli -h localhost -p 6379 info

[root@LNMP conf]# redis-cli -h localhost -p 6379 info
# Server
redis_version:2.8.9
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:f4fef593e6e0c11c
redis_mode:standalone
os:Linux 2.6.32-358.el6.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.4.7
process_id:3248
run_id:ffb234a2db473390b99948ae8b9cdb9022aca489
tcp_port:6379
uptime_in_seconds:82589
uptime_in_days:0
hz:10
lru_clock:10657853
config_file:/application/redis/conf/redis.conf

# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:1881496
used_memory_human:1.79M
used_memory_rss:2367488
used_memory_peak:1916864
used_memory_peak_human:1.83M
used_memory_lua:33792
mem_fragmentation_ratio:1.26
mem_allocator:jemalloc-3.2.0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1436720995
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:5
total_commands_processed:1120
instantaneous_ops_per_sec:1
rejected_connections:0
sync_full:1
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:3
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:318

# Replication
role:master
connected_slaves:1
slave0:ip=192.168.1.10,port=6379,state=online,offset=1845,lag=0
master_repl_offset:1845
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1844

# CPU
used_cpu_sys:178.05
used_cpu_user:97.68
used_cpu_sys_children:0.02
used_cpu_user_children:0.02

# Keyspace
db0:keys=18,expires=0,avg_ttl=0
[root@LNMP conf]# 

如果想统计某一段,就在后面直接跟标签名即可:

[root@LNMP conf]# redis-cli -h localhost -p 6379 info Replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.1.10,port=6379,state=online,offset=2181,lag=1
master_repl_offset:2195
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:2194

[root@LNMP conf]# redis-cli -h localhost -p 6379 info CPU
# CPU
used_cpu_sys:178.42
used_cpu_user:97.91
used_cpu_sys_children:0.02
used_cpu_user_children:0.02
[root@LNMP conf]#

 

[root@LNMP conf]# redis-cli -h localhost -p 6379 info Memory
# Memory
used_memory:1880776
used_memory_human:1.79M
used_memory_rss:2371584
used_memory_peak:1916864
used_memory_peak_human:1.83M
used_memory_lua:33792
mem_fragmentation_ratio:1.26
mem_allocator:jemalloc-3.2.0
[root@LNMP conf]# 

[root@LNMP conf]# redis-cli -h localhost -p 6379 info stats
# Stats
total_connections_received:11
total_commands_processed:1530
instantaneous_ops_per_sec:1
rejected_connections:0
sync_full:1
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:3
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:318
[root@LNMP conf]#

提示:也可以在交互模式下执行以上命令 


master和slave安装配置过程如下:

#1.wget 

#tar zxvf redis-2.8.19.tar.gz

#cd redis-2.8.19/src/

#vi Makefile

PREFIX?=/opt/etc/redis

 

#make && make install


#redis_6309.conf

daemonize yes

pidfile /var/run/redis_6309.pid

port 6309

tcp-backlog 10240

timeout 600

tcp-keepalive 60

loglevel notice

logfile stdout

logfile /data/log/redis/redis_6309.log

databases 16

save 900 1

save 300 10

save 60 10000

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir /data/redis/redis_6309/

slave-serve-stale-data yes

slave-read-only yes

repl-disable-tcp-nodelay no

slave-priority 100

maxmemory 4gb

maxmemory-policy allkeys-lru

appendonly no

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

 

 

#/opt/etc/redis/bin/redis-server /opt/etc/redis/conf/redis_6309.conf

 

 

 

 

#SLAVE 配置

daemonize yes

pidfile /var/run/redis_6309.pid

port 6309

tcp-backlog 10240

timeout 600

tcp-keepalive 60

loglevel notice

logfile stdout

logfile /data/log/redis/redis_6309.log

databases 16

save 900 1

save 300 10

save 60 10000

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir /data/redis/redis_6309/

slave-serve-stale-data yes

slave-read-only yes

repl-disable-tcp-nodelay no

slaveof 10.0.20.14 6309

slave-priority 100

maxmemory 4gb

maxmemory-policy allkeys-lru

appendonly no

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

 

 

 

二,redis master 非持久化,备持久化

2.1 master 

#redis 6309

daemonize yes

pidfile /var/run/redis.pid

port 6309

tcp-backlog 10240

timeout 0

tcp-keepalive 0

loglevel notice

logfile stdout

logfile /var/log/redis/redis_6309.log

databases 16

#save 900 1

#save 300 10

#save 60 10000

save ""

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir /var/lib/redis_6309/

slave-serve-stale-data yes

slave-read-only yes

repl-disable-tcp-nodelay no

slave-priority 100

maxmemory 4gb

maxmemory-policy allkeys-lru

appendonly yes

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

 

#redis 6310

more redis_6310.conf

daemonize yes

pidfile /var/run/redis_6310.pid

port 6310

tcp-backlog 10240

timeout 0

tcp-keepalive 0

loglevel notice

logfile stdout

logfile /var/log/redis/redis_6310.log

databases 16

#save 900 1

#save 300 10

#save 60 10000

save ""

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir /var/lib/redis_6310/

slave-serve-stale-data yes

slave-read-only yes

repl-disable-tcp-nodelay no

slave-priority 100

maxmemory 4gb

maxmemory-policy allkeys-lru

appendonly yes

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

 


2.2 salve 

#redis 6309

daemonize yes

pidfile /var/run/redis.pid

port 6309

tcp-backlog 10240

timeout 0

tcp-keepalive 0

loglevel notice

logfile stdout

logfile /data/redis/logs/redis_6309.log

databases 16

save 900 1

save 300 10

save 60 10000

save ""

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir /data/redis/6309/redis_6309/

slave-serve-stale-data yes

slave-read-only yes

slaveof 10.0.20.179 6309

repl-disable-tcp-nodelay no

slave-priority 100

maxmemory 4gb

maxmemory-policy allkeys-lru

appendonly no

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

 


 

#redis_6310

more redis_6310.conf

daemonize yes

pidfile /var/run/redis_6310.pid

port 6310

tcp-backlog 10240

timeout 0

tcp-keepalive 0

loglevel notice

logfile stdout

logfile /data/redis/logs/redis_6310.log

databases 16

save 900 1

save 300 10

save 60 10000

save ""

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir /data/redis/6310/redis_6310/

slave-serve-stale-data yes

slave-read-only yes

slaveof 10.0.20.179 6310

repl-disable-tcp-nodelay no

slave-priority 100

maxmemory 4gb

maxmemory-policy allkeys-lru

appendonly no

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

hz 10