总结redis第三部分(安全性、主从、哨兵、事物、持久化、发布与订阅、虚拟内存)
因为redis速度相当快,所以在一台比较好的服务器下,一个外部用户在一秒内可以进行15W次的密码尝试,这意味着需要设定非常强大的密码来防止暴力破解。
可以通过设置密码以及登录redis方式来操作,具体参考
九、redis主从复制9、1简介
1、Master可以拥有多个slave。
2、多个slave可以连接同一个master外,还可以连接到其他的slave。
3、主从复制不会阻塞master,在同步数据时,master可以继续处理client请求。
4、提供系统的伸缩性。
9、2主从复制过程1、slave与master建立连接,发送sync同步命令。
2、master会开启一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存。
3、master后台完成保存后,就把文件发送给slave。
4、slave将接收到的master文件保存到磁盘上。
9、3主从复制配置#现在使用同一台机器的不同配置模拟主从复制场景。root@redisconf]#pwd/application/redis/conf[root@redisconf]#lsappendonly.aofdump.rdbredis.conf[root@redisconf]#cd..[root@redisredis]#cp-aconfconf-slave#下述为从节点[root@redisredis]#cdconf-slave/[root@redisconf-slave]#lsappendonly.aofdump.rdbredis.conf#设置从节点端口port6380#设置从节点中的文件名和路径配置为XX-slave的形式logfile/application/redis/logs/redis-slave.logdir/application/redis/conf-slave/#配置主节点的IP和端口slaveof10.0.0.116379#配置主节点的密码(redis4.0主节点的redis.conf也要配置)masterauthredis#设置防火墙关闭状态[root@redisconf-slave]#/etc/init.d/iptablesstop[root@redisconf-slave]#/etc/init.d/iptablesstatusiptables:Firewallisnotrunning.#可使用info查看role角色,即可知道是主服务或从服务。
#主节点[root@redis~]#redis-server/application/redis/conf/redis.conf[root@redis~]#lsof-i:6379COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAMEredis-ser2456root4uIPv6162050t0TCP*:6379(LISTEN)redis-ser2456root5uIPv4162070t0TCP*:6379(LISTEN)[root@redis~]#cd/application/redis/logs/[root@redislogs]#lltotal1780-rw-r--r--1rootroot1751493Dec802:09redis.log-rw-r--r--1rootroot59765Dec802:09redis-slave.log[root@redislogs]#tailfredis.log2456:M08Dec02:08:46.338-Accepted10.0.0.11:175862456:M08Dec02:08:47.345-Accepted10.0.0.11:175872456:M08Dec02:08:48.352-Accepted10.0.0.11:175882456:M08Dec02:08:49.076-0clientsconnected(0slaves),758544bytesinuse#从节点[root@redis~]#redis-server/application/redis/conf-slave/redis.conf[root@redis~]#lsof-i:6380COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAMEredis-ser2460root4uIPv6162160t0TCP*:6380(LISTEN)redis-ser2460root5uIPv4162180t0TCP*:6380(LISTEN)[root@redis~]#cd/application/redis/logs/[root@redislogs]#lltotal1724-rw-r--r--1rootroot1741206Dec802:06redis.log-rw-r--r--1rootroot15808Dec802:06redis-slave.log#从节点日志如果出现下述情况的话,那么需要把redis.conf文件中的bind127.0.0.1注释掉。这种情况在多台机器中会出现,现在单台机器模拟是不会出现的,因为redis采用的安全策略是默认只允许本地访问,所以现在在同一台机器中测试就不用注释掉,redis.conf的具体参数参考“4、3、4redis.conf文件配置说明”。[root@redislogs]#tailfredis-slave.log2460:S08Dec02:09:49.164#ErrorconditiononsocketforSYNC:Brokenpipe2460:S08Dec02:09:50.168-0clientsconnected(0slaves),758544bytesinuse2460:S08Dec02:09:50.180*ConnectingtoMASTER10.0.0.11:63792460:S08Dec02:09:50.181*MASTER<->SLAVEsyncstarted2460:S08Dec02:09:50.181*NonblockingconnectforSYNCfiredtheevent.#可以发现从节点没有连接成功,那么需要设置从节点对应的redis.conf文件的bind值。[root@redisconf-slave]#lsof-i:6380COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAMEredis-ser2460root4uIPv6162160t0TCP*:6380(LISTEN)redis-ser2460root5uIPv4162180t0TCP*:6380(LISTEN)[root@redisconf-slave]#redis-cli-ashutdown-p6380shutdown[root@redisconf-slave]#lsof-i:6380[root@redisconf-slave]#pwd/application/redis/conf-slavebind127.0.0.1#主节点设置值[root@redis~]#redis-cli-aredis-p6379127.0.0.1:6379>keys*(emptylistorset)127.0.0.1:6379>setnamenamevalOK127.0.0.1:6379>getname"nameval"[root@redislogs]#pwd/application/redis/logs[root@redislogs]#tailfredis.log2506:M08Dec02:21:33.242-Accepted127.0.0.1:363242506:M08Dec02:21:33.584-1clientsconnected(1slaves),1848864bytesinuse2506:M08Dec02:21:38.616-DB0:1keys(0volatile)in4slotsHT.127.0.0.1:6379>delname(integer)1127.0.0.1:6379>keys*1)"name2"#从节点获取值[root@redis~]#redis-cli-aredis-p6380127.0.0.1:6380>keys*(emptylistorset)127.0.0.1:6380>keys*1)"name"127.0.0.1:6380>getname"nameval"2512:S08Dec02:19:28.089*BackgroundAOFrewritefinishedsuccessfully2512:S08Dec02:19:28.089-BackgroundAOFrewritesignalhandlertook236us2512:S08Dec02:19:32.915-1clientsconnected(0slaves),779440bytesinuse2512:S08Dec02:21:38.716-DB0:1keys(0volatile)in4slotsHT.2512:S08Dec02:21:38.717-2clientsconnected(0slaves),800536bytesinuse
#注意从节点是没有写操作的,只有读操作
127.0.0.1:6380>delname(error)READONLYYoucan'twriteagainstareadonlyslave.127.0.0.1:6380>keys*1)"name2"#通过监控查看#主节点做监控[root@redislogs]#redis-cli-aredis-p6379monitorOK127.0.0.1:6379>flushallOK127.0.0.1:6379>keys*(emptylistorset)[root@redislogs]#redis-cli-aredis-p6379monitorOK1481135598.941742[0127.0.0.1:36324]"flushall"1481135634.460910[0127.0.0.1:36324]"keys""*"127.0.0.1:6379>setnamenamevalOK127.0.0.1:6379>getname"nameval"[root@redislogs]#redis-cli-aredis-p6379monitorOK1481135697.418957[0127.0.0.1:36324]"set""name""nameval"1481135698.642795[0127.0.0.1:36324]"get""name"#从节点做监控[root@redisconf-slave]#redis-cli-aredis-p6380monitorOK127.0.0.1:6380>keys*(emptylistorset)[root@redisconf-slave]#redis-cli-aredis-p6380monitorOK1481135598.306657[010.0.0.11:6379]"PING"1481135598.947041[010.0.0.11:6379]"flushall"1481135608.370998[010.0.0.11:6379]"PING"1481135618.428639[010.0.0.11:6379]"PING"1481135628.493744[010.0.0.11:6379]"PING"1481135638.562807[010.0.0.11:6379]"PING"1481135648.730527[010.0.0.11:6379]"PING"1481135658.800544[010.0.0.11:6379]"PING"1481135663.809136[0127.0.0.1:62476]"keys""*"1481135668.860633[010.0.0.11:6379]"PING"[root@redisconf-slave]#redis-cli-aredis-p6380monitorOK1481135688.972458[010.0.0.11:6379]"PING"1481135697.422176[010.0.0.11:6379]"set""name""nameval"1481135699.036100[010.0.0.11:6379]"PING"127.0.0.1:6380>keys*1)"name"127.0.0.1:6380>getname"nameval"[root@redisconf-slave]#redis-cli-aredis-p6380monitorOK1481135747.385987[0127.0.0.1:62476]"keys""*"1481135749.378369[010.0.0.11:6379]"PING"1481135750.203089[0127.0.0.1:62476]"get""name"1481135759.444582[010.0.0.11:6379]"PING"
#主节点127.0.0.1:6379>infoReplication#Replicationrole:masterconnected_slaves:1slave0:ip=127.0.0.1,port=6380,state=online,offset=2256,lag=0master_repl_offset:2256repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:2repl_backlog_histlen:2255#Replication是通过info查看节点信息中的一部分#从节点127.0.0.1:6380>infoReplication#Replicationrole:slavemaster_host:10.0.0.11master_port:6379master_link_status:upmaster_last_io_seconds_ago:6master_sync_in_progress:0slave_repl_offset:2326slave_priority:100slave_read_only:1connected_slaves:0master_repl_offset:0repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0
有了主从复制以后,如果想对主从复制服务器进行监控,那么在redis2.6以后提供了一个“哨兵”的机制,在2.6版本中的哨兵为1.0版本并不稳定,会出现各种各种的问题,在redis2.8版本以后的哨兵功能才稳定起来。
顾名思义,哨兵的含义就是监控redis系统的运行状况,其功能主要有两点:
监控主数据库和从数据库是否正常运行。
2、主数据库出现故障时,可以自动将从数据库转换为主数据库,实现自动切换。
一个节点可以被多个哨兵去监控。哨兵跟所有redis节点是没有直接关系的,哨兵只是一个监控程序而已。
(可以使用keepalived(配合nginx使用)代替哨兵,实现高可用。)
10、2操作步骤#(只配主节点即可)
#配置sentinel.conf
[root@redisredis-3.2.5]#pwd/home/lly/tools/redis-3.2.5#拷贝到从节点目录下[root@redisredis-3.2.5]#cpsentinel.conf/application/redis/conf-slave/[root@redisredis-3.2.5]#cp/application/redis/conf-slave/sentinel.conf/application/redis/conf-slave/sentinel.conf.ori[root@redisredis-3.2.5]#vim/application/redis/conf-slave/sentinel.confsentinelmonitormymaster127.0.0.163791#名称,IP,端口,投票选举次数建议为1,多台机器记得设置master的内网IP(内部系统交互用内网IP,外部访问提供外网IP)。sentineldown-after-millisecondsmymaster5000#设置5000毫秒检测一次,默认1秒sentinelfailover-timeoutmymaster900000sentinelparallel-syncsmymaster2sentinelauth-passmymasterredis#主节点密码(节点redis.conf中未配置密码,那么此步省略)
#测试第一步
#启动哨兵模式,注意下面的命令中不要加-aredis–p6380[root@redisconf-slave]#redis-serversentinel.conf--sentinel&[root@redis~]#lsof-i:26379COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAMEredis-ser2650root4uIPv6194300t0TCP*:26379(LISTEN)redis-ser2650root5uIPv4194320t0TCP*:26379(LISTEN)#查看哨兵相关信息[root@redis~]#redis-cli-p26379infoSentinel#Sentinelsentinel_masters:1sentinel_tilt:0sentinel_running_scripts:0sentinel_scripts_queue_length:0sentinel_simulate_failure_flags:0master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=1,sentinels=1#主节点日志[root@redis~]#tailf/application/redis/logs/redis.log1481137928.553897[0127.0.0.1:36329]"PING"1481137929.589836[0127.0.0.1:36329]"PING"1481137929.763963[0127.0.0.1:36329]"PUBLISH""__sentinel__:hello""127.0.0.1,26379,a14563baa663afc1c2e06ee3cb07f222c220fd7b,0,mymaster,127.0.0.1,6379,0"
#测试第二步
#关闭主节点[root@redis~]#redis-cli-aredis-p6379shutdown#从节点日志[root@redisconf-slave]#tailf/application/redis/logs/redis-slave.log2574:S08Dec03:15:16.629*MASTER<->SLAVEsyncstarted2574:S08Dec03:15:16.629#ErrorconditiononsocketforSYNC:Connectionrefused2574:M08Dec03:15:17.016*Discardingpreviouslycachedmasterstate.2574:M08Dec03:15:17.016*MASTERMODEenabled(userrequestfrom'id=5addr=127.0.0.1:62481fd=7name=sentinel-a14563ba-cmdage=320idle=0flags=xdb=0sub=0psub=0multi=3qbuf=0qbuf-free=32768obl=36oll=0omem=0events=rcmd=exec')2574:M08Dec03:15:17.020#CONFIGREWRITEexecutedwithsuccess.2574:M08Dec03:15:17.048*1changesin900seconds.Saving...2574:M08Dec03:15:17.050*Backgroundsavingstartedbypid27122712:C08Dec03:15:17.067*DBsavedondisk2712:C08Dec03:15:17.068*RDB:6MBofmemoryusedbycopy-on-write2574:M08Dec03:15:17.150*Backgroundsavingterminatedwithsuccess2574:M08Dec03:15:17.980-Clientclosedconnection2574:M08Dec03:15:17.981-Clientclosedconnection2574:M08Dec03:15:18.069-Accepted127.0.0.1:624992574:M08Dec03:15:18.070-Accepted127.0.0.1:625002574:M08Dec03:15:20.671-DB0:1keys(0volatile)in4slotsHT.2574:M08Dec03:15:20.672-2clientsconnected(0slaves),800816bytesinuse2574:M08Dec03:15:25.705-DB0:1keys(0volatile)in4slotsHT.2574:M08Dec03:15:25.705-2clientsconnected(0slaves),800800bytesinuse#查看此时的哨兵信息[root@redis~]#redis-cli-p26379infoSentinel#Sentinelsentinel_masters:1sentinel_tilt:0sentinel_running_scripts:0sentinel_scripts_queue_length:0sentinel_simulate_failure_flags:0master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=1,sentinels=1#原从节点info信息(现在是主节点)127.0.0.1:6380>infoReplication#Replicationrole:masterconnected_slaves:0master_repl_offset:0repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0#原主节点info信息(现在是从节点)127.0.0.1:6379>infoReplicationCouldnotconnecttoRedisat127.0.0.1:6379:Connectionrefusednotconnected>
#测试第三步
#启动原主节点(现在是从节点)[root@redis~]#redis-server/application/redis/conf/redis.conf#查看哨兵切换日志,从节点切换到了原主节点6379[root@redisconf-slave]#redis-serversentinel.conf--sentinel&2650:X08Dec03:15:17.980#+failover-endmastermymaster127.0.0.163792650:X08Dec03:15:17.980#+switch-mastermymaster127.0.0.16379127.0.0.163802650:X08Dec03:15:17.981*+slaveslave127.0.0.1:6379127.0.0.16379@mymaster127.0.0.163802650:X08Dec03:18:07.759*+convert-to-slaveslave127.0.0.1:6379127.0.0.16379@mymaster127.0.0.16380#原主节点日志(现在是从节点)[root@redis~]#tailf/application/redis/logs/redis.log2574:M08Dec03:18:08.674*Backgroundsavingterminatedwithsuccess2574:M08Dec03:18:08.679*Synchronizationwithslave127.0.0.1:6379succeeded2574:M08Dec03:18:11.903-DB0:1keys(0volatile)in4slotsHT.2574:M08Dec03:18:11.903-3clientsconnected(1slaves),1891152bytesinuse2574:M08Dec03:18:16.932-DB0:1keys(0volatile)in4slotsHT.2574:M08Dec03:18:16.932-3clientsconnected(1slaves),1891136bytesinuse#原主节点info信息(现在是从节点)变成从节点信息notconnected>infoReplication#Replicationrole:slavemaster_host:127.0.0.1master_port:6380master_link_status:upmaster_last_io_seconds_ago:0master_sync_in_progress:0slave_repl_offset:2061slave_priority:100slave_read_only:1connected_slaves:0master_repl_offset:0repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0#原从节点info信息(现主节点),变成了主节点信息127.0.0.1:6380>infoReplication#Replicationrole:masterconnected_slaves:1slave0:ip=127.0.0.1,port=6379,state=online,offset=5736,lag=0master_repl_offset:5736repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:2repl_backlog_histlen:5735
首先是使用multi打开事务,然后进行设置,这时设置的数据都会放入队列里进行保存,最后使用exec执行,把数据依次存储到redis中,可以使用discard方法取消事务。
#multi标记一个事务块的开始。随后的指令将在执行EXEC时作为一个原子执行。返回值simple-string-reply:始终为OK#exec执行事务中所有在排队等待的指令并将链接状态恢复到正常当使用WATCH时,只有当被监视的键没有被修改,且允许检查设定机制时,EXEC会被执行返回值multi-bulk-reply:每个元素与原子事务中的指令一一对应当使用WATCH时,如果被终止,EXEC则返回一个空的应答集合#discard刷新一个事务中所有在排队等待的指令,并且将连接状态恢复到正常。如果已使用WATCH,DISCARD将释放所有被WATCH的key。返回值status-reply:所有返回都是OK#watch(锁定key,直到执行了multi/exec命令)标记所有指定的key被监视起来,在事务中有条件的执行(乐观锁)。返回值simple-string-reply:总是OK。#unwatch(取消事务命令)刷新一个事务中已被监视的所有key。如果执行EXEC或者DISCARD,则不需要手动执行UNWATCH。返回值simple-string-reply:总是OK。127.0.0.1:6379>keys*1)"age"127.0.0.1:6379>getage"11"127.0.0.1:6379>multiOK127.0.0.1:6379>incrageQUEUED127.0.0.1:6379>exec1)(integer)12127.0.0.1:6379>getage"12"127.0.0.1:6379>multiOK127.0.0.1:6379>incrageQUEUED127.0.0.1:6379>discardOK127.0.0.1:6379>getage"12"127.0.0.1:6379>keys*1)"age"127.0.0.1:6379>getage"13"127.0.0.1:6379>multiOK127.0.0.1:6379>incrageQUEUED127.0.0.1:6379>getageQUEUED127.0.0.1:6379>exec1)(integer)142)"14"127.0.0.1:6379>unwatchOK127.0.0.1:6379>getage"14"127.0.0.1:6379>getage"14"127.0.0.1:6379>multiOK127.0.0.1:6379>incrageQUEUED127.0.0.1:6379>unwatchQUEUED127.0.0.1:6379>getageQUEUED127.0.0.1:6379>exec1)(integer)152)OK3)"15"127.0.0.1:6379>watchageOK127.0.0.1:6379>multiOK127.0.0.1:6379>incrageQUEUED127.0.0.1:6379>unwatchQUEUED127.0.0.1:6379>discardOK127.0.0.1:6379>getage"15"
Redis的事务不能保证同时成功或失败进行提交或回滚,所以redis的事务目前还是比较简单的(程序中一般是不会使用redis事务的)。
127.0.0.1:6379>keys*1)"age"127.0.0.1:6379>getage"15"127.0.0.1:6379>setnamenamevalOK127.0.0.1:6379>multiOK127.0.0.1:6379>incrageQUEUED#注意incrname并没报错,是在执行exec命令时报错,这个incr命令在java中调用是报错的。127.0.0.1:6379>incrnameQUEUED#下述虽然报错,但是事务已提交,name没有改变。如果下述执行discard命令中断事务的话,对所有的值都不会有影响。127.0.0.1:6379>exec1)(integer)162)(error)ERRvalueisnotanintegeroroutofrange127.0.0.1:6379>getage"16"127.0.0.1:6379>getname"nameval"
Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到硬盘来保证持久化。Redis持久化的方式有以下两种。
12、1快照RDB文件方式snapshotting(快照)默认方式,将内存中以快照的方式写入到二进制文件中,默认为dump.rdb,可以通过配置设置自动做快照持久化的方式,我们可以配置redis在N秒内如果超过M个key修改,那么就自动做快照。
快照设置:
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存。下述同理。
save 300 10
save 60 10000
12、2AOF文件方式append-only file(缩写aof)的方式(有点类似于oracle日志),由于快照方式是在一定时间间隔做一次,所以可能发生redis意外down的清苦康就会丢失最后一次快照后的所有修改的数据,aof比快照方式有更好的持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到命令中,当redis重启启动时会重新执行文件中保存的写命令来在内存中重建这个数据库的内容。Aof文件不是立即写到磁盘上,可以通过配置文件修改强制写到硬盘中。
aof设置:
# appendonly yes //启动aof持久化方式有三种修改方式。
# appendfsync always //受到写命令就立即写入到磁盘中,效率最慢,但是保证完全的持久化。(比如页面写入慢,可能就是这种造成的,可加服务器处理)
# appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中。
# appendfsync no //完全依赖操作系统,性能最好,不进行同步,系统去操作,持久化没保证。
RDB文件和AOF文件只开其中一种即可
上述内容都是在redis.conf文件中配置的,redis.conf的参数解释详情参考“4、3、4redis.conf配置文件说明”。
十三、发布与订阅消息13、1简介Redis提供了简单的发布订阅功能。
使用subscribe [频道] 进行订阅监听。
使用publish [频道] [发布内容] 进行发布消息广播。
为了解耦发布者(publisher)和订阅者(subscribe)之间的关系,redis使用了channel(频道)作为两者的中介,发布者将信息直接发布给channel,而channel负责将信息发送给适当的订阅者,发布者和订阅者直接没有相互关系,也不知道对方的存在。
参考网站(包括场景和源码分析):
“http://blog.csdn.net/clh704/article/details/19754939”
“http://www.cnblogs.com/huangxincheng/p/5002794.html”
13、2操作13、2、1一个发布,一个监听#开启两个窗口,一个做发布,一个做监听。
#注意事项:发布窗口的publish后面的名称channel1一定要跟监听窗口中subscribe后面的名称channel1保持一致,不然不能监听到消息。
#发布窗口[root@redislogs]#redis-cli127.0.0.1:6379>publishchannel1testmessage1(integer)1#接收到发布信息的监听个数127.0.0.1:6379>publishchannel1testmessage2(integer)1127.0.0.1:6379>publishchanneltesttestmessage(integer)0#监听窗口127.0.0.1:6379>subscribechannel1Readingmessages...(pressCtrl-Ctoquit)1)"subscribe"2)"channel1"3)(integer)1#注意监听的信息是3个一组1)"message"2)"channel1"3)"testmessage1"#注意监听的信息是3个一组1)"message"2)"channel1"3)"testmessage2"
#发布部分[root@redislogs]#redis-cli127.0.0.1:6379>publishchannel1message1(integer)2127.0.0.1:6379>publishchannel1message2(integer)2#监听部分[root@redis~]#redis-cli127.0.0.1:6379>subscribechannel1Readingmessages...(pressCtrl-Ctoquit)1)"subscribe"2)"channel1"3)(integer)11)"message"2)"channel1"3)"message1"1)"message"2)"channel1"3)"message2"[root@redisconf]#redis-cli127.0.0.1:6379>subscribechannel1Readingmessages...(pressCtrl-Ctoquit)1)"subscribe"2)"channel1"3)(integer)11)"message"2)"channel1"3)"message1"1)"message"2)"channel1"3)"message2"
#发布部分[root@redislogs]#redis-cli127.0.0.1:6379>publishchannel1message11(integer)2127.0.0.1:6379>publishchannel1message12(integer)2[root@redis~]#redis-cli127.0.0.1:6379>publishchannel2message21(integer)2127.0.0.1:6379>publishchannel2message22(integer)2#监听部分[root@redis~]#redis-cli127.0.0.1:6379>subscribechannel1channel2Readingmessages...(pressCtrl-Ctoquit)1)"subscribe"2)"channel1"3)(integer)11)"subscribe"2)"channel2"3)(integer)21)"message"2)"channel1"3)"message11"1)"message"2)"channel2"3)"message21"1)"message"2)"channel1"3)"message12"1)"message"2)"channel2"3)"message22"[root@redisconf]#redis-cli127.0.0.1:6379>subscribechannel1channel2Readingmessages...(pressCtrl-Ctoquit)1)"subscribe"2)"channel1"3)(integer)11)"subscribe"2)"channel2"3)(integer)21)"message"2)"channel1"3)"message11"1)"message"2)"channel2"3)"message21"1)"message"2)"channel1"3)"message12"1)"message"2)"channel2"3)"message22"
下述内容参考文档
“http://ifeve.com/redis-mem/”
“http://blog.csdn.net/xinguimeng/article/details/43884893”
“http://www.cnblogs.com/stephen-liu74/archive/2012/04/04/2366803.html”
14、1简介和大多数NoSql数据库一样,redis同样遵循了key/values数据存储模型。在有些情况下,redis会将key/values保存在内存中以提高数据查询和数据修改的效率,然而这样的做法并非总是很好的选择。鉴于此,我们可以将之进一步优化,即尽量在内存中只保留keys的数据,这样可以保证数据检索的效率,而values数据在很少使用的时候可以被换出到磁盘。
redis未使用linux的虚拟内存机制,而是实现了自己的虚拟内存机制,主要原因有以下两点:
1、linux虚拟内存粒度过大,在linux中使用4KB的页面,对于redis来说太大了,而redis中的绝大多数对象都远远小于这个数值。
2、redis可以把数据交换到磁盘上的时候进行适当的操作,比如压缩,通常保存到磁盘上的对象可以去除指针和对象元数据信息,一般压缩后的对象可以比内存中的对象小10倍,这样可以节省很多的IO操作。
14、2应用场景在实际应用中,如果内存中有一个10W条记录的key数据集,而只有10%被经常使用,那么开启虚拟内存的redis将把与较少使用的key相对应的value转移到磁盘上。当客户端请求获取这些value时,他们将被从swap文件中读回,并载入到内存中。也就是说,如果你的数据库中有大量的keys,其中每个key仅仅关联很小的value,那么这种场景就不是非常适合使用虚拟内存。如果数据库中只是包含很少的keys,而每一个key所关联的value确非常大,那么这种场景就适合使用虚拟内存。
14、3虚拟内存配置1、在配置文件中添加以下配置项,以使当前Redis服务器在启动时打开虚存功能。
vm-enabled yes
2、在配置文件中设定Redis最大可用的虚存字节数。如果内存中的数据大于该值,则有部分对象被换出到磁盘中,其中被换出对象所占用内存将被释放,直到已用内存小于该值时才停止换出。
vm-max-memory (bytes)
Redis的交换规则是尽量考虑"最老"的数据,即最长时间没有使用的数据将被换出。如果两个对象的age相同,那么Value较大的数据将先被换出。需要注意的是,Redis不会将Keys交换到磁盘,因此如果仅仅keys的数据就已经填满了整个虚存,那么这种数据模型将不适合使用虚存机制,或者是将该值设置的更大,以容纳整个Keys的数据。在实际的应用,如果考虑使用Redis虚拟内存,我们应尽可能的分配更多的内存交给Redis使用,以避免频繁的换入换出。
3、在配置文件中设定页的数量及每一页所占用的字节数。为了将内存中的数据传送到磁盘上,我们需要使用交换文件。这些文件与数据持久性无关,Redis会在退出前会将它们全部删除。由于对交换文件的访问方式大多为随机访问,因此建议将交换文件存储在固态磁盘上,这样可以大大提高系统的运行效率。
vm-pages 134217728
vm-page-size 32
在上面的配置中,Redis将交换文件划分为vm-pages个页,其中每个页所占用的字节为vm-page-size,那么Redis最终可用的交换文件大小为:vm-pages * vm-page-size。由于一个value可以存放在一个或多个页上,但是一个页不能持有多个value,鉴于此,我们在设置vm-page-size时需要充分考虑Redis的该特征。
4、在Redis的配置文件中有一个非常重要的配置参数,即:
vm-max-threads 4
该参数表示Redis在对交换文件执行IO操作时所应用的最大线程数量。通常而言,我们推荐该值等于主机的CPU cores。如果将该值设置为0,那么Redis在与交换文件进行IO交互时,将以同步的方式执行此操作。
对于Redis而言,如果操作交换文件是以同步的方式进行,那么当某一客户端正在访问交换文件中的数据时,其它客户端如果再试图访问交换文件中的数据,该客户端的请求就将被挂起,直到之前的操作结束为止。特别是在相对较慢或较忙的磁盘上读取较大的数据值时,这种阻塞所带来的影响就更为突兀了。然而同步操作也并非一无是处,事实上,从全局执行效率视角来看,同步方式要好于异步方式,毕竟同步方式节省了线程切换、线程间同步,以及线程拉起等操作产生的额外开销。特别是当大部分频繁使用的数据都可以直接从主内存中读取时,同步方式的表现将更为优异。
如果你的现实应用恰恰相反,即有大量的换入换出操作,同时你的系统又有很多的cores,有鉴于此,你又不希望客户端在访问交换文件之前不得不阻塞一小段时间,如果确实是这样,我想异步方式可能更适合于你的系统。
至于最终选用哪种配置方式,最好的答案将来自于不断的实验和调优。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。