Reids 6.x——高级主题 高级主题1、服务器配置1.1、Redis服务器允许远程主机访问1.2、客户端远程连接Redis服务器1.3、设置密码1.3.1、通过命令设置Redis密码1.3.2、通过修改Redis配置文件设置密码1.4、Redis端口修改1.5、查看配置1.6、修改配置1.7、配置项说明2、Redis事务2.1、Redis事务的常用命令4.2、简单事务控制2.3、取消一个事务2.4、乐观锁控制复杂事务3、Redis发布和订阅3.1、Redis发布和订阅的常用命令3.2、Redis发布和订阅实例4、Redis管道5、数据备份与恢复5.1、数据备份5.2、数据恢复6、Redis性能测试7、Redis客户端连接8、Redis服务开机自启动8.1、Windows下Redis服务开机自启动8.2、Linux下Redis服务开机自启动9、Redis内存分析工具介绍Redis的高级主题包括服务器配置、Redis事务、Redis发布和订阅、Pipeline批量发送请求、数据备份与恢复等。1、服务器配置在Windows和Linux的Redis服务器里面都有一个配置文件。Redis配置文件位于Redis安装目录下在不同操作系统下Redis配置文件名是不一样的。在Windows下Redis配置文件名为redis.windows.conf。在Linux下Redis配置文件名为redis.conf。在Linux下使用redis-server命令启动Redis服务器时可以在命令后面指定配置文件。例如在Linux下使用如下命令启动Redis服务器。$ redis-server /usr/local/redis/conf/redis.conf也可以通过Redis的CONFIG命令对Redis配置文件进行查看或设置项。1.1、Redis服务器允许远程主机访问若主机需要远程访问Redis服务器则可以修改Redis配置文件redis.conf。文件中bind字段默认为bind127.0.0.1表示只能在本机访问Redis服务器如图所示。若允许远程主机访问Redis服务器可以将bind 127.0.0.1改为bind 0.0.0.0。找到daemonize no把这一项的no改成yes。daemonize yes主要是开启Redis的守护进程可以在Linux启动时自动运行Redis将Redis服务器作为守护进程daemon来运行。daemonizeyes关闭protected-mode模式让外部网络可以直接访问Redis服务器。在Redis配置文件中找到protected-modeyes把这一项的yes改成no。protected-mode no1.2、客户端远程连接Redis服务器远程连接Redis服务器需要使用redis-cli命令redis-cli命令的用法为redis-cli[OPTIONS]​[cmd[arg[arg…]​]​]​。redis-cli命令的关键参数如下。-h主机IP地址默认是127.0.0.1。-p端口默认是6379。-a密码如果Redis设置了密码需要传递密码。假设有两台Redis服务器Redis服务器的IP地址分别是192.168.1.11和192.168.1.14。现在需要在192.168.1.11上通过redis-cli命令远程访问192.168.1.14上的Redis服务器在192.168.1.11上通过以下命令远程连接192.168.1.14上的Redis服务器。$ redis-cli-h192.168.1.14-p6379192.168.1.14:6379SET age20OK192.168.1.14:6379GET age20通过本例客户端远程连接到192.168.1.14上的Redis服务器设置了一个String类型的值使age等于“20”​。1.3、设置密码通过Redis配置文件来设置密码客户端连接到Redis服务器时就需要密码验证这样可以让Redis服务器更安全。1.3.1、通过命令设置Redis密码首先通过CONFIG GET requirepass命令查看Redis服务器是否设置了密码验证。127.0.0.1:6379CONFIG GET requirepass1)requirepass2)默认情况下requirepass对应的参数是空的即没有密码表示不需要通过密码验证就可以连接到Redis服务器。然后设置Redis服务器的当前密码为123。Redis服务器重新启动后又会将密码重置为默认即没有密码因此不建议用此种方式设置密码。127.0.0.1:6379CONFIG SET requirepass123OK127.0.0.1:6379CONFIG GET requirepass1)requirepass2)123通过命令设置Redis密码的完整实例如下。[rootbogon bin]# ./redis-cli -h 127.0.0.1 -p 6379# 获取现有Redis服务器密码127.0.0.1:6379CONFIG GET requirepass1)requirepass2)# 设置新密码127.0.0.1:6379CONFIG SET requirepass123OK127.0.0.1:6379exit# 重新设置密码后连接Redis服务器需添加密码参数[rootbogon bin]# ./redis-cli -h 127.0.0.1 -p 6379 -a 123127.0.0.1:6379setage20OK重新设置密码后需要重新登录Redis服务器才能获取操作权限。1.3.2、通过修改Redis配置文件设置密码编辑redis.conf配置文件添加requirepass值设置密码。requirepass123以上设置的Redis服务器的访问密码为123读者可以根据实际需要进行密码的设置。重启Redis服务器后再次进入Redis客户端并输入以下内容。127.0.0.1:6379KEYS *(error)NOAUTH Authentication required发现没有权限进入当前数据库需要使用AUTH命令进行授权操作。127.0.0.1:6379AUTH123OK输入密码则成功进入当前数据库用这种方式每次进入当前数据库的时候都需要输入密码。还有一种简单的方式即直接登录数据库并授权。[rootbogon bin]# ./redis-cli -h 127.0.0.1 -p 6379 -a 123在本例中我们设置了Redis服务器的访问密码为123。建议用此种方式设置密码重启Redis服务器后就可以使用设置好的密码连接Redis服务器了。1.4、Redis端口修改Redis默认的端口是6379在redis.conf配置文件里搜索6379就能找到端口参数配置如下所示。# Accept connections on the specified port, default is 6379 (IANA #815344).# If port 0 is specified Redis will not listen on a TCP socket.port6379可以将默认的端口修改成指定的端口不要端口冲突就行。启动Redis服务器后可以使用ps-ef|grep redis命令查看Redis服务器占用的端口如图所示。从图可以看出现在Redis服务器使用的端口是6379。1.5、查看配置可以通过CONFIG GET命令查看配置。CONFIG GET命令的基本语法如下。redis127.0.0.1:6379CONFIG GET CONFIG_SETTING_NAME实例查看Redis的日志级别。127.0.0.1:6379CONFIG GET loglevel1)loglevel2)notice1.6、修改配置可以通过修改redis.conf配置文件或使用CONFIG SET命令来修改配置。CONFIG SET命令的基本语法如下。redis127.0.0.1:6379CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE实例修改Redis记录的日志级别。127.0.0.1:6379CONFIG SET loglevelnoticeOK127.0.0.1:6379CONFIG GET loglevel1)loglevel2)notice127.0.0.1:63791.7、配置项说明redis.conf配置项说明如下。Redis默认不是以守护进程的方式运行的可以通过daemonize配置项修改。如果指定为yes表示启用守护进程。daemonize no当Redis以守护进程的方式运行时Redis默认会把pid写入/var/run/redis.pid文件可以通过pidfile配置项来指定。pidfile /var/run/redis.pid指定Redis监听端口可以通过port配置项来指定默认端口为6379。port6379指定绑定的主机地址可以用于限制连接默认只能本机访问Redis服务器。bind127.0.0.1指定Redis客户端闲置多长时间后关闭连接如果指定为0表示关闭该功能。timeout300指定日志的记录级别Redis支持4个级别即debug、verbose、notice、warning默认值为verbose。loglevel verbose指定日志文件的保存路径如果指定为表示默认为标准输出。logfile指定数据库的数量默认数据库数量为0可以使用SELECT命令来连接指定的数据库。databases16指定在多长时间内执行多少次更新操作Redis就将数据同步到数据文件中。savesecondschangesRedis的默认配置文件中设置了3个触发条件。save9001save30010save6010000save 900 1表示900s15min内有1个更新save 30010表示300s5min内有10个更新save 60 10000表示60s1min内有10 000个更新Redis就将数据同步到数据文件中。对于存储到磁盘中的Redis快照可以设置是否进行压缩存储默认值为yes。如果指定为yesRedis会采用LZF压缩算法对存储到磁盘中的Redis快照进行压缩。如果不想消耗CPU来压缩快照的话可以指定为no来关闭该选项但是存储在磁盘上的快照会比较大。rdbcompressionyes指定存储数据的本地数据库的文件名默认值为dump.rdb。dbfilename dump.rdb指定本地数据库存放目录。「dir/usr/local/redis/bin指定当本机为Slave从服务器服务时Master主服务器服务的IP地址及端口。在Redis启动时它会自动从Master服务进行数据同步。slaveofmasteripmasterport指定当Master服务设置了密码保护时Slave服务连接Master服务的密码。masterauthmaster-password指定Redis的连接密码。如果配置了连接密码则客户端在连接Redis时需要使用AUTH命令提供密码默认配置是关闭的。requirepass foobared指定同一时间内客户端允许的最大连接数如果设置为maxclients 0表示不做限制。当客户端连接数达到最大限制时Redis会关闭新的连接并向客户端发送maxnumber of clients reached错误信息。maxclients128指定Redis的最大内存限制。Redis在启动时会把数据缓存到内存中达到最大内存后Redis会尝试清除已到期的key。Redis新的vm虚拟内存机制会把key存放在内存把value存放在swap区。maxmemorybytes指定Redis是否在每次执行更新操作后进行日志记录在默认情况下Redis是异步地把内存中的数据写入磁盘的。如果不开启此选项可能会在主机断电时丢失一段时间内的数据。该选项默认值为no。appendonly no指定更新日志文件名默认值为appendonly.aofappendfilename appendonly.aof指定更新日志的条件共有3个可选值。no表示等操作系统进行数据缓存后才同步到磁盘特点是速度快。always表示每次执行更新操作后需要手动调用fsync()将数据写到磁盘特点是速度慢比较安全。everysec表示每秒同步一次数据到磁盘是上面两个选项的折中选项也是默认值。appendfsync everysec指定是否启用虚拟内存机制默认值为no。vm-enabled no指定虚拟内存文件路径默认值为/tmp/redis.swap。不可多个Redis实例共享。vm-swap-file /tmp/redis.swap指定将所有大于vm-max-memory的数据存入虚拟内存默认值为0无论vm-max-memory多小所有索引数据都是内存存储的Redis的索引数据就是key​也就是说当vm-max-memory设置为0的时候其实是所有value都存储在磁盘。vm-max-memory0Redis的swap文件被分成了很多个page一个对象可以保存在多个page上但一个page不能被多个对象共享。vm-page-size32指定swap文件中的page数量。vm-pages134217728指定访问swap文件的线程数此选项值最好不要超过计算机的核数。如果设置为0那么所有对swap文件的操作都是串行的可能会造成比较长时间的延迟。此选项默认值为4。vm-max-threads4指定在向客户端响应时是否把较小的包合并为一个包发送默认值为yes。glueoutputbufyes2、Redis事务Redis的事务可以一次执行多个命令有以下两个重要的特点。事务是一个单独的隔离操作事务中的所有命令都会按顺序执行事务在执行的过程中不会被其他客户端发送的命令所打断。事务是一个原子性操作事务中的命令要么全部被执行要么全部都不执行。一个事务会经历3个阶段即开始事务、命令入队、执行事务如图所示。2.1、Redis事务的常用命令下表列出了Redis事务的常用命令及其描述。4.2、简单事务控制以下是一个简单事务控制的实例。先使用MULTI命令开始一个事务然后将多个命令入队到事务中最后由EXEC命令触发事务一起执行事务块内的所有命令。127.0.0.1:6379SET age20OK127.0.0.1:6379MULTI OK#两个SET命令都没有被执行而是被放到了队列中127.0.0.1:6379SET age21QUEUED127.0.0.1:6379SET age22QUEUED127.0.0.1:6379GET age QUEUED#SADD命令也没有被执行也被放到了队列中127.0.0.1:6379SADD tagjavapythoncQUEUED127.0.0.1:6379SMEMBERS tag QUEUED# 触发事务一起执行队列中的命令执行命令后返回的是执行3个命令的结果127.0.0.1:6379EXEC1)OK2)OK3)224)(integer)35)1)python2)c3)java# 查看 age对应的字符串127.0.0.1:6379GET age22# 查看 tag对应的集合127.0.0.1:6379SMEMBERS tag1)python2)c3)java[插图]从本例中可以看到两个SET命令和一个SADD命令并没有被立即执行而是放到了队列中在执行EXEC命令后3个命令才被连续执行最后返回的是3个命令的执行结果。2.3、取消一个事务我们可以执行DISCARD命令来取消一个事务让事务回滚。实例如下。127.0.0.1:6379SET age20OK127.0.0.1:6379GET age20127.0.0.1:6379MULTI OK127.0.0.1:6379SET age21QUEUED127.0.0.1:6379SET age22QUEUED127.0.0.1:6379DISCARD OK127.0.0.1:6379GET age20从本例中可以看到两个SET命令并没有被立即执行而是放到了队列中在执行DISCARD命令后清空事务的命令队列并退出事务的上下文也就是事务回滚。2.4、乐观锁控制复杂事务乐观锁就是利用版本号比较机制只是在读数据的时候将读到的数据的版本号一起读出来当对数据的读操作结束并准备写数据的时候再进行一次数据的版本号的比较。若版本号没有变化即认为数据是一致的没有更改可以直接写入若版本号有变化则认为数据被更新不能写入防止脏写。乐观锁工作机制执行WATCH命令监视Redis给定的每一个key当执行EXEC命令时如果监视的任何一个key自从执行WATCH命令后发生过变化则整个事务会回滚不执行任何操作。Redis的乐观锁实例测试如表所示。为了解决这个问题引入了乐观锁使用乐观锁的实例如表所示。通过以上基于Redis的乐观锁的简单实例我们可以得出以下两点结论。乐观锁的实现必须基于WATCH命令然后利用Redis的事务。WATCH的生命周期只和事务关联一个事务执行完毕相应的WATCH的生命周期就会结束。3、Redis发布和订阅Redis发布和订阅是一种消息通信模式发送者Publish用来发送消息订阅者Subscribe用来接收消息。Redis客户端可以订阅任意数量的频道。下图展示了频道channel1以及订阅这个频道的3个客户端client2、client5和client1之间的关系。当有新消息通过PUBLISH命令发送给频道channel1时这个消息就会被发送给订阅它的3个客户端client2、client5和client1​如图所示。3.1、Redis发布和订阅的常用命令下表列出了Redis发布和订阅的常用命令及其描述。3.2、Redis发布和订阅实例以下实例演示了发布和订阅是如何工作的。首先打开一个客户端连接Redis服务器作为订阅者接收消息。在本实例中我们创建了一个订阅频道命名为redisChat。127.0.0.1:6379SUBSCRIBE redisChat Reading messages...(press Ctrl-C to quit)1)subscribe2)redisChat3)(integer)1其次重新开启一个Redis客户端作为发送者发送消息然后在同一个频道redisChat发布两次消息订阅者就能接收消息。127.0.0.1:6379PUBLISH redisChatmessage1(integer)1127.0.0.1:6379PUBLISH redisChatmessage2(integer)1127.0.0.1:6379订阅者的客户端会显示如下消息。127.0.0.1:6379SUBSCRIBE redisChat Reading messages...(press Ctrl-C to quit)1)subscribe2)redisChat3)(integer)11)message2)redisChat3)message11)message2)redisChat3)message24、Redis管道Redis是一个客户端-服务器CS模型的TCP服务器使用和HTTP类似的相应请求协议。一个客户端可以通过一个Socket连续发送多个请求命令每个请求命令发出后客户端通常会阻塞并等待Redis服务器处理Redis服务器处理完请求后会将结果通过响应报文返回给客户端。Redis的管道Pipeline可以一次性发送多条命令并在执行完后一次性将结果返回。管道可以减少客户端与Redis服务器的通信次数从而降低往返延时时间。管道实现的原理是队列而队列遵循先进先出原则这样就保证了数据的顺序性。Redis管道技术可以在Redis服务器启动时使用在Redis客户端向Redis服务器发送请求Request​并一次性读取所有Redis服务器的响应Response​。在Linux客户端新建脚本pipeline.sh。[rootlocalhost ~]# touch pipeline.sh使用vi命令修改pipeline.sh。[rootlocalhost ~]# vi pipeline.sh在pipeline.sh中添加以下内容脚本文件名为Redis\Chapter04\pipeline.sh。(echo-enPING\r\nSET db redis\r\nGET db\r\nSET visitor 0\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\nGET visitor\r\n;sleep10)|nclocalhost6379给pipeline.sh赋予可执行命令权限。[rootlocalhost ~]# chmod x pipeline.sh执行pipeline.sh。[rootlocalhost ~]# ./pipeline.sh得到以下内容。[rootlocalhost ~]# ./pipeline.shPONG OK$5redis OK :1 :2 :3$13以上实例中我们首先使用PING命令查看Redis服务器是否可用之后我们设置了db的值为redis并获取了db的值最后使visitor自增3次并获取了visitor的值。打开一个终端并使用redis-cli命令连接Redis服务器。127.0.0.1:6379GET visitor3127.0.0.1:6379GET dbredis从上面结果可以看出Redis数据库已经存储了db和visitor的值。5、数据备份与恢复5.1、数据备份Redis的SAVE命令用于创建当前数据库的快照文件。实例使用SAVE命令创建当前数据库的快照。127.0.0.1:6379SAVE OK该命令将在Redis安装目录中创建dump.rdb文件。5.2、数据恢复如果需要恢复数据只需将一台Redis服务器上的快照文件dump.rdb移动到另一台Redis服务器的安装目录并启动服务即可。获取Redis安装目录可以使用CONFIG命令如下所示。127.0.0.1:6379CONFIG GETdir1)dir2)/usr/local/redis/bin在本例中使用CONFIG GET dir命令输出的Redis安装目录为/usr/local/redis/bin。创建Redis备份文件也可以使用BGSAVE命令该命令在后台执行。127.0.0.1:6379BGSAVE Background saving started6、Redis性能测试Redis性能测试是通过同时执行多个命令实现的。Redis性能测试的基本命令如下。redis-benchmark[option][option value]实例同时执行10 000个请求来测试Redis的性能如图所示。Redis性能测试工具可选参数如图所示。实例使用多个参数来测试Redis性能。$ redis-benchmark-h127.0.0.1-p6379-tSET,LPSH-n10000-qSET:65789.48requests per second LPUSH:74074.07requests per second以上实例中连接Redis的主机IP地址为127.0.0.1端口为6379执行SET命令和LPUSH命令请求数为10000通过-q参数让结果只显示每秒执行的请求数。7、Redis客户端连接在Redis 2.4中最大连接数是被直接硬编码写在代码里面的而在Redis 2.6以后的版本中这个值变成可配置的。maxclients的默认值是10 000也可以在redis.conf配置文件中对这个值进行修改。127.0.0.1:6379CONFIG GET maxclients1)maxclients2)10000以下实例可以在Redis服务器启动时设置最大连接数为100 000。$ redis-server--maxclients100000Redis客户端查看客户端连接的命令及其描述如表所示。Redis客户端命令如图所示。8、Redis服务开机自启动每次启动Redis服务都需要使用redis-server命令稍显烦琐。当然也可以把redis-server命令放在启动脚本里每次运行脚本就可以启动Redis服务了。但有没有更好的方法让主机每次开机后就自动启动Redis服务呢8.1、Windows下Redis服务开机自启动可以把Redis设置成Windows服务这样Windows启动后就会自启动Redis服务和Windows服务一样可以启动/停止服务。1注册Redis为Windows后台服务在Redis的目录下执行以下命令执行后Redis就作为Windows后台服务了。redis-server --service-install redis.windows.conf如果执行命令成功会显示图所示页面。按“WinR”组合键执行services.msc命令就可以看到Redis已经作为Windows后台服务了。2启动Redis服务将Redis成功注册到Windows后台服务中后Redis并没有启动可以在Windows服务列表中启动Redis服务。启动Redis服务的命令如下。redis-server --service-start3停止Redis服务停止Redis服务的命令如下。redis-server --service-stop4卸载Redis服务卸载Redis服务的命令如下。redis-server --service-uninstall将Redis成功注册到Windows后台服务后就可以使用Windows命令启动/停止Redis服务如图所示。启动Redis服务。net start redis停止Redis服务。net stop redis8.2、Linux下Redis服务开机自启动1修改redis.conf配置文件为了让redis-server命令能在操作系统启动时自动执行需要将Redis服务作为守护进程Daemon来运行。我们回到/usr/local/redis/conf目录中找到redis.conf配置文件这个文件是Redis服务运行时加载的配置文件使用以下命令查看其中的内容。$vi/usr/local/redis/conf/redis.conf此文件内容非常多但是大部分内容是注释我们重点关注其中的两个配置项daemonize和pidfile。daemonize默认值是false表示Redis服务作为守护进程来运行需要把它改成daemonize yes。pidfile默认值是pidfile/var/run/redis_6379.pid表示当Redis服务以守护进程方式运行时Redis服务默认会把pid写入/var/run/redis_6379.pid文件Redis服务运行时该文件就存在Redis服务一旦停止该文件就会自动删除因而可以用来判断Redis服务是否正在运行。该配置项不用修改。为了让Redis能在Linux启动时自动运行需要修改完配置项daemonize后保存redis.conf配置文件然后退出文件。2修改初始化脚本redis_init_script有了基本配置Redis还需要有一个管理启动、关闭和重启的脚本。在Redis的源代码里已经提供了一个初始化脚本redis_init_script。这个初始化脚本的位置在%/redis-6.0.6/utils/目录下如图所示。redis_init_script脚本中指定了端口、Server路径、CLI路径、PIDFILE路径以及CONF路径。在安装时执行了makeinstall命令后这个脚本不需要做多大改动因为makeinstall命令会把Redis的可执行命令都复制到/usr/local/bin目录下。只需要修改CONF选项对应的Redis配置文件为Linux使用的redis.conf配置文件即可。在笔者的计算机上Redis配置文件保存在/usr/local/redis/conf/redis.conf目录下读者需要根据实际情况进行修改。修改后的redis_init_script脚本如图所示。3将redis_init_script脚本复制到/etc/init.d目录下并修改脚本名字为redis$cpredis_init_script /etc/init.d/redis给redis文件授予执行权限。$chmodx /etc/init.d/redis4开启服务自启动在/etc/init.d目录下的脚本都是可以在Linux启动时自动启动的服务还需要一个Linux启动时的配置。开启Redis服务自启动的命令如下。$chkconfigredis on5启动和停止Redis服务重启CentOS之后就可以执行以下命令启动和停止Redis服务了。启动Redis服务。$serviceredis start停止Redis服务。$serviceredis stop以上两个命令等价于以下命令。$/etc/init.d/redis start $/etc/init.d/redis stop9、Redis内存分析工具redis-rdb-tools是用Python编写的用来分析Redis的RDB快照文件的工具。在内存分析中我们主要用它生成内存报告。1安装redis-rdb-tools安装redis-rdb-tools前需要配置Python环境这部分的内容请参考11.7.2小节在Linux下安装Python 3。配置好Python环境后可以通过Python的pip来安装redis-rdb-tools。$ pip3installrdbtools python-lzf2生成内存报告使用redis-rdb-tools生成内存报告的实例如下。首先在Redis客户端生成两条String类型的数据如下所示。127.0.0.1:6379SET name xinping OK127.0.0.1:6379SET age25OK127.0.0.1:6379SAVE然后把Redis的RDB快照内存报告输出到控制台。$ rdb-cmemory /usr/local/redis/bin/dump.rdb database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry0,string,age,48,string,8,8,0,string,name,64,string,7,7,在生成的报告中有databasekey所在的Redis数据库编号​、typekey类型​、key键​、size_in_byteskey占用的内存大小​、encodingRDB编码方式​、num_elementskey中的value的个数​、len_largest_elementkey中的value的长度和expirykey的过期时间从返回的报告可以看出key为age的String类型数据占用了46个字节key为name的String类型数据占用了64个字节。也可以使用以下命令把Redis的内存报告生成为memory.csv文件并将文件输出到控制台。$ rdb-cmemory /usr/local/redis/bin/dump.rdbmemory.csv $catmemory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry0,string,age,48,string,8,8,0,string,name,64,string,7,7,