Redis是NoSQL中比较常典型的一个非关系型数据库,在日常工作中也是最为常见的。Redis是一个由C语言编写的开源的、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

https://db-engines.com/en/ranking
一、安装及启动Redis
由于我们日常中最多使用redis的环境是在linux中,所以这里主要来看linux下的安装方法。
1、下载并安装Redis
我们可以使用wget下载,也可以将redis的包下载下来并且导入到linux中
1$ wget http://download.redis.io/releases/redis-2.8.17.tar.gz 2$ yum install gcc tcl -y 3$ tar xzf redis-2.8.8.tar.gz 4$ cd redis-4.0.8 5$ make 6$ mkdir /usr/local/redis 7$ make install PREFIX=/usr/local/redis
2、启动redis
./redis-server
默认启动redis使用的是默认配置,端口号为6379,密码为空。如果需要后台启动的话,可以使用nohup来启动。
nohup redis-server &
当然,如果需要指定redis的配置文件,那我们可以在启动命令中指定好配置文件就可以。
nohup redis-server /usr/local/redis/redis.conf &
3、停止redis
redis-cli shutdown
4、redis配置
1# Protected mode is a layer of security protection, in order to avoid that 2# Redis instances left open on the internet are accessed and exploited. 3# 4# When protected mode is on and if: 5# 6# 1) The server is not binding explicitly to a set of addresses using the 7# "bind" directive. 8# 2) No password is configured. 9# 10# The server only accepts connections from clients connecting from the 11# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain 12# sockets. 13# 14# By default protected mode is enabled. You should disable it only if 15# you are sure you want clients from other hosts to connect to Redis 16# even if no authentication is configured, nor a specific set of interfaces 17# are explicitly listed using the "bind" directive. 18protected-mode yes 19 20# Accept connections on the specified port, default is 6379 (IANA #815344). 21# If port 0 is specified Redis will not listen on a TCP socket. 22port 6379 23 24# Unix socket. 25# 26# Specify the path for the Unix socket that will be used to listen for 27# incoming connections. There is no default, so Redis will not listen 28# on a unix socket when not specified. 29# 30# unixsocket /tmp/redis.sock 31# unixsocketperm 700 32 33# Close the connection after a client is idle for N seconds (0 to disable) 34timeout 0 35 36# TCP keepalive. 37# 38# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence 39# of communication. This is useful for two reasons: 40# 41# 1) Detect dead peers. 42# 2) Take the connection alive from the point of view of network 43# equipment in the middle. 44# 45# On Linux, the specified value (in seconds) is the period used to send ACKs. 46# Note that to close the connection the double of the time is needed. 47# On other kernels the period depends on the kernel configuration. 48# 49# A reasonable value for this option is 300 seconds, which is the new 50# Redis default starting with Redis 3.2.1. 51tcp-keepalive 300 52 53# By default Redis does not run as a daemon. Use 'yes' if you need it. 54# Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 55# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. 56# 启用守护进程后,Redis会把pid写到一个pidfile中,在/var/run/redis.pid 57daemonize yes 58 59# Set the number of databases. The default database is DB 0, you can select 60# a different one on a per-connection basis using SELECT <dbid> where 61# dbid is a number between 0 and 'databases'-1 62databases 16 63 64################################ SNAPSHOTTING ################################ 65# 66# Save the DB on disk: 67# 68# save <seconds> <changes> 69# 70# Will save the DB if both the given number of seconds and the given 71# number of write operations against the DB occurred. 72# 73# In the example below the behaviour will be to save: 74# after 900 sec (15 min) if at least 1 key changed 75# after 300 sec (5 min) if at least 10 keys changed 76# after 60 sec if at least 10000 keys changed 77# 78# Note: you can disable saving completely by commenting out all "save" lines. 79# 80# It is also possible to remove all the previously configured save 81# points by adding a save directive with a single empty string argument 82# like in the following example: 83# 84# save "" 85 86save 900 1 87save 300 10 88save 60 10000 89 90 91# Compress string objects using LZF when dump .rdb databases? 92# For default that's set to 'yes' as it's almost always a win. 93# If you want to save some CPU in the saving child set it to 'no' but 94# the dataset will likely be bigger if you have compressible values or keys. 95rdbcompression yes 96 97# The filename where to dump the DB 98dbfilename dump.rdb 99 100# The working directory. 101# 102# The DB will be written inside this directory, with the filename specified 103# above using the 'dbfilename' configuration directive. 104# 105# The Append Only File will also be created inside this directory. 106# 107# Note that you must specify a directory here, not a file name. 108dir ./
5、连接redis
远程连接redis,可以使用redis自带的工具redis-cli,具体使用方法如下:
1redis-cli -h 127.0.0.1 -p 6379 -n 0 2 3 -h <hostname> Server hostname (default: 127.0.0.1). 4 -p <port> Server port (default: 6379). 5 -a <password> Password to use when connecting to the server. 6 --help 显示帮助信息 7 8切换数据库: 9select 0 10select 10
6、redis常用命令
Redis 是一个高性能的key-value数据库,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。不过既然redis是一个数据库,那么也就逃脱不开增删改查的操作,接下来把每种数据类型常用的增删改查命令列举一次。
如果对某个命令不知道该如何使用的时候可以使用–help来查询如:
1help set 2 3 DEL key [key ...] 4 summary: Delete a key 5 since: 1.0.0 6 group: generic 7 KEYS pattern 8 summary: Find all keys matching the given pattern 9 since: 1.0.0 10 group: generic 11 12 RENAME key newkey 13 summary: Rename a key 14 since: 1.0.0 15 group: generic 16 17 MOVE key db 18 summary: Move a key to another database 19 since: 1.0.0 20 group: generic 21 22 EXPIRE key seconds 23 summary: Set a key's time to live in seconds 24 since: 1.0.0 25 group: generic 26 27 EXISTS key [key ...] 28 summary: Determine if a key exists 29 since: 1.0.0 30 group: generic
(1)String(字符串)
redis中最简单的数据类型,可以存储文字、数字、浮点数还可以进行二进制的存储,value存储最大数据量为512M。
1APPEND 2 APPEND key value 3 summary: Append a value to a key 4 since: 2.0.0 5 group: string 6在一个key的值后面追加上value内容 7 8GET 9 GET key 10 summary: Get the value of a key 11 since: 1.0.0 12 group: string 13获取key的值 14 15GETRANGE 16 GETRANGE key start end 17 summary: Get a substring of the string stored at a key 18 since: 2.4.0 19 group: string 20获取key值的切片 从start开始到end结束 21 22GETSET 23 GETSET key value 24 summary: Set the string value of a key and return its old value 25 since: 1.0.0 26 group: string 27将value作为key的值写入,并将key的旧值返回 28 29INCR 30 INCR key 31 summary: Increment the integer value of a key by one 32 since: 1.0.0 33 group: string 34给key的int值加1,如果这个key没有存在,则会先初始化一个0,然后再加1 35 36INCRBY 37 INCRBY key increment 38 summary: Increment the integer value of a key by the given amount 39 since: 1.0.0 40 group: string 41将 key所储存的值加上增量 increment,如果key的值不是int类型,则报错 42 43MGET 44 MGET key [key ...] 45 summary: Get the values of all the given keys 46 since: 1.0.0 47 group: string 48同时获取多个key 49 50MSET 51 MSET key value [key value ...] 52 summary: Set multiple keys to multiple values 53 since: 1.0.1 54 group: string 55同时写入多个key 56 57MSETNX 58 MSETNX key value [key value ...] 59 summary: Set multiple keys to multiple values, only if none of the keys exist 60 since: 1.0.1 61 group: string 62只有在key不存在的时候才可以同时写入多个key值 63 64PSETEX 65 PSETEX key milliseconds value 66 summary: Set the value and expiration in milliseconds of a key 67 since: 2.6.0 68 group: string 69写入一个值,但是只有设置的毫秒的有效期,超过后会被删除 70 71SET 72 SET key value [EX seconds] [PX milliseconds] [NX|XX] 73 summary: Set the string value of a key 74 since: 1.0.0 75 group: string 76写入一个值 77SETEX 78 SETEX key seconds value 79 summary: Set the value and expiration of a key 80 since: 2.0.0 81 group: string 82写入一个值,并且有设置的有效期 83 84SETNX 85 SETNX key value 86 summary: Set the value of a key, only if the key does not exist 87 since: 1.0.0 88 group: string 89将 key 的值设为value,当且仅当key不存在 90SETRANGE 91 SETRANGE key offset value 92 summary: Overwrite part of a string at key starting at the specified offset 93 since: 2.2.0 94 group: string 95用value参数覆写(overwrite)给定key所储存的字符串值,从偏移量offset开始。 96STRLEN 97 STRLEN key 98 summary: Get the length of the value stored in a key 99 since: 2.2.0 100 group: string 101返回key所储存的字符串值的长度。
(2)Hash(哈希)
hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。Redis 中每个 hash 可以存储 232 – 1 键值对(40多亿)。
1HDEL 2 HDEL key field [field ...] 3 summary: Delete one or more hash fields 4 since: 2.0.0 5 group: hash 6删除哈希表key中的一个或多个指定域,不存在的域将被忽略。 7 8HEXISTS 9 HEXISTS key field 10 summary: Determine if a hash field exists 11 since: 2.0.0 12 group: hash 13判断哈希表key中的field是否存在 14 15HGET 16 HGET key field 17 summary: Get the value of a hash field 18 since: 2.0.0 19 group: hash 20获取哈希表key中的field 21 22HGETALL 23 HGETALL key 24 summary: Get all the fields and values in a hash 25 since: 2.0.0 26 group: hash 27获取哈希表key中的所有域和值 28 29HINCRBY 30 HINCRBY key field increment 31 summary: Increment the integer value of a hash field by the given number 32 since: 2.0.0 33 group: hash 34为哈希表key中的域field的值加上增量increment。 35 36HKEYS 37 HKEYS key 38 summary: Get all the fields in a hash 39 since: 2.0.0 40 group: hash 41返回哈希表key中的所有域。 42 43HLEN 44 HLEN key 45 summary: Get the number of fields in a hash 46 since: 2.0.0 47 group: hash 48返回哈希表key中域的数量。 49 50HMGET 51 HMGET key field [field ...] 52 summary: Get the values of all the given hash fields 53 since: 2.0.0 54 group: hash 55返回哈希表key中,一个或多个给定域的值。 56 57HMSET 58 HMSET key field value [field value ...] 59 summary: Set multiple hash fields to multiple values 60 since: 2.0.0 61 group: hash 62同时将多个field-value(域-值)对设置到哈希表key中。 63 64HSET 65 HSET key field value 66 summary: Set the string value of a hash field 67 since: 2.0.0 68 group: hash 69将哈希表key中的域field的值设为value 70 71HSETNX 72 HSETNX key field value 73 summary: Set the value of a hash field, only if the field does not exist 74 since: 2.0.0 75 group: hash 76将哈希表key中的域field的值设置为value,当且仅当域field不存在。 77 78HVALS 79 HVALS key 80 summary: Get all the values in a hash 81 since: 2.0.0 82 group: hash 83返回哈希表key中所有的域
7、监控redis
-
图形化监控工具:TreeSoft
-
命令行监控:
- 吞吐量
- Redis提供的INFO命令不仅能够查看实时的吞吐量(ops/sec),还能看到一些有用的运行时信息。下面用grep过滤出一些比较重要的实时信息,比如已连接的和在阻塞的客户端、已用内存、拒绝连接、实时的tps和数据流量等:
[root@liml redis]# /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456 info |
grep -e "connected_clients" -e "blocked_clients" -e "used_memory_human" -e "used_memory_peak_human" -e "rejected_connections" -e "evicted_keys" -e "instantaneous" connected_clients:3 #连接数 blocked_clients:0 #阻塞连接数 used_memory_human:3.37M # redis占用内存 used_memory_peak_human:3.37M #redis占用内存峰值 instantaneous_ops_per_sec:192 #每秒处理请求数 instantaneous_input_kbps:11.82 #每秒读字节数 instantaneous_output_kbps:0.75 #每秒写字节数 rejected_connections:0 #拒绝连接数 evicted_keys:0 #运行以来删除的key数量
- 吞吐量
-
- 延迟
- 监控redis的延迟可以使用redis提供的ping命令来不断的ping服务器,并且记录服务器响应ping的时间。
[root@liml ~]# /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456 --latency min: 0, max: 1, avg: 0.08 (284 samples)
[root@liml ~]# /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456
127.0.0.1:6380> monitor 1522663856.563254 [0 127.0.0.1:34881] "PING" 1522663856.573585 [0 127.0.0.1:34881] "PING" 1522663856.583894 [0 127.0.0.1:34881] "PING" 1522663856.686623 [0 127.0.0.1:34881] "PING" 1522663856.696851 [0 127.0.0.1:34881] "PING" 1522663856.707109 [0 127.0.0.1:34881] "PING" - 延迟
-
- 持续实时监控
- 持续监控redis使用的是linux自带的watch命令和我们前面监控命令结合到一起就可以变成持续的实时监控工具了。
先将前面的命令保存到一个shell脚本中,
vi testredis.sh #!/bin/bash /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456 info | grep -e "connected_clients" -e "blocked_clients" -e "used_memory_human" -e "used_memory_peak_human" -e "rejected_connections" -e "evicted_keys" -e "instantaneous"
#保存后并给予执行的权限 chmod 755 testredis.sh
使用watch命令实时监控
watch -n 1 -d "/usr/local/redis/testredis.sh"
- 持续实时监控
-
- 慢操作日志
- SORT、LREM、SUNION等操作在大对象上会非常耗时,使用时要注意参照官方API上每个命令的算法复杂度。和主流数据库提供的慢SQL日志一样,Redis也提供了记录慢操作的日志。注意这部分日志只会计算纯粹的操作耗时。
- 慢操作日志
8、压力测试redis
redis-benchmark
默认情况下面,基准测试使用单一的 key。在一个基于内存的数据库里, 单一 key 测试和真实情况下面不会有巨大变化。当然,使用一个大的 key 范围空间, 可以模拟现实情况下面的缓存不命中情况。
这时候我们可以使用 -r 命令。比如,假设我们想设置 10 万随机 key 连续 SET 100 万次,我们可以使用下列的命令:
1./redis-benchmark -p 6380 -a 123456 -t set -n 1000 -r 10 2====== set -n 1 -r 1000 ====== 3 100000 requests completed in 1.24 seconds 4 50 parallel clients 5 3 bytes payload 6 keep alive: 1 7 899.88% <= 1 milliseconds 999.89% <= 2 milliseconds 1099.90% <= 3 milliseconds 1199.95% <= 5 milliseconds 12100.00% <= 5 milliseconds 1380450.52 requests per second
有几个因素直接决定 Redis 的性能。它们能够改变基准测试的结果, 所以我们必须注意到它们。一般情况下,Redis 默认参数已经可以提供足够的性能, 不需要调优。
- 网络带宽和延迟通常是最大短板。建议在基准测试之前使用 ping 来检查服务端到客户端的延迟。根据带宽,可以计算出最大吞吐量。 比如将 4 KB 的字符串塞入 Redis,吞吐量是 100000 q/s,那么实际需要 3.2 Gbits/s 的带宽,所以需要 10 GBits/s 网络连接, 1 Gbits/s 是不够的。 在很多线上服务中,Redis 吞吐会先被网络带宽限制住,而不是 CPU。 为了达到高吞吐量突破 TCP/IP 限制,最后采用 10 Gbits/s 的网卡, 或者多个 1 Gbits/s 网卡。
- CPU 是另外一个重要的影响因素,由于是单线程模型,Redis 更喜欢大缓存快速 CPU, 而不是多核。这种场景下面,比较推荐 Intel CPU。AMD CPU 可能只有 Intel CPU 的一半性能(通过对 Nehalem EP/Westmere EP/Sandy 平台的对比)。 当其他条件相当时候,CPU 就成了 redis-benchmark 的限制因素。
- 在小对象存取时候,内存速度和带宽看上去不是很重要,但是对大对象(> 10 KB), 它就变得重要起来。不过通常情况下面,倒不至于为了优化 Redis 而购买更高性能的内存模块。
- Redis 在 VM 上会变慢。虚拟化对普通操作会有额外的消耗,Redis 对系统调用和网络终端不会有太多的 overhead。建议把 Redis 运行在物理机器上, 特别是当你很在意延迟时候。在最先进的虚拟化设备(VMWare)上面,redis-benchmark 的测试结果比物理机器上慢了一倍,很多 CPU 时间被消费在系统调用和中断上面。