Redis

 ·  ☕ 23  · 👀...

介绍

技术 特性 适用场景 说明
Redis 并发:几万至十几万 - 官网
- Doc

常用命令

通用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 测试redis服务的可用性
$ ping 

# 获得Redis的所有配置
$ config get *

# 查看Redis服务器的统计信息
$ info

# 切换库
$ select db

# 删除当前库
$ flushdb

# 删除所有库
$ flushall

# 退出当前Redis连接
$ exit
$ quit

# 查看当前数据库中key的数据
$ dbsize

操作Key命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 列出所有key
# 注意:线上环境慎用
$ keys *

# 列出以xx开头的key
$ keys xx*

# 检查某个key是否存在
$ exists key

# 将当前库的key移动到给定的库中
$ move k1 2

# 设置key的值的过期时间
$ expire key seconds

# 查看key还有多少秒过期。
  # -1:永不过期
  # -2:已过期或key存在
$ ttl key

# 查看key所存储的值的类型
$ type key

# 删除key
$ del key

操作String命令

# 将字符串值value设置到key中
$ set key value

# 获得key的值
$ get key

# 将key中存储的数字值加1。
# 注意:只能对数字类型的数据操作。如果key不存在,则key的值先初始化为0,再执行incr操作。
$ incr key

# 将key中存储的数字值减1。
# 注意:只能对数字类型的数据操作。如果key不存在,则key的值先初始化为0,再执行incr操作。
$ decr key

# set expire的简写,设置key的值,并将key的生存时间设为seconds(以秒为单位)
$ setex key seconds value

# set if not exists的简写,如果key不存在,则set值,存在则不设置值
$ setnx key value

# 设置key的值为value,并返回key的旧值
$ getset key value 

# 返回key所存储的字符串值的长度
$ strlen

# 如果key存在且是字符串,则将value追加到key原来旧值的末尾。
# 如果key不存在,则将key值设置为value
$ append

# 将key所存储的值加上增量值,如果key不存在,则key的值先被初始化为0再执行incrby命令
$ incrby key increment

# 将key所存储的值减去增量值,如果key不存在,则key的值先被初始化为0再执行decrby命令
$ decrby

# 获取key中字符串值从start开始到end结束的子字符串
$ getrange key start end

# 从指定的位置开始将key的值替换为新的字符串,比如旧值helloworld,setrange key 5 redis,将从第5个下标位置往后开始替换为新的字符串redis,最终结果:helloredis
$ setrange key offset value

# 同时设置一个或多个key-value对
$ mset key value [key,value ...]

# 获取所有(一个或多个)给定key的值
$ mget key [key ...]

# 同时设置一个或多个key-value对,当且仅当所有给定key都不存在时才能设置成功,否则只要有一个key存在都会失败
$ msetnx

操作Hash命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 将哈希表key中的域filed的值设置为value
$ hset key field value

# 获取哈希表key中给定域field的值
$ hget key field

# 同时将多个field-value(域-值)对设置到哈希表key中
$ hmset

# 获取哈希表key中一个或多个给定域的值
$ hmget

# 获取哈希表key中所有的域和值
$ hgetall key

# 删除哈希表中一个或多个指定域field
$ hdel

# 查看哈希表key中的所有field域
$ hkeys key

# 查看哈希表key中所有域的值
$ hvals

# 获取哈希表key中域field的个数
$ hlen

# 查看哈希表key中,给定域field是否存在
$ hexists

# 为哈希表key中的域field的值加上增量increment
$ hincrby

# 为哈希表中的域field加上浮点数增量increment
$ hincrbyfloat
# 将哈希表key中的域field的值设置为value,当且仅当域field不存在的时候才设置,否则不设置
$ hsetnx

操作list命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 将一个或多个值value插入到列表key的表头(最左边)
$ lpush key value [value ...]

# 将一个或多个值value插入到列表key的表尾(最右边)
$ rpush

# 获取列表key中指定区间内的元素。
    # 0:表示列表的第一个元素
    # 1:表示列表的第二个元素
    # -1:表示列表的最后一个元素
    # -2:表示列表的倒数第二个元素
    # 一次类推
$ lrange

# 从左边获取列表key的一个元素,并将该元素移除
$ lpop

# 从右边获取列表key的一个元素,并将该元素移除
$ rpop

# 获取列表key中下标为指定index的元素
$ lindex

# 获取列表key的长度
$ llen

# 从左到右删除列表中指定个数的并与指定value值相等的value
$ lrem

# 删除指定区域外的元素,比如TRIM list 0 2,表示只保留列表list的前3个元素,其余元素全部删除
$ ltrim key start stop

# 将列表source中的最后一个元素(尾元素)弹出插入到列表destination,作为destination列表的头元素
$ rpoplpush

# 将列表key下标为index的元素的值设置为value
$ lset

# 将值value插入到列表key当中位于值pivot之前或之后的位置
$ linsert key BEFORE|AFTER pivot value

操作set命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 
$ sadd key member [member ...]

# 获取集合key中的所有成员元素
$ smembers

# 判断member元素是否是集合key的成员
$ sismember

# 获取集合里面的元素个数
$ scard

# 删除集合key中的一个或多个member元素
$ srem

# 随机返回集合中的一个元素
$ srandmember

# 随机从集合中删除一个元素
$ spop

# 将member元素从一个集合移动到另一个集合
$ smove

操作zset命令

# 将一个或多个member元素及其score值加入到有序集合key中
$ zadd key score value [score value ...]

# 删除有序集合key中的一个或多个成员
$ zrem

# 获取有序集合key的元素成员的个数
$ zcard

# 获取有序集合key中成员member的排名,有序集合成员按score值从小到大顺序排列
$ zrank

# 获取有序集合key中成员member的排名,有序集合成员按score值从大到小顺序排列
$ zrevrank

# 获取有序集合key中所有score值介于min和max之间的成员
$ zrangebyscore

# 获取有序集合key中所有score值介于max和min之间的所有成员
$ zrevrangebyscore

# 获取有序集合key中所有score值介于min和max之间的成员的个数
$ zcount

# 获取有序集合key中,指定区间内的成员,按score值从小到大排序
$ zrange key start stop [WITHSCORES]

# 获取有序集合key中,指定区间内的成员,按score值从大到小排序
$ zrevrange

开发

RedisTemplate

RedisTemplate介绍

spring 封装了 RedisTemplate 对象来进行对redis的各种操作,它支持所有的 redis 原生的 api。

RedisTemplate对数据结构操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
//操作字符串
redisTemplate.opsForValue();

//操作hash
redisTemplate.opsForHash();

//操作list
redisTemplate.opsForList();

//操作set
redisTemplate.opsForSet();

//操作有序set
redisTemplate.opsForZSet();

序列化策略

序列化策略 说明
JdkSerializationRedisSerializer POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。
是目前最常用的序列化策略。
StringRedisSerializer Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。
是最轻量级和高效的策略。
JacksonJsonRedisSerializer jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。
【需要jackson-mapper-asl工具支持】
OxmSerializer 提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。
【需要spring-oxm模块的支持】

RedisTemplate与StringRedisTemplate对比

比较项 说明
继承关系 StringRedisTemplate继承自RedisTemplate。
数据互通性 两者的数据是不共通的。
1. StringRedisTemplate只能管理StringRedisTemplate里面的数据
2. RedisTemplate只能管理RedisTemplate中的数据。
序列化策略 1. StringRedisTemplate默认采用的是String的序列化策略
2. RedisTemplate默认采用的是JDK的序列化策略。
使用场景 1. RedisTemplate使用的序列类在在操作数据的时候,比如说存入数据会将数据先序列化成字节数组,然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式。
2. 如果你的数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer而不是JdkSerializationRedisSerializer。
3. 当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可,但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。

总结

  1. 针对“序列化和发序列化”中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的策略,原则上,我们可以将数据存储为任何格式以便应用程序存取和解析(其中应用包括app,hadoop等其他工具),不过在设计时仍然不推荐直接使用“JacksonJsonRedisSerializer”和“OxmSerializer”,因为无论是json还是xml,他们本身仍然是String。

  2. 如果你的数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer而不是JdkSerializationRedisSerializer。

  3. 如果你的数据格式必须为json或者xml,那么在编程级别,在redisTemplate配置中仍然使用StringRedisSerializer,在存储之前或者读取之后,使用“SerializationUtils”工具转换转换成json或者xml。

Redis 执行 Lua

Redis执行Lua基本命令

命令 说明
EVAL 执行Lua脚本。
EVALSHA 执行Lua脚本的sha1。
SCRIPT FLUSH 清空Redis Script。
SCRIPT LOAD 将一个脚本装入脚本缓存,但并不立即运行它
SCRIPT EXISTS 根据给定的脚本校验和,检查指定的脚本是否存在于脚本缓存
SCRIPT KILL 杀死当前正在运行的脚本

Redis Lua scripts debugger

介绍

Redis 执行Lua脚本的过程

发送命令请求
          EVAL "return redis.call('DBSIZE')" 0
Caller ------------------------------------------> Redis

          为脚本 "return redis.call('DBSIZE')"
          创建 Lua 函数
Redis  ------------------------------------------> Lua

          绑定超时处理钩子
Redis  ------------------------------------------> Lua

          执行脚本函数
Redis  ------------------------------------------> Lua

               执行 redis.call('DBSIZE')
Fake Client <------------------------------------- Lua

               伪客户端向服务器发送
               DBSIZE 命令请求
Fake Client -------------------------------------> Redis

               服务器将 DBSIZE 的结果
               (Redis 回复)返回给伪客户端
Fake Client <------------------------------------- Redis

               将命令回复转换为 Lua 值
               并返回给 Lua 环境
Fake Client -------------------------------------> Lua

          返回函数执行结果(一个 Lua 值)
Redis  <------------------------------------------ Lua

          将 Lua 值转换为 Redis 回复
          并将该回复返回给客户端
Caller <------------------------------------------ Redis

开启调试会话

1
2
$ redis-cli --ldb --eval /tmp/script.lua
$ redis-cli --ldb --eval /tmp/script.lua mykey somekey , arg1 arg2

LDB 在默认情况下将使用子进程来创建调试会话, 并且在调试完成之后, 脚本对数据库进行的任何修改都将会被回滚。

开启同步模式

在一些特殊情况下, 为了追踪特定的 bug , 用户可以会想要保留每个调试会话对数据库所做的修改。 想要这么做的用户可以在启动调试器时, 向 redis-cli 客户端给定 ldb-sync-mode 选项:

1
$ redis-cli --ldb-sync-mode --eval /tmp/script.lua

错误处理

说明
redis.call() 当 redis.call() 在执行命令的过程中发生错误时,脚本会停止执行,并返回一个脚本错误,错误的输出信息会说明错误造成的原因。
redis.pcall() redis.pcall() 出错时并不引发(raise)错误,而是返回一个带 err 域的 Lua 表(table),用于表示错误

Redis使用Lua的注意事项

Redis使用Lua的注意事项 说明
不要使用全局变量 如果Lua脚本中包括全局变量时,会报错。定义变量时一定使用local关键字。
evalsha执行位置 一定要确保Lua脚本已经通过load script或eval加载或执行脚本之后再调用evalsha。
设定超时时间 在一主多从的环境中,一定要注意使用evalsha时,从服务有可能会出现未成功加载lua脚本的情况。
redis配置文件中一定要设置lua超时钩子lua-time-limit 5000。

运维

安装

程序说明

路径 说明
/usr/local/bin/redis-server Redis服务器
/usr/local/bin/redis-cli 命令行客户端
/usr/local/bin/redis-benchmark Redis的性能测试工具
/usr/local/bin/redis-check-aof AOF文件修复工具
/usr/local/bin/redis-check-dump RDB文件检测工具
/usr/local/bin/redis-sentinel 启动redis-sentinel
/usr/local/bin/redis.conf Redis的配置文件

安装步骤

1
2
3
4
5
6
7
> brew install redis
> redis-server
> brew services start redis
> brew services stop redis
> redis-server /usr/local/etc/redis.conf
> lsof -i tcp:6379
> redis-cli
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#### yum安装
> yum update
> yum install epel-release
> yum install redis
> systemctl start redis
> systemctl enable redis
> redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> 
#### 解压安装
> yum install gcc gcc-c++ -y
> cd /usr/local
> wget http://download.redis.io/releases/redis-5.0.5.tar.gz
> tar zxvf redis-5.0.5.tar.gz
> cd redis-5.0.5
> make
> make install
> ./utils/install_server.sh
> netstat -nltp|grep redis
> ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> 
#### 常用管理命令
> service redis_6379 start
> service redis_6379 stop
> service redis_6379 restart
> chkconfig redis_6379 on
> chkconfig redis_6379 off

默认配置如下:

配置项 配置值
Port 6379
Config file /etc/redis/6379.conf
Log file /var/log/redis_6379.log
Data dir /var/lib/redis/6379
Executable /usr/local/bin/redis-server
Cli Executable /usr/local/bin/redis-cli
1
2
3
> sudo apt-get update
> sudo apt-get install redis-server
> sudo /etc/init.d/redis-server start

配置

Redis配置文件样例

# Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
# 启用守护进程后,Redis会把pid写到一个pidfile中,在/var/run/redis.pid
daemonize no

# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid

# 指定Redis监听端口,默认端口为6379
# 如果指定0端口,表示Redis不监听TCP连接
port 6379

# 绑定的主机地址
# 你可以绑定单一接口,如果没有绑定,所有接口都会监听到来的连接
# bind 127.0.0.1

# 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 0

# 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
# debug (很多信息, 对开发/测试比较有用)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose

# 日志记录方式,默认为标准输出,如果配置为redis为守护进程方式运行,而这里又配置为标准输出,则日志将会发送给/dev/null
logfile stdout

# 设置数据库的数量,默认数据库为0,可以使用select <dbid>命令在连接上指定数据库id
# dbid是从0到‘databases’-1的数目
databases 16

################################ SNAPSHOTTING  #################################
# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   满足以下条件将会同步数据:
#   900秒(15分钟)内有1个更改
#   300秒(5分钟)内有10个更改
#   60秒内有10000个更改
#   Note: 可以把所有“save”行注释掉,这样就取消同步操作了

save 900 1
save 300 10
save 60 10000

# 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes

# 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb

# 工作目录.
# 指定本地数据库存放目录,文件名由上一个dbfilename配置项指定
# 
# Also the Append Only File will be created inside this directory.
# 
# 注意,这里只能指定一个目录,不能指定文件名
dir ./

################################# REPLICATION #################################
slave-serve-stale-data yes

# Slaves send PINGs to server in a predefined interval. It's possible to change
# this interval with the repl_ping_slave_period option. The default value is 10
# seconds.
#
# repl-ping-slave-period 10

# The following option sets a timeout for both Bulk transfer I/O timeout and
# master data or ping response timeout. The default value is 60 seconds.
#
# It is important to make sure that this value is greater than the value
# specified for repl-ping-slave-period otherwise a timeout will be detected
# every time there is low traffic between the master and the slave.
#
# repl-timeout 60

############################## APPEND ONLY MODE ###############################

# 
# Note that you can have both the async dumps and the append only file if you
# like (you have to comment the "save" statements above to disable the dumps).
# Still if append only mode is enabled Redis will load the data from the
# log file at startup ignoring the dump.rdb file.
# 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。
# 因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
# log file in background when it gets too big.

appendonly no

# 指定更新日志条件,共有3个可选值:
# no:表示等操作系统进行数据缓存同步到磁盘(快)
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折衷,默认值)

appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

################################## SLOW LOG ###################################
slowlog-max-len 1024

################################ VIRTUAL MEMORY ###############################

# 把vm-enabled设置为yes,根据需要设置好接下来的三个VM参数,就可以启动VM了
vm-enabled no

# Redis交换文件最好的存储是SSD(固态硬盘)
# 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
# *** WARNING *** if you are using a shared hosting the default of putting
# the swap file under /tmp is not secure. Create a dir with access granted
# only to Redis user and configure Redis to create the swap file there.
vm-swap-file /tmp/redis.swap

# With vm-max-memory 0 the system will swap everything it can. Not a good
# default, just specify the max amount of RAM you can in bytes, but it's
# better to leave some margin. For instance specify an amount of RAM
# that's more or less between 60 and 80% of your free RAM.
# 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多少,所有索引数据都是内存存储的(Redis的索引数据就是keys)
# 也就是说当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0

# Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的数据大小来设定的。
# 建议如果存储很多小对象,page大小最后设置为32或64bytes;如果存储很大的对象,则可以使用更大的page,如果不确定,就使用默认值
vm-page-size 32

# 设置swap文件中的page数量由于页表(一种表示页面空闲或使用的bitmap)是存放在内存中的,在磁盘上每8个pages将消耗1byte的内存
# swap空间总容量为 vm-page-size * vm-pages
vm-pages 134217728

# 设置访问swap文件的I/O线程数,最后不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟,默认值为4
vm-max-threads 4

############################### ADVANCED CONFIG ###############################
# 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 512
hash-max-zipmap-value 64

list-max-ziplist-entries 512
list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# 指定是否激活重置哈希,默认为开启
activerehashing yes

配置RDB持久化

################################ 快照  #################################  
#  
# Save the DB on disk:保存数据库到磁盘  
#  
#   save <秒> <更新>  
#  
#   如果指定的秒数和数据库写操作次数都满足了就将数据库保存。  
#  
#   下面是保存操作的实例:  
#   900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)  
#   300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)  
#   60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)  
#  
#   注释:注释掉“save”这一行配置项就可以让保存数据库功能失效。  
#  
#   你也可以通过增加一个只有一个空字符串的配置项(如下面的实例)来去掉前面的“save”配置。  
#  
#   save ""  

# 作用:15分钟内至少有一个键被更改
save 900 1

# 作用:5分钟内至少有10个键被更改
save 300 10

# 作用:1分钟内至少有10000个键被更改
save 60 10000

# rdb文件存储路径
dir ./  

# rdb文件名  
dbfilename dump.rdb  


  
#在默认情况下,如果RDB快照持久化操作被激活(至少一个条件被激活)并且持久化操作失败,Redis则会停止接受更新操作。  
#这样会让用户了解到数据没有被正确的存储到磁盘上。否则没人会注意到这个问题,可能会造成灾难。  
#  
#如果后台存储(持久化)操作进程再次工作,Redis会自动允许更新操作。  
#  
#然而,如果你已经恰当的配置了对Redis服务器的监视和备份,你也许想关掉这项功能。  
#如此一来即使后台保存操作出错,redis也仍然可以继续像平常一样工作。  
stop-writes-on-bgsave-error yes  
  
#是否在导出.rdb数据库文件的时候采用LZF压缩字符串和对象?  
#默认情况下总是设置成‘yes’, 他看起来是一把双刃剑。  
#如果你想在存储的子进程中节省一些CPU就设置成'no',  
#但是这样如果你的kye/value是可压缩的,你的到处数据接就会很大。  
rdbcompression yes  
  
#从版本RDB版本5开始,一个CRC64的校验就被放在了文件末尾。  
#这会让格式更加耐攻击,但是当存储或者加载rbd文件的时候会有一个10%左右的性能下降,  
#所以,为了达到性能的最大化,你可以关掉这个配置项。  
#  
#没有校验的RDB文件会有一个0校验位,来告诉加载代码跳过校验检查。  
rdbchecksum yes   

配置AOF持久化

# 作用:是否开启AOF
# 默认值:关闭(no)
appendonly yes

# 设置AOF持久化策略
# 可选值:
    # always:每次都同步(最安全但是最慢,不推荐)
    # everysec:每秒同步(默认的同步策略,推荐)
    # no:不主动同步,由操作系统来决定(最快但是不安全,不推荐)
appendfsync everysec

# 指定 AOF 文件名  
appendfilename appendonly.aof 

# 作用:在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
# 默认值:no
# 可选项:  
    # yes:表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no  
no-appendfsync-on-rewrite no   
  
# 作用:当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。  
auto-aof-rewrite-percentage 100  
  
# 作用:当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。  
auto-aof-rewrite-min-size 64mb

配置登陆密码

requirepass 密码

配置允许远程访问

  • 将bind 127.0.0.1注释掉,或修改成允许访问的远程机器的ip地址。
  • 在redis3.2之后,redis增加了protected-mode,将 protected-mode yes 修改为 protected-mode no

配置后端模式启动

daemonize yes

系统调优

方法1:立即生效

1
$ sysctl vm.overcommit_memory=1

方法2:重启生效

1
$ vi /etc/sysctl.config

增加如下配置:

vm.overcommit_memory = 1

管理Redis

查看Redis版本

1
$ redis-cli --version

查看Redis的信息和状态

1
> info

查看Redis是否在运行

1
> ping

如果返回PONG,则说明Redis正在运行。
或者

1
$ ps -ef |grep redis

将Redis做成服务

启动脚本在cd /usr/local/redis/utils/redis_init_script,根据启动脚本要求,需要将改好的配置文件复制一份到指定目录,不过这一步可以省略,系统安装时已经自动帮我们做了。

1
2
$ mkdir /etc/redis
$ cp redis.conf /etc/redis/6379.conf

将启动脚本复制到/etc/init.d目录

1
2
$ cd /usr/local/redis/utils/
$ cp redis_init_script /etc/init.d/redisd

在启动脚本开头加入注视,修改启动脚本的运行级别

1
$ vi /etc/init.d/redisd

修改如下:

1
2
3
4
#!/bin/sh
# chkconfig:    2345 90 10

# description:  Redis is a persistent key-value database

启动Redis

1
2
$ cd /usr/local/bin
$ ./redis-server &   #加上“&”表示以后台服务运行。

1
$ redis-server ./redis.conf   #这种方式可以为Redis指定配置文件运行。
1
$ service redisd start  #需要将Redis做成服务才可执行此命令。

停止Redis

1
$ redis-cli shutdown

或者

1
$ service redisd stop  #需要将Redis做成服务才可执行此命令。

开机启动

1
$ chkconfig redisd on  #需要将Redis做成服务才可执行此命令。

取消开机启动

1
$ chkconfig redisd off  #需要将Redis做成服务才可执行此命令。

取消开机启动

1
$ chkconfig redisd off

连接 Redis

1
2
$ redis-cli -h 127.0.0.1 -p 6379
$ auth "password"

备份

1
2
3
127.0.0.1:6379> SAVE
# 获取redis的安装目录
127.0.0.1:6379> CONFIG GET dir

备份完成后会在安装目录下(默认/var/lib/redis/)创建dump.rdb文件

恢复

将备份文件(dump.rdb)移动到redis安装目录,并启动redis服务即可,redis会自动加载并恢复dumop.rdb中的数据。

使用Redis-Dump备份数据

Mac 中安装Redis-Dump

安装RVM

1
2
3
4
5
6
$ curl -L get.rvm.io | bash -s stable
$ source ~/.bashrc
$ source ~/.bash_profile
$ rvm -v
# 列出已知ruby的版本
$ rvm list known

安装 Ryby2.2.4

1
2
$ rvm install 2.2.4
$ ryby -v

安装 Redis-Dump

1
$ gem install redis-dump

导出数据

1
$ redis-dump -u ip:port -a 'password' -d 0 > redisA.json 

导入数据

1
$ cat redisA.json | redis-load -u 127.0.0.1:6379 -a 'pwssword'

图形客户端

Ubuntu中安装redis-desktop-manager

1
$ sudo snap install redis-desktop-manager

Redis监控

Monitor

1
$ redis-cli monitor

RedisMonitor

试用了一下,就是一个空的东西,什么都没有,什么功能也没有。

安装redis-monitor 1.0.3

1
2
3
4
5
$ pip install redis-monitor
$ redis-monitor init
$ redis-monitor createdb
$ redis-monitor start
$ curl http://localhost:9527

性能优化

修改Linux内存分配策略

1
2
3
4
5
$ vi /etc/sysctl.conf
# 添加如下内容,并重启:
vm.overcommit_memory = 1
# 或者(立即生效)
$ sysctl vm.overcommit_memory=1
overcommit_memory 说明
0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1 不管需要多少内存,都允许申请。
2 只允许分配物理内存和交换内存的大小。(交换内存一般是物理内存的一半)

关闭Transparent Huge Pages(THP)

THP会造成内存锁影响redis性能,建议关闭。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ vi /etc/rc.local
# 添加如下内容:
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
 echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
 echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
# 给rc.local添加可执行权限
$ chmod +x /etc/rc.d/rc.local

修改linux中TCP 监听的最大容纳数量

在高并发环境下你需要一个高backlog值来避免慢客户端连接问题。
注意Linux内核默默地将这个值减小到/proc/sys/net/core/somaxconn的值,所以需要确认增大somaxconn和tcp_max_syn_backlog两个值来达到想要的效果。
如果想限制redis的最大连接数需要修改maxclients,默认最大连接数为10000。

限制Redis的内存大小

标题 说明
限制Redis的内存大小 如果不限制内存,当物理内存使用完之后,会使用swap分区,这样性能较低,如果限制了内存,当到达指定内存之后就不能添加数据了,否则会报OOM错误。可以设置maxmemory-policy,内存不足时删除数据。
知识点 - 通过redis的info命令查看内存使用情况
- 如果不设置maxmemory或者设置为0,64位系统不限制内存,32位系统最多使用3GB内存。

修改配置文件

maxmemory:最大内存
maxmemory-policy:内存不足时,数据清除策略

使用管道进行批量化操作

Redis是个单线程模型,客户端过来的命令是按照顺序执行的,所以想要一次添加多条数据的时候可以使用管道,或者使用一次可以添加多条数据的命令。

降低Redis的内存占用

降低Redis的内存占用事项 说明
短结构 Redis为列表、集合、散列和有序集合提供了一组配置选项,这些选项可以让Redis以更节约空间的方式存储长度较短的结构。
分片结构 分片(sharding)是一种广为人知的技术,它基于某些简单的规则将数据分为更小的部分,然后根据数据所属的部分来决定将数据发送到哪个位置上面。
打包存储二进制位和字节 如果被存储的是一些简短并且长度固定的连续ID,那么还有比使用分片散列更为节约内存的数据存储方法可用,这时可以将数据打包存储在字符串键里面。

性能测试

可选参数

说明 默认值
-h 指定服务器主机名 127.0.0.1
-p 指定服务器端口 6379
-s 指定服务器 socket
-c 指定并发连接数 50
-n 指定请求数 10000
-d 以字节的形式指定 SET/GET 值的数据大小 2
-k 1=keep alive 0=reconnect 1
-r SET/GET/INCR 使用随机 key, SADD 使用随机值
-P 通过管道传输 请求 1
-q 强制退出 redis。仅显示 query/sec 值
–csv 以 CSV 格式输出
-l 生成循环,永久执行测试
-t 仅运行以逗号分隔的测试命令列表。
-I Idle 模式。仅打开 N 个 idle 连接并等待。

示例

1
2
3
4
5
6
7
8
9
# 语法(该命令是在 redis 的目录下执行的,而不是 redis 客户端的内部指令。)
$ redis-benchmark [option] [option value]

# 示例:同时执行 10000 个请求来检测性能
$ redis-benchmark -n 10000  -q

# 示例2:主机为 127.0.0.1,端口号为 6379,执行的命令为 set,lpush,请求数为 10000,
## 通过 -q 参数让结果只显示每秒执行的请求数。
$ redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q

Wanglibing
Wanglibing
Engineer,Lifelong learner