标签归档:redis

CentOS 7源码安装Redis 6.0及自启动

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。当下非常流行,使用非常广泛,这篇文章记录下CentOS 7源码安装Redis服务的方法。

安装Redis

先执行下面的命令,安装一大堆依赖:

#安装依赖
yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make
#升级gcc
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash

写这篇文章的时候,Redis最新稳定版为6.0,随着时间推移,版本会发生变化,请前往Redis官方:https://redis.io/download下载最新版本。

#下载Redis
wget https://download.redis.io/releases/redis-6.0.9.tar.gz
#解压Redis
tar xzf redis-6.0.9.tar.gz
#进入Redis目录
cd redis-6.0.9
#编译
make

编译成功后,Redis服务二进制文件位于src/redis-server,直接输入这个路径即可运行Redis服务,不过运行后是在前台运行,一旦结束或窗口关闭,Redis服务也随之停止。

运行Redis

为了方便后期管理与维护,可以将Redis src放到特定目录下,比如mv src/ /usr/local/redis

同时可以将redis-6.0.9目录下的redis.conf也复制一份:

cp redis.conf /etc

默认情况下,Redis是前台运行,如果需要后台运行,需要修改redis.conf配置文件,将

daemonize no

修改为:

daemonize yes

然后输入命令:/usr/local/redis/redis-server /etc/redis.conf重新启动Redis服务,这个时候就是保持后台运行了,通过ps命令可看到进程:

[root@hecs-centos-7 ~]# ps -ef|grep 'redis'
root     10217     1  0 22:00 ?        00:00:00 /usr/local/redis/redis-server 127.0.0.1:6379

设置环境变量

每次都输入Redis绝对路径来运行,难免还是有些不方便,我们可以将Redis路径加入到Linux环境变量,在/etc/profile这个文件底部追加:

export PATH=$PATH:/usr/local/redis

再输入命令source /etc/profile使其生效,这样我们就可以直接执行redis命令,而不用输入完整路径了。比如:

[root@hecs-centos-7 ~]# redis-server -v
Redis server v=6.0.9 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=ef93b08070de4db5

Redis客户端

通过上面编译后,Redis自带了一个命令行客户端redis-cli,输入下面的命令可检测Redis是否正常运行。

[root@hecs-centos-7 ~]# /usr/local/redis/redis-cli 
127.0.0.1:6379> ping
PONG

注册为Systemd服务

如果需要将Redis设置为开启启动,我们可以将redis注册为Systemd服务,方便日后管理。首先创建一个服务文件:vi /etc/systemd/system/redis.service,内容如下:

[Unit]
Description=Redis Server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/redis/redis-server /etc/redis.conf

[Install]
WantedBy=multi-user.target

然后输入systemctl daemon-reload重新加载服务,接下来就可以使用systemctl命令来管理了:

#启动redis
systemctl start redis
#停止redis
systemctl stop redis
#开机启动
systemctl enable redis

redis批量删除key 远程批量删除key

一、遇到的问题

  在开发的过程中,经常会遇到要批量删除某种规则的key,如缓存的课程数据“course-课程uid”,其中课程uid是变量,我们需要删除”course-*”这一类的数据,但是这里就坑了,redis有提供批量查询一类key的命令keys,但是没有提供批量删除某种类型key的命令。

二、解决方案

  先看看我们怎么解决。

1、先进入redis的客户端

cd redis所在目录/src
./redis-cli

2、初始化数据,模拟数据

复制代码
127.0.0.1:6379> set course-1 1
OK
127.0.0.1:6379> set course-2 2
OK
127.0.0.1:6379> set course-3 3
OK
复制代码

3、通过keys命令可以看到,现在有上面的三个key

127.0.0.1:6379> keys  course-*
1) "course-3"
2) "course-2"
3) "course-1"

4、退出redis的客户端

127.0.0.1:6379> exit

5.1、本地批量删除key

./redis-cli keys "course-*" | xargs ./redis-cli del

此处刚刚 course-*  相关的3个key已经被删除了

原理解析:

  先通过redis客户端执行了keys命令,模糊搜索出所有的key,通过xargs命令,将前面查询出来的key作为后面redis的del命令的输入

最终执行的结果可以理解成

 1、模糊查询

keys "course-*" 

  查询出上面的course-1 course-2 course-3 这三个key

2、执行删除key

  del的三个key来自前面的keys查询

del course-1 course-2  course-3    

5.2、远程批量删除key

  经常我们开发的时候,redis都是公用的,可能redis不在本地我们可以通过redis客户端远程进行删除

./redis-cli -h redis所在服务器ip -p 端口 keys "course-*" |xargs ./redis-cli -h redis所在服务器ip -p 端口 del

三、补充知识

1、远程某台机子的redis

  以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。

redis-cli -h 127.0.0.1 -p 6379 -a "mypass"

2、xargs命令

xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。 详情课件 http://man.linuxde.net/xargs

转自:https://www.cnblogs.com/0201zcr/p/9647787.html

Redis CPU使用率过高问题的排查

Redis CPU占用过高会导致所有使用Redis的客户端性能大幅下降,可能的原因中其中一个是大量的请求,尤其是keys命令请求过多,查询流程:

  1. 使用info和monitor命令(这两个命令也可以登录之后使用,不过有可能造成client的crash)

redis-cli -h 192.168.1.2  -a ‘passwd’ info 

Clients

connected_clients:25
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:1

Memory

used_memory:24022936
used_memory_human:22.91M
used_memory_rss:27422720
used_memory_rss_human:26.15M
used_memory_peak:76894968
used_memory_peak_human:73.33M
total_system_memory:33566736384
total_system_memory_human:31.26G
used_memory_lua:43008
used_memory_lua_human:42.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.14
mem_allocator:jemalloc-4.0.3

Persistence

loading:0
rdb_changes_since_last_save:3502
rdb_bgsave_in_progress:0
rdb_last_save_time:1575614696
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:8119852
total_commands_processed:287772910835
instantaneous_ops_per_sec:23686
total_net_input_bytes:8372810113180
total_net_output_bytes:1471697139442
instantaneous_input_kbps:676.85
instantaneous_output_kbps:129.54
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:158935
evicted_keys:0
keyspace_hits:188709502
keyspace_misses:6948953
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:823
migrate_cached_sockets:0

Replication

role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

CPU

used_cpu_sys:3372080.50
used_cpu_user:404838.31
used_cpu_sys_children:851.85
used_cpu_user_children:5934.84

Cluster

cluster_enabled:0

Keyspace

db0:keys=14078,expires=1209,avg_ttl=150542
db6:keys=878,expires=682,avg_ttl=42691293

redis-cli -h 192.168.1.2 -a ‘ passwd ‘ monitor 

info命令会显示当前的状态,monitor会显示当前的客户端的命令请求;

  1. 使用慢查询 

redis-cli -h 192.168.1.xx  -a ‘ passwd ‘ slowlog get (reset替换get清空旧的log)

这个命令会显示出最近一段时间内的耗时较久的查询。

这几个命令综合起来,基本可以找到是哪些命令频繁调用造成系统繁忙。

一般来说,都是大量调用keys命令并使用通配符造成的。

Redis服务器设置密码后,使用/etc/init.d/redis restart出现(error) NOAUTH Authentication required.

Redis服务器设置密码后,使用/etc/init.d/redis restart出现(error) NOAUTH Authentication required.

#/etc/init.d/redis restart

Stopping …

OK
(error) NOAUTH Authentication required.
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
出现这样的错误信息,redis 这时是没有停止服务的。

可以使用ps -ef | grep redis  查进程号 然后kill 掉,如果在deamon下还需要去删除pid文件,有点繁琐。

解决办法:

用redis-cli 密码登陆(redis-cli -a  password)就OK了。

再用ps -ef | grep redis 可以看到redis进程已经正常退出。

修改redis服务脚本,加入如下所示的红色授权信息即可:

vi /etc/init.d/redis
$CLIEXEC -a “password” -p $REDISPORT shutdown

systemctl管理双redis启动、停止、开机自动启动

systemctl管理双redis启动、停止、开机自动启动
1. 创建服务
用service来管理服务的时候,是在/etc/init.d/目录中创建一个脚本文件,来管理服务的启动和停止,在systemctl中,也类似,文件目录有所不同,在/lib/systemd/system目录下创建一个脚本文件redis_6379.service,里面的内容如下:

[Unit]
Description=Redis
After=network.target

[Service]
ExecStart=/usr/local/bin/redis-server /usr/local/redis/redis_6379.conf  –daemonize no
ExecStop=/usr/local/bin/redis-cli -h 127.0.0.1 -p 6379 shutdown

[Install]
WantedBy=multi-user.target
[Unit] 表示这是基础信息 
Description 是描述
After 是在那个服务后面启动,一般是网络服务启动后启动
[Service] 表示这里是服务信息 
ExecStart 是启动服务的命令
ExecStop 是停止服务的指令
[Install] 表示这是是安装相关信息 
WantedBy 是以哪种方式启动:multi-user.target表明当系统以多用户方式(默认的运行级别)启动时,这个服务需要被自动运行。
更详细的service文件说明请访问:这里

2. 创建软链接
创建软链接是为了下一步系统初始化时自动启动服务

ln -s /lib/systemd/system/redis_6379.service /etc/systemd/system/multi-user.target.wants/redis_6379.service
1
创建软链接就好比Windows下的快捷方式 
ln -s 是创建软链接 
ln -s 原文件 目标文件(快捷方式的决定地址)

如果创建软连接的时候出现异常,不要担心,看看/etc/systemd/system/multi-user.target.wants/ 目录是否正常创建软链接为准,有时候报错只是提示一下,其实成功了。

$ ll /etc/systemd/system/multi-user.target.wants/
total 8
drwxr-xr-x  2 root root 4096 Mar 30 15:46 ./
drwxr-xr-x 13 root root 4096 Mar 13 14:18 ../
lrwxrwxrwx  1 root root   31 Nov 23 14:43 redis_6379.service -> /lib/systemd/system/redis_6379.service
…略…

3. 刷新配置
刚刚配置的服务需要让systemctl能识别,就必须刷新配置

$ systemctl daemon-reload
如果没有权限可以使用sudo
$ sudo systemctl daemon-reload
4. 启动、重启、停止
启动redis

$ systemctl start redis_6379
重启redis

$ systemctl restart redis_6379 
停止redis

$ systemctl stop redis_6379
1
5. 开机自启动
redis服务加入开机启动

$ systemctl enable redis_6379
1
禁止开机启动

$ systemctl disable redis_6379
1
6. 查看状态
查看状态

$ systemctl status redis

● redis_6379.service – Redis
   Loaded: loaded (/usr/lib/systemd/system/redis_6379.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2018-11-12 14:32:32 CST; 2min 30s ago
  Process: 305 ExecStop=/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 shutdown (code=exited, status=0/SUCCESS)
 Main PID: 335 (redis-server)
   CGroup: /system.slice/redis_6379.service
           └─335 /usr/local/redis/bin/redis-server 127.0.0.1:6379

Nov 12 14:32:32 10-13-35-210 systemd[1]: Started Redis.
Nov 12 14:32:32 10-13-35-210 systemd[1]: Starting Redis…

其他端口,复制一份

redis_6379

重启redis时没有用root用户,结果dump.rdb文件停止更新,bgsave命令报错

原因:
1.dump.rdb文件所在的文件夹权限没有开通导致dump.rdb文件停止更新此时修改redis数据时会报错原因是默认配置 stop-writes-on-bgsaveerror yes当bgsave出错时数据将不能修改如下操作后可以更新数据: config set stop-writes-on-bgsaveerror nodump.rdb文件也恢复更新
2.当redis的内存占用比较大时在上述操作后dump.rdb文件仍然停止更新并且slave服务器也不能同步原因是操作系统的vm.overcommit_memory配置(配置说明在最后)如下操作:
echo 1 > /proc/sys/vm/overcommit_memory
后dump.rdb文件恢复更新。slave也可以同步数据了。
3.当使用root用户启动redis时没有上述问题

vm.overcommit_memory 表示内核在分配内存时候做检查的方式。这个变量可以取到0,1,2三个值。对取不同的值时的处理方式都定义在内核源码 mm/mmap.c 的 __vm_enough_memory 函数中。
取 1 的时候 : 此时宏为 OVERCOMMIT_ALWAYS函数直接 return 0分配成功。
取 2 的时候:  此时宏为 OVERCOMMIT_NEVER内核计算:内存总量×vm.overcommit_ratio/100+SWAP 的总量如果申请空间超过此数值则分配失败。vm.overcommit_ratio 的默认值为50。
取 0 的时候: 此时宏为 OVERCOMMIT_GUESS内核计算:NR_FILE_PAGES 总量+SWAP总量+slab中可以释放的内存总量如果申请空间超过此数值则将此数值与空闲内存总量减掉 totalreserve_pages(?) 的总量相加。如果申请空间依然超过此数值则分配失败。
以上为粗略描述在实际计算时如果非root进程则在计算时候会保留3%的空间而root进程则没有该限制。详细过程可看源码。

Redis Bgrewriteaof 命令 – 异步执行一个 AOF(AppendOnly File) 文件重写操作

Redis Bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。

即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。

注意:从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。

语法

redis Bgrewriteaof 命令基本语法如下:

	
  1. redis 127.0.0.1:6379> BGREWRITEAOF

可用版本

>= 1.0.0

返回值

反馈信息。

实例

	
  1. redis 127.0.0.1:6379>
  2. Background append only file rewriting started

Redis Save 与 BGSAVE 的区别

一,save保存数据到磁盘的方式:

Redis Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘。

语法
redis Save 命令基本语法如下:

redis 127.0.0.1:6379> SAVE

返回值

保存成功时返回 OK 。

 

二,BGSAVE保存数据到磁盘的方式:

BGSAVE 命令执行之后立即返回 OK ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。

客户端可以通过 LASTSAVE 命令查看相关信息,判断 BGSAVE 命令是否执行成功。

 

时间复杂度:

O(N), N 为要保存到数据库中的 key 的数量。

案例:

redis> BGSAVE
Background saving started

 

 

三,结论

SAVE  保存是阻塞主进程,客户端无法连接redis,等SAVE完成后,主进程才开始工作,客户端可以连接

BGSAVE  是fork一个save的子进程,在执行save过程中,不影响主进程,客户端可以正常链接redis,等子进程fork执行save完成后,通知主进程,子进程关闭。很明细BGSAVE方式比较适合线上的维护操作,两种方式的使用一定要了解清楚在谨慎选择。

1.Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。

 

2.Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。

 

3.Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。

下面是我的一个实际项目的情况,大概情况是这样的:一个Master,4个Slave,没有Sharding机制,仅是读写分离,Master负责写入操作和AOF日志备份,AOF文件大概5G,Slave负责读操作,当Master调用BGREWRITEAOF时,Master和Slave负载会突然陡增,Master的写入请求基本上都不响应了,持续了大概5分钟,Slave的读请求过也半无法及时响应,Master和Slave的服务器负载图如下:

 

Master Server load:

 

Slave server load: 

 

上面的情况本来不会也不应该发生的,是因为以前Master的这个机器是Slave,在上面有一个shell定时任务在每天的上午10点调用BGREWRITEAOF重写AOF文件,后来由于Master机器down了,就把备份的这个Slave切成Master了,但是这个定时任务忘记删除了,就导致了上面悲剧情况的发生,原因还是找了几天才找到的。

 

no-appendfsync-on-rewrite的配置设为yes可以缓解这个问题,设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入。最好是不开启Master的AOF备份功能。

 

4.Redis主从复制的性能问题,第一次Slave向Master同步的实现是:Slave向Master发出同步请求,Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的命令转发给Slave,初次同步完成。第二次以及以后的同步实现是:Master将变量的快照直接实时依次发送给各个Slave。不管什么原因导致Slave和Master断开重连都会重复以上过程。Redis的主从复制是建立在内存快照的持久化基础上,只要有Slave就一定会有内存快照发生。虽然Redis宣称主从复制无阻塞,但由于磁盘io的限制,如果Master快照文件比较大,那么dump会耗费比较长的时间,这个过程中Master可能无法响应请求,也就是说服务会中断,对于关键服务,这个后果也是很可怕的。

 

以上1.2.3.4根本问题的原因都离不开系统io瓶颈问题,也就是硬盘读写速度不够快,主进程 fsync()/write() 操作被阻塞。

 

5.单点故障问题,由于目前Redis的主从复制还不够成熟,所以存在明显的单点故障问题,这个目前只能自己做方案解决,如:主动复制,Proxy实现Slave对Master的替换等,这个也是Redis作者目前比较优先的任务之一,作者的解决方案思路简单优雅,详情可见
Redis Sentinel design draft http://redis.io/topics/sentinel-spec

 

总结:

1.Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。

2.如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。

3.为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。

4.尽量避免在压力较大的主库上增加从库

5.为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…….,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变。

php安装swoole扩展

swoole是一个PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。
Swoole内置了Http/WebSocket服务器端/客户端、Http2.0服务器端。
Swoole可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。 使用PHP+Swoole作为网络通信框架,可以使企业IT研发团队的效率大大提升,更加专注于开发创新产品。

注意事项:
1、server.php中的ip地址必须是外网可访问地址 123.57.232.99,不能为localhost

1、安装

# wget https://github.com/swoole/swoole-src/archive/swoole-1.7.6-stable.tar.gz

# tar zxvf swoole-1.7.6-stable.tar.gz

# cd swoole-src-swoole-1.7.6-stable

# /usr/local/php/bin/phpize

  1. #./configure  --enable-zip --with-php-config=/usr/local/php/bin/php-config 
  2. # make
  3. # make install

提示:
Build complete.
Don’t forget to run ‘make test’.

Installing shared extensions: /usr/lib64/php/modules/
说明安装成功

2、php加载swoole扩展

extension=/xxx/xxx/php5.6/lib/php/extensions/no-debug-non-zts-20131226/swoole.so

3、重启服务
service php-fpm restart

4、测试,查看phpinfo信息,如下图所示:

5、代码测试

server.php代码:

# telnet 123.57.232.99 55152 
  • 1

Trying 123.57.232.99…
Connected to 123.57.232.99.
Escape character is ‘^]’.
rr
Swoole: rr
测试
Swoole: 测试

官网方式参考(php7.2.19)使用了这个方式:

安装Swoole框架和扩展

Swoole扩展

到GitHub首页下载Swoole扩展源码,地址:https://github.com/swoole/swoole-src 下载后按照标准的PHP扩展编译方式进行编译和安装。一般是

phpize
./configure
make install 

编译安装完后,修改php.ini加入extension=swoole.so开启swoole扩展。也可以通过dl(‘swoole.so’)动态载入,推荐修改php.ini。


下载swoole_framework源码,地址:https://github.com/swoole/framework。放置到您的workspace目录中即可。swoole_framework是PHP代码,只需要require/include即可,无需编译和安装。

redis 3.2.10 安装和主从配置

1. 下载 redis

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

2. 解压

tar xzf redis-3.2.9.tar.gz

3. 进入 src 目录

cd redis-3.2.9

4. make

5. make test && make install

6. 如果出现 tcl 需要安装 yum -y install tcl

7. make install

8.注意 rdb 目录 和 save 配置 ,dir 目录指定文件存档目录, bind 指定ip

9. 修改密码 requirepass 修改

10. 指定启动目录 redis-server /etc/redis.conf

11. slave 机器安装 redis

12. slave 机器 redis.conf 修改 slaveof 和  masterauth

13. 重启

14. info 查看信息

master:

slave:


./redis-cli -p <修改的端口号> -a <修改的密码> shutdown