1.redis是什么?
Redis:是一个非关系型(NoSql:Not Only SQL)的内存数据库。它具备一定持久层功能,但通常做为缓存工具。
2.redis如何使用?
2.1redis安装及文件简介
2.1.1linux下安装
(1)这里我们只介绍linux下的安装.需要注意的是redis的安装依赖gcc,所以我们首先安装gcc.
yum install gcc-c++
(2)下载redis压缩包
wget http://download.redis.io/releases/redis-5.0.5.tar.gz
如需下载其他版本将后面的5.0.5换为对应版本号即可
(3)解压
tar -zxvf redis-5.0.5.tar.gz
(4)编译
进入解压后的redis目录:cd redis-5.0.5
我们可以看到一个Makefile文件,使用make PREFIX=/usr/local/redis install进行安装,PREFIX=/usr/local/redis表示设置PREFIX的值,实际效果就是将redis安装到/usr/local/redis,在该目录下我们可以看到bin目录,这里面就是redis常用的命令了。
(5)赋值配置文件
将/redis-5.0.5目录下的redis.conf配置文件复制到我们刚刚安装redis的目录
cp /redis-5.0.5/redis.conf /usr/local/redis ,为什么要复制能,因为我们后期使用redis主要就是对该文件的操作,这里保留一份原始的配置,修改报错后还可以恢复。
(6)启动关闭redis服务
redis分为服务端和客户端,进入刚安装的redis目录cd /usr/local/redis,还记刚说的bin目录么?该目录下就是redis常用的命令
我们使用./bin/redis-server ./redis.conf来启动redis服务端。./为当前目录。后面的./redis.conf表示使用当前目录的redis.conf配置文件来启动redis。
使用./bin/redis-cli命令(没错,使用当前目录中bin目录下的redis-cli命令)可以进入redis的命令行客户端。使用shutdown关闭redis服务端,然后使用quit命令退出客户端。当然我们也可以使用./bin/redis-cli shutdown来直接关闭,避免进入客户端。
2.2redis数据类型及使用场景
这是redis官网对于数据类型的介绍,二进制安全的字符串(redis分为Binary-safe strings)、列表(Lists)、集合(Sets)、有序集合(Sorted sets)、哈希集合(Hashes)、位数组(Bit arrays)、
基数(HyperLogLogs)、流(Streams)。下面我们使用命令行客户端(redis-cli)一一介绍数据类型相关命令,及该数据类型使用场景。
2.2.1字符串类型
字符串是Redis最基本的数据结构,它将以一个键和一个值存储于 Redis 内部.
命 令 |
说 明 |
备 注 |
set key value |
设置键值对 |
最常用的写入命令 |
get key |
通过键获取值 |
最常用的读取命令 |
del key |
通过 key,删除键值对 |
删除命令,返冋删除数,注意,它是个通用的命令,换句话说在其他数据结构中,也可以使用它 |
strlen key |
求 key 指向字符串的长度 |
返回长度 |
getset key value |
修改原来 key 的对应值,并将旧值返回 |
如果原来值为空,则返回为空,并设置新值 |
getrange key start end |
获取子串 |
记字符串的长度为 len,把字符串看作一个数组,而 Redis 是以 0 开始计数的,所以 start 和 end 的取值范围 为 0 到 len-1 |
append key value |
将新的字符串 value,加入到原来 key 指向的字符串末 |
Redis 除了这些之外还提供了对整数和浮点型数字的功能。如果字符串是数字(整数或者浮点数),那么 Redis 还能支持简单的运算。不过它的运算能力比较弱,目前版本只能支持简单的加减法运算。我们可以用来实现计数。
命 令 |
说 明 |
备 注 |
incr key |
在原字段上加 1 |
只能对整数操作 |
incrby key increment |
在原字段上加上整数(increment) |
只能对整数操作 |
decr key |
在原字段上减 1 |
只能对整数操作 |
decrby key decrement |
在原字段上减去整数(decrement) |
只能对整数操作 |
incrbyfloat keyincrement |
在原字段上加上浮点数(increment) |
可以操作浮点数或者整 |
2.2.2链表类型
Redis链表是双向的,因此即可以从左到右,也可以从右到左遍历它存储的节点,结构如下图所示。
根据链表的特性我们可以知道,插入/删除数据方便,只需要修改节点的引用即可,但是增加了查找的时间。 Redis中我们可以使用链表实现消息队列。
命 令 |
说 明 |
备 注 |
lpush key node1 [node2.]..... |
把节点 node1 加入到链表最左边 |
如果是 node1、node2 ...noden 这样加入, 那么链表开头从左到右的顺序是 noden...node2、node1 |
rpush key node1[node2]...... |
把节点 node1 加入到链表的最右边 |
如果是 node1、node2....noden 这样加 入,那么链表结尾从左到右的顺序是 node1、node2,node3...noden |
lindex key index |
读取下标为 index 的节点 |
返回节点字符串,从 0 开始算 |
llen key |
求链表的长度 |
返回链表节点数 |
lpop key |
删除左边第一个节点,并将其返回 |
—— |
rpop key |
删除右边第一个节点,并将其返回 |
—— |
linsert key before|after pivot node |
插入一个节点 node,并且可以指定在值为pivot 的节点的前面(before)或者后面(after)) |
如果 list 不存在,则报错;如果没有值为对应 pivot 的,也会插入失败返回 -1 |
lpushx list node |
如果存在 key 为 list 的链表,则插入节点 node, 并且作为从左到右的第一个节点 |
如果 list 不存在,则失败 |
rpushx list node |
如果存在 key 为 list 的链表,则插入节点 node,并且作为从左到右的最后个节点 |
如果 list 不存在,则失败 |
lrange list start end |
获取链表 list 从 start 下标到 end 下标的节点值 |
包含 start 和 end 下标的值 |
lrem list count value |
如果 count 为 0,则删除所有值等于 value 的节 点:如果 count 不是 0,则先对 count 取绝对值,假设记为 abs,然后从左到右删除不大于 abs 个等于 value 的节点 |
注意,count 为整数,如果是负数,则 Redis 会先求取其绝对值,然后传递到后台操作 |
lset key index node |
设置列表下标为 index 的节点的值为 node |
—— |
ltrim key start stop |
修剪链表,只保留从 start 到 stop 的区间的节点,其余的都删除掉 |
包含 start 和 end 的下标的节点会保留 |
需要注意的是,我们需要考虑插入与删除内容的大小,这将是什么消耗性能。
需要指出的是,之前这些操作链表的命令都是进程不安全的,因为当我们操作这些命令的时候,其他 Redis 的客户端也可能操作同一个链表,这样就会造成并发数据安全和一致性的问题,尤其是当你操作一个数据量不小的链表结构时,常常会遇到这样的问题。
为了克服这些问题,Redis 提供了链表的阻塞命令,它们在运行的时候,会给链表加锁,以保证操作链表的命令安全性。当使用这些命令时,Redis 就会对对应的链表加锁,加锁的结果就是其他的进程不能再读取或者写入该链表,只能等待命令结束。加锁的好处可以保证在多线程并发环境中数据的一致性,保证一些重要数据的一致性,比如账户的金额、商品的数量。
不过在保证这些的同时也要付出其他线程等待、线程环境切换等代价,这将使得系统的并发能力下降,
命 令 |
说 明 |
备 注 |
blpop key timeout |
移出并获取列表的第一个元索,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元索为止 |
相对于 lpop 命令,它的操作是进程安全的 |
brpop key timeout |
移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
相对于 rpop 命令,它的操作是进程安全的 |
rpoplpush key sre dest |
按从左到右的顺序,将一个链表的最后一个元素移除,并插入到目标链表最左边 |
不能设置超时时间 |
brpoplpush key src dest timeout |
按从左到右的顺序,将一个链表的最后一个元素移除,并插入到目标链表最左边,并可以设置超时时间 |
可设置超时时间 |
2.2.3集合类型
Redis 的集合不是一个线性结构,而是一个哈希表结构,它的内部会根据 hash 分子来存储和查找数据,理论上一个集合可以存储 2 的 32 次方减 1 个节点(大约 42 亿)个元素,因为采用哈希表结构,所以对于 Redis 集合的插入、删除和查找的复杂度都是 0(1),只是我们需要注意 3 点。
- 对于集合而言,它的每一个元素都是不能重复的,当插入相同记录的时候都会失败。
- 集合是无序的。
- 集合的每一个元素都是 String 数据结构类型。
我们可以利用集合的交、并、差集等特性来进行数据区分,如获取两个人共同的好友,获取两个人共同好友,然后求交集即可。
命 令 |
说 明 |
备 注 |
sadd key member1 [member2 member3......] |
给键为 key 的集合増加成员 |
可以同时増加多个 |
scard key |
统计键为 key 的集合成员数 |
— |
sdiffkey1 [key2] |
找出两个集合的差集 |
参数如果是单key,那么 Redis 就返回这个 key 的所有元素 |
sdiftstore des key1 [key2] |
先按 sdiff 命令的规则,找出 key1 和 key2 两 个集合的差集,然后将其保存到 des 集合中。 |
— |
sinter key1 [key2] |
求 key1 和 key2 两个集合的交集。 |
参数如果是单 key,那么 Redis 就返冋这个 key 的所有元素 |
sinterstore des key1 key2 |
先按 sinter 命令的规则,找出 key1 和 key2 两个集合的交集,然后保存到 des 中 |
— |
sismember key member |
判断 member 是否键为 key 的集合的成员 |
如果是返回 1,否则返回 0 |
smembers key |
返回集合所有成员 |
如果数据量大,需要考虑迭代遍历的问题 |
smove src des member |
将成员 member 从集合 src 迁移到集合 des 中 |
— |
spop key |
随机弹出集合的一个元素 |
注意其随机性,因为集合是无序的 |
srandmember key [count] |
随机返回集合中一个或者多个元素,count 为限制返回总数,如果 count 为负数,则先求其绝对值 |
count 为整数,如果不填默认为 1,如果 count 大于等于集合总数,则返回整个集合 |
srem key member1[member2......] |
移除集合中的元素,可以是多个元素 |
对于很大的集合可以通过它删除部分元素,避免删除大量数据引发 Redis 停顿 |
sunion key1 [key2] |
求两个集合的并集 |
参数如果是单 key,那么 Redis 就返回这个 key 的所有元素 |
sunionstore des key1 key2 |
先执行 sunion 命令求出并集,然后保存到键为 des 的集合中 |
— |
2.2.4有序类型
有序集合是在无序集合上增加一个分数(浮点数类型)来实现的。
应用场景,比如根据好友的“亲密度”排序显示好友列表。
命 令 |
说 明 |
备 注 |
zadd key score1 value1 [score2 value2......] |
向有序集合的 key,增加一个或者多个成员 |
如果不存在对应的 key,则创建键为 key 的有序集合 |
zcard key |
获取有序集合的成员数 |
— |
zcount key min max |
根据分数返回对应的成员列表 |
min 为最小值,max 为最大值,默认为包含 min 和 max 值,采用数学区间表示的方法,如果需要不包含,则在分数前面加入“(”,注意不支持“[”表示 |
zincrby key increment member |
给有序集合成员值为 member 的分数增加 increment |
— |
zinterstore desKey numkeys key1 [key2 key3......] |
求多个有序集合的交集,并且将结果保存到 desKey 中 |
numkeys 是一个整数,表示多少个有序集合 |
zlexcount key min max |
求有序集合 key 成员值在 min 和 max 的范围 |
这里范围为 key 的成员值,Redis 借助数据区间的表示方法,“[”表示包含该值,“(”表示不包含该值 |
zrange key start stop [withscores] |
按照分值的大小(从小到大)返回成员,加入 start 和 stop 参数可以截取某一段返回。如果输入可选项 withscores,则连同分数一起返回 |
这里记集合最人长度为 len,则 Redis 会将集合排序后,形成一个从 0 到 len-1 的下标,然后根据 start 和 stop 控制的下标(包含 start 和 stop)返回 |
zrank key member |
按从小到大求有序集合的排行 |
排名第一的为 0,第二的为 1…… |
zrangebylex key min max [limit offset count] |
根据值的大小,从小到大排序,min 为最小值,max 为最大值;limit 选项可选,当 Redis 求出范围集合后,会生产下标 0 到 n,然后根据偏移量 offset 和限定返回数 count,返回对应的成员 |
这里范围为 key 的成员值,Redis 借助数学区间的表示方法,“[”表示包含该值,“(”表示不包含该值 |
zrangebyscore key min max [withscores] [limit offset count] |
根据分数大小,从小到大求取范围,选项 withscores 和 limit 请参考 zrange 命令和 zrangebylex 说明 |
根据分析求取集合的范围。这里默认包含 min 和 max,如果不想包含,则在参数前加入“(”, 注意不支持“[”表示 |
zremrangebyscore key start stop |
根据分数区间进行删除 |
按照 socre 进行排序,然后排除 0 到 len-1 的下标,然后根据 start 和 stop 进行删除,Redis 借助数学区间的表示方法,“[”表示包含该值,“(” 表示不包含该值 |
zremrangebyrank key start stop |
按照分数排行从小到大的排序删除,从 0 开始计算 |
— |
zremrangebylex key min max |
按照值的分布进行删除 |
— |
zrevrange key start stop [withscores] |
从大到小的按分数排序,参数请参见 zrange |
与 zrange 相同,只是排序是从大到小 |
zrevrangebyscore key max min [withscores] |
从大到小的按分数排序,参数请参见 zrangebyscore |
与 zrangebyscore 相同,只是排序是从大到小 |
zrevrank key member |
按从大到小的顺序,求元素的排行 |
排名第一位 0,第二位 1...... |
zscore key member |
返回成员的分数值 |
返回成员的分数 |
zunionstore desKey numKeys key1 [key2 key3 key4......] |
求多个有序集合的并集,其中 numKeys 是有序集合的个数 |
—— |
2.2.5哈希类型
Redis中的哈希结构如同Java的Map一样,它特别适合存储对象,一个hash结构可以存储232-1(约40多亿)个键值对。假设有个角色表(role)有三个字段id、name、age。我们可以使用hmset role id 001 name sevensun age 18来实现数据在Redis的哈希存储。hmset是哈希存储的命令,role为key,通过key我们可以找到对应的hash结构,而redis中hash结构由一系列的field和value组成,格式为field value。下图演示了hash结构的存储与获取。
命 令 |
说 明 |
备 注 |
hdel key field1[field2......] |
删除 hash 结构中的某个(些)字段 |
可以进行多个字段的删除 |
hexists key field |
判断 hash 结构中是否存在 field 字段 |
存在返回 1,否则返回 0 |
hgetall key |
获取所有 hash 结构中的键值 |
返回键和值 |
hincrby key field increment |
指定给 hash 结构中的某一字段加上一个整数 |
要求该字段也是整数字符串 |
hincrbyfloat key field increment |
指定给 hash 结构中的某一字段加上一个浮点数 |
要求该字段是数字型字符串 |
hkeys key |
返回 hash 中所有的键 |
—— |
hlen key |
返回 hash 中键值对的数量 |
—— |
hmget key field1[field2......] |
返回 hash 中指定的键的值,可以是多个 |
依次返回值 |
hmset key field1 value1 [field2 field2......] |
hash 结构设置多个键值对 |
—— |
hset key filed value |
在 hash 结构中设置键值对 |
单个设值 |
hsetnx key field value |
当 hash 结构中不存在对应的键,才设置值 |
—— |
hvals key |
获取 hash 结构中所有的值 |
—— |
在使用大的 hash 结构时,需要考虑返回数据的大小,以避免返回太多的数据,引发 JVM 内存溢出或者 Redis 的性能问题。
2.2.6位数组类型
2.2.7基数类型
2.2.7流类型
2.3redis数据配置文件(redis.conf)介绍
key |
value |
description |
daemonize |
默认no,需改为yes |
yes表示redis-server后台运行,除非手动kill掉 |
pidfile |
/var/run/redis.pid |
当redis以守护进程方式运行时,redis默认会把pid写入/var/run/redis.pid文件, |
port |
6379 |
redis监听端口 |
bind |
127.0.0.1 |
用于指定本机网卡对应的IP地址,一般注释即可 |
timeout |
300 |
当客户端闲置多长时间后关闭连接,如果指定为0,表示永不关闭 |
tcp-keepalive |
0 |
设置检测客户端网络中断时间间隔,单位为秒,如果设置为0,则不检测,建议设置为60 |
save |
300 10 |
表示300秒内有10个更改就将数据同步到数据文件 |
rdbcompssion |
yes |
指定存储至本地数据库时是否压缩数据,默认为yes,redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变得巨大: |
dir |
./ |
指定本地数据库存放目录 |
masterauth |
<master-password> |
当master服务设置了密码保护时,slave服务连接master的密码: |
requirepass |
foobared |
设置redis连接密码,如果配置了连接密码,客户端在连接redis时需要通过auth <password>命令提供密码,默认关闭: |
maxclients |
128 |
设置同一时间最大客户端连接数,默认无限制,redis可以同时打开的客户端连接数为redis进程可以打开的最大文件描述符数,如果设置maxclients 0,表示不作限制。当客 户端连接数到达限制时,redis会关闭新的连接并向客户端返回 max number of clients reached错误消息: |
maxmemory |
128 |
指定redis最大内存限制,redis在启动时会把数据加载到内存中,达到最大内存后,redis会先尝试清除已到期或即将到期的key,当次方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制, 会把key存放内存,value会存放在swap区: |
maxmemory-policy |
volatile-lru:使用LRU算法移除key,只对设置了过期时间的key; allkeys-lru:使用LRU算法移除key,作用对象所有key; volatile-random:在过期集合key中随机移除key,只对设置了过期时间的key; allkeys-random:随机移除key,作用对象为所有key; volarile-ttl:移除哪些ttl值最小即最近要过期的key; noeviction:永不过期,针对写操作,会返回错误信息。 |
|
appendonly |
no |
指定是否在每次更新操作后进行日志记录,redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内置存在于内存中。默认为no: |
slaveof |
<masterip><masterport> |
设置当本机为slave服务时,设置master服务的IP地址及端口,在redis启动时,它会自动从master进行数据同步: |
2.4redis持久化
2.4.1RDB:持久化配置
#时间策略,900秒内若有一条写命令则触发一次快照(即备份). #save save 900 1 save 300 10 save 60 10000 #快照文件名称 dbfilename dump.rdb #快照文件存放路径,./表示当前路径 dir ./ #如果持久化出错,主进程是否停止写入 #这是当备份进程出错时,主进程就停止接受新的写入操作,是为了保护持久化的数据一致性问题。 #如果自己的业务有完善的监控系统,可以禁止此项配置, 否则请开启。 stop-writes-on-bgsave-error yes #是否压缩 #建议没有必要开启,毕竟Redis本身就属于CPU密集型服务器,再开启压缩会带来更多的CPU消耗, #相比硬盘成本,CPU更值钱 rdbcomproession yes #导入时是否检查 rdbchecksum yes |
2.4.2AOF持久化配置
#是否开启aof appendonly yes #aof快照文件名称 appendfilename 'appendonly.aof' #同步方式 #把每个写命令都立即同步到aof,很慢,但是很安全 #appendfsync always #每秒同步一次,是折中方案,兼顾速度与安全,最多丢失一秒数据 appendfsync everysec #redis不处理交给OS来处理,非常快,但是也最不安全 #appendfsync no #aop重写期间是否同步 no-appendfsync-on-rewrite no # 重写触发配置 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 加载aof时如果有错如何处理,如果设置为no,发生错误会立即停止,必须修复后才可继续执行 aof-load-truncated yes # 文件重写策略 aof-rewrite-incremental-fsync yes |
3.4.3持久化实现原理
(1)RDB持久化分为手动和定时触发两种。
save命令时:
2.5redis事物
2.6redis主从复制
3.redis案例
4.redis面试
5.redis与其他缓存技术比较
参考
1.Redis是什么