1.基本概念
redis和memcached一样,也是一个key-value存储系统,支持的存储value类型更多,包括string(字符串),list(链表),set(集合),zset(有序集合)和hash(哈希);它和memcached一样,数据都是换存在内存中,区别是redis会周期的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步,数据可以从主服务器向任意数量的从服务器同步,从服务器可以是关联其他从服务器的主服务器,由于完全实现发布/订阅机制,使得从数据库在任何地方同步时,可订阅一个频道并接受主服务器完整的消息发布记录;它提供了丰富的客户端,如:java,c/c++,c#,php,javascript,perl,object-c,python,ruby,erlang等。
2.redis数据存储
redis的持久化存储分为数据快照和只增文件三部分,配置文件中有二个参数对其进行配置。
(1)save seconds updated,save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配置,比如默认配置文件中的设置,就设置了三个条件。
这种方式叫做数据快照,是默认的方式。它将数据做一个备份,将数据存储到二进制文件中,这个二进制的文件默认的文件名称为dump.rdb,我们可以通过save secondes updated来是指n秒内如果超过m个key键修改就自动做快照。但是这种方式存在缺陷:由于快照方式实在一定间隔时间做一次的,所以如果redis意外宕机的话,就会丢失最后一次快照后的所有修改
(2)appendonly yes/no,appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。
这种方式叫做只增文件,它在写入内存数据的同时将操作命令保存到日志文件(默认命名为appendonly.aof),在redis遇到意外情况后重启时可以通过日志文件恢复到数据库状态。但是,正因为如此,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建时间也会很长。
3.redis持久化工作
(1)客户端向服务端发送写操作(数据在客户端的内存中)
(2)数据库服务端收到写请求的数据(数据在服务端的内存中)
(3)服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区)
(4)操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)
(5)磁盘控制器将数据写到磁盘的物理介质上(数据真正落到磁盘上)
其中appenfsync来控制redis中对aof调用write写入后,何时再调用fsync将其写到磁盘上,它的参数为:
appendfsync no/always/everysec,
no表示不会主动调用fsync去将aof日志内容同步到磁盘,所以只能,always表示每次更新操作后手动调用fysnc()将数据写到磁盘,只能依赖于操作系统的调试了。对大多数的linux操作系统,是每30秒进行一次fsync,将缓冲区的数据写到磁盘上。
ererysec,redis会默认每隔一秒进行一次fsync调用,将缓冲区的数据写到磁盘。但是当这一次的fsync调用市场超过1秒,redis会采取延迟fsync的策略,再等一秒钟。也就是两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。因此,在绝大多数情况下,redis会每隔一秒进行一次fsync,在最坏情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库心痛中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘
always,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会收到影响。
3.redis内存优化
(1)虚拟内存功能,redis存储超过物理内存数据的一种数据在内存和磁盘换入换出的一个持久化策略,但是管理成本非常高,所以要关闭vm功能,vm-enabled为no
(2)redis为不同数据类型分别提供了一组参数来控制内存使用,这里就不做过多介绍
4.redis过期策略,这点比memcached的lur要丰富的多。
config set maxmemory-policy volatile-lru
volatile-lru:只对设置了过期时间的key进行lru(默认值)
allkeys-lru:是从所有key里删除不经常使用的key
volatile-random:随机删除即将过期的key
allkeys-random:随机删除
volatile-ttl:删除即将过期的
noeviction:永不过期,返回错误
maxmemory-samples 3是说每次进行淘汰的时候会随机抽取3个key,从里面淘汰最不经常使用的(默认选项)
以上是对redis的基本了解,下面我们来安装并试用下吧。
[root@uvmsvr12 src]$ wget http://download.redis.io/releases/redis-2.8.19.tar.gz
[root@uvmsvr12 src]$ tar -zxvf redis-2.8.19.tar.gz
[root@uvmsvr12 src]$ cd redis-2.8.19
[root@uvmsvr12 src]$ make
[root@uvmsvr12 src]$ make test
此时会报错:
You need tcl 8.5 or newer in order to run the Redis test
我们需要安装tcl8.5
[root@uvmsvr12 src]$ wget http://downloads.sourceforge.net/tcl/tcl8.6.3-src.tar.gz
[root@uvmsvr12 src]$ tar -zxvf tcl8.6.3-src.tar.gz
[root@uvmsvr12 src]$ cd tcl8.6.3/unix
[root@uvmsvr12 src]$ ./configure
[root@uvmsvr12 src]$ make && make install
安装完毕后我们继续安装redis
[root@uvmsvr12 src]$ cd redis-2.8.19
[root@uvmsvr12 src]$ make test
[root@uvmsvr12 src]$ make PREFIX=/usr/local/redmis install
这样redis就被安装在/usr/local/redis下了
[root@uvmsvr12 redis]# ll bin
total 15220
-rwxr-xr-x 1 root root 4586275 Mar 31 16:39 redis-benchmark #redis性能测试工具,测试redis在你的系统及你的配置下的读写性能
-rwxr-xr-x 1 root root 22185 Mar 31 16:39 redis-check-aof>
-rwxr-xr-x 1 root root 45395 Mar 31 16:39 redis-check-dump
-rwxr-xr-x 1 root root 4679763 Mar 31 16:39 redis-cli #redis命令行工具
lrwxrwxrwx 1 root root 33 Mar 31 16:39 redis-sentinel -> /usr/local/redis/bin/redis-server
-rwxr-xr-x 1 root root 6241764 Mar 31 16:39 redis-server #redis服务的daemon启动程序
至于配置文件我们可以从源码目录中copy
copy /usr/local/redis-2.8.19/redis.conf /usr/local/redis/
copy /usr/local/redis-2.8.19/sentinel.conf /usr/local/redis/
其中redis.conf我们可以用来master和slave,而sentinel.conf是用来配置高可用的配置文件,我们以后再介绍。
下面我们来看下配置文件redis.conf
daemonize no #redis默认不是以守护进程的方式运行,可以通过修改此选项,使用yes,启用守护进程
pidfile /var/run/redis.pid
port 6379
tcp-backlog 511
timeout 0 #当客户端闲置多长时间,关闭连接,单位秒
tcp-keepalive 0 #如果非0,单位秒,表示将周期性的使用so_keepalive监测客户端是否还处于健康状态,避免服务器一直阻塞,官方建议60秒
loglevel notice #日志级别,此为普通信息,用于生产环境
logfile " #日志存储路径
databases 16 #可用的数据库数,默认值为16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes #当持久化出现错误之后,是否继续提供写服务
rdbcompression yes #持久化到rdb文件时,是否压缩
rdbchecksum yes #读取和写入的时候是否支持CRC64校验,默认开启
dbfilename dump.rdb #镜像文件的名字
dir ./ #当前工作目录,配置文件和镜像文件都在此目录下
slave-serve-stale-data yes #当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果为yes,slave服务器可以继续接受客户端的请求,否则,会返回给请求的客户端如下信息"sync with master in progress"
slave-read-only yes #是否允许slave服务器节点只提供读服务
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no #指定想slave同步数据时,是否禁用socket的no_dely选项。若为yes,禁用no_delay,则tcp协议栈不会延迟小包的发送时机,这样数据同步的延时会小,但需要更大的带宽,应该配置为no以降低同步延时,但在主从节点间网络负载已经很高的情况下,可以配置为yes
slave-priority 100 #指定slave的优先级。在不只1个slave存在的部署环境下,当master宕机时,redis sentinel会将priority最小的slave提升为master。需要注意的是,若该配置为0,则对应的slave永远不会自动提升为master
appendonly no #开启appendonly模式之后,redis会把所接受到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该2文件恢复出之前的状态,但是这会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof进行重新整理,模式是不开启的。
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no #指定是否在后台aof文件rewrite期间调用fsync,默认为no。redis在后台写rdb文件或重写aof文件期间会存在大量的磁盘io,此时,在某些linux系统中,调用fsync可能会阻塞</span>
auto-aof-rewrite-percentage 100 #指定redis重写aof文件的条件,默认为100,表示与上次rewrite的aof文件大小相比,当前aof文件增长量超过上次aof文件大小的100%时,就会触发background rewrite。若配置为0,则会禁用自动rewrite
auto-aof-rewrite-min-size 64mb #指定触发rewrite的aof文件大小。若aof文件小于该值,即使当前文件的增量比例达到auto-aof-rewrite-percentage的配置,也不会触发自动rewrite,即这两个配置项同时满足时,才会触发rewrite。
aof-load-truncated yes
lua-time-limit 5000 #一个lua脚本最长的执行时间,单位为毫秒,如果为0或负数表示无限执行时间,默认为5000
slowlog-log-slower-than 10000 #时间单位为微秒,注意,负数时间会禁用满查询日志,而0则会强制记录所有命令
slowlog-max-len 128 #慢查询日志长度,这个长度没有限制。只是主要会消耗内存,你可以通过slowlog reset来回收内存
latency-monitor-threshold 0
notify-keyspace-events "" #带一个由0到多个字符组成的字符串参数。空字符串意思是通知被禁用
hash-max-ziplist-entries 512 #针对hash类型,只要hash的filed在这个范围内使用紧凑存储,这可以节省存储,也是为什么要尽量使用hash少使用的理由,特别在原子技术的时候,对一个用户可能要记录很多数量,一定要采用hash的策略,这是非常有用的。当然这个值不是越大越好,通常不要超过1024
hash-max-ziplist-value 64 #hash的value的大小,在这个大小内会使用紧凑存储。<span style="font-family: Arial, Helvetica, sans-serif;">当然这个值不是越大越好,通常不要超过512</span>
list-max-ziplist-entries 512 #和hash的用法一样,但是针对list
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
介绍完配置文件后,我们来单独配置一个,如下:
daemonize yes
pidfile "/var/run/redis.pid"
port 6379
loglevel notice
logfile "/var/log/redis/redis.log"
databases 16
dbfilename "dump.rdb"
dir "/data/redisdb"
启动redis
/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf
由于默认使用6379端口,我们可以使用redis-cli命令登陆
[root@uvmsvr12 redis]$ /usr/local/redis/bin/redis-cli -p 6379
127.0.0.1:6379> set name test
OK
127.0.0.1:6379> get name
"test"
127.0.0.1:6379>
停止redis实例
/usr/local/redis/bin/redis-cli -p 6379 shutdown
好,redis的初步认识就先了解到这里吧,关于主从以及高可用我们本月再说。