1. Redis 简介
Redis是一个开源的 key-value 存储系统。和 Memecached 类似,它支持存储的value 类型相对更多,包括 string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove 及交集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis 支持各种不同方式的排序。与 memcached一样,为了保证效率,数据都是缓存在内存中。区别是 Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave(主从)同步。
1.1 应用场景
1.1.1 配合关系型数据库做高速缓存
- 高频次,热门访问的数据,降低数据库IO
- 分布式架构,做 session 共享
1.1.2 由于其拥有持久化能力,利用其多样的数据结构存储特定的数据
安装部分,虚拟机之前装过,应该是被我删掉了, 建议看下我之前写的
Windows下Redies安装并设置成本地服务。主要是阿里云的yum源一直有问题。本地的也还可以,能用就行。
2. 相关知识
Redis是单线程+多路IO复用技术
多路复用是指使用一个线程来检查多个文件描述(Socket)的就绪状态,比如调用 select 和 poll 函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)。
串行 vs 多线程+锁(memcached)vs 单线程+多路IO复用(Redis)
例子:
阻塞IO,给女神发一条短信,说我来找你了,然后就默默的一直等着女神下楼,这个期间除了等待你不会做其他事情,属于备胎做法。
非阻塞IO,给女神发短信,如果不回,接着再发,一直发到女神下楼,这个期间你除了发短信等待不会做其他事情,属于专一做法。
IO多路复用,是找一个宿管大妈来帮你监视下楼的女生,这个期间你可以做些其他事情。IO复用又包括 select,poll,epoll 模式。
- select 大妈,每一个女生下楼,select大妈都不知道这个是不是你的女神,她需要一个一个询问,并且 select大妈能力还有限,最多一次帮你监视1024个妹子。
- poll 大妈不限制等着女生的数量,只要是经过宿舍楼门口的女生,都会帮你去问是不是你女神。
- epoll 大妈不限制盯着女生的数量,并且也不需要一个个去问,那么如何做呢?epoll 大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字,只要女生下楼了,epoll 大妈就知道这个是不是你女神了,然后大妈再通知你。
3. Redis 数据类型
基本指令
指令 | 功能 |
keys * | 查看当前库的所有键 |
exists <key> | 判断某个键是否存在 |
type <key> | 查看键的类型 |
del <key> | 删除某个键 |
expire <key> <seconds> | 为键值设置过期时间,单位秒 |
ttl <key> | 查看还有多少秒过期,-1 表示用不过期,-2 表示已过期 |
dbsize | 查看当前数据库的key的数量 |
Flushdb | 清空当前库 |
Flushall | 通杀全部库 |
3.1 String
String 是 Redis 最基本的类型,你可以理解成语 Memacched 一模一样的类型,一个key对应一个value。
String 类型是二进制安全的。意味着Redis的String可以包含任何数据。比如jpg图片或者序列化的对象。
String 类型是 Redis最基本的数据类型,一个Redis中字符串value最多可以是512M。
指令 | 功能 |
get <key> | 查询对应键值 |
set <key> <value> | 添加键值对 |
append <key> <value> | 将给定的<value>追加到原值的末尾 |
strlen <key> | 获得值的长度 |
setnx <key> <value> | 只有在 key 不存在时,设置 key 的值 |
incr <key> | - 将key中存储的数字值增1;- 只能对数字值操作,如果为空,新增值为1(对存储在指定 key的数值执行原子的加1操作。) |
decr <key> | - 将 key中储存数值值减1;- 只能对数字值操作,如果为空,新增值为-1 |
incrby / decrby <key> <步长> | 将 key 中储存的数字值增减。自定义步长。 |
mset <key1> <value1> <key2> <value2> …… | 同时设置一个或多个 key-value 对 |
mget <key1> <key2> <key3> ...... | 同时获取一个或多个 value |
msetnx <key1> <value1> <key2> <value2> ...... | 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。 |
getrange <key> <起始位置> <结束位置> | 获得值的范围,类似 java 中的 subsring |
setrange <key> <起始位置> <value> | 用 <value> 覆写 <key> 所储存的字符串值,从 <起始位置> 开始。 |
setex <key> <过期时间> <value> | 设置键值的同时,设置过期时间,单位秒 |
getset <key> <value> | 以新换旧,设置了新值同时获得旧值 |
3.1.1 原子性
- 所谓原子性操作是指不会被线程调度机制打断的操作;这种操作一旦开始就一直运行到结束,中间不会有任何 context switch(切换到另一个线程)。
(1)在单线程中,能够在单条指令中完成的操作都可以认为是"原子操作",因为中断只能发生于指令之间。
(2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
Redis单命令的原子性主要得益于 Redis的单线程
3.2 List
单键多值
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。
它的底层实际是个 双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
指令 | 功能 |
Ipush/rpush <key> <value1> <value2> | 从左边/右边插入一个或多个值 |
Inpop/rpop <key> | 从左边/右边吐出一个值。值在键在,值光键忘 |
rpoplpush <key1> <key2> | 从 <key1> 列表右边吐出一个值,插到<key2>列表左边 |
range <key> <start> <stop> | 按照索引下标获得元素(从左到右) |
linde <key> <index> | 按照索引下标获得元素(从左到右) |
llen <key> | 获得列表长度 |
linsert <key> after <value> <newvalue> | 在 <value> 的后面插入 <newvalue> 插入值 |
lrem <key> <n> <value> | 从左边删除n个value(从左到右) |
3.3 Set
Redis set对外提供的功能与List类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是list所不能提供的。
- Redis 的 Set 是 string 类型的无序集合。它底层其实是一个 value 为 null 的 hash表,所以添加,删除,查找的复杂度都是 O(1)。
指令 | 功能 |
sadd <key> <value1> <value2> ...... | 将一个或多个 member 元素加入到集合 key。已经存在于集合的 member 元素将被忽略。 |
smembers <key> | 取出该集合的所有值。 |
sismember <key> <value> | 判断集合 <key> 是否为含有该 <value> 值,有返回 1,没有返回 0。 |
scard <key> | 返回该集合的元素个数。 |
srem <key> <value1> <value2> | 删除集合中的某个元素。 |
spop <key> | 随机从该集合中吐出一个值。会从集合中删除。 |
srandmember <key> <n> | 随机从该集合中取出 n 个值。不会从集合中删除。 |
sinter <key1> <key2> | 返回两个集合的交集元素。 |
sunion <key1> <key2> | 返回两个集合的并集元素。 |
sdiff <key1> <key2> | 返回两个集合的差集元素。 |
3.4 Hash
- Redis hash 是一个键值对集合。
- Redis hash 是一个 String 类型的 field 和 value 的映射表,hash特别适合用于存储对象。
- 类似 Java 里面的 Map<String,String>
指令 | 功能 |
hset <key> <field> <value> | 给 <key> 集合中的 <field> 键赋值 <value> |
hget <key1> <field> | 从 <key1> 集合 <field> 取出 value |
hmset <key1> <field1> <value1> | 批量设置 hash 的值 |
hexists key <field> | 查看哈希表 key 中,给定域 field 是否存在。 |
hkey <key> | 列出该 hash 集合的所有 field |
hvals <key> | 列出该 hash 集合的所有 value |
hincrby <key> <field> <increment> | 为哈希表 key 中的域 field 的值加上增量 increment |
hsetnx <key> <field> <value> | 为哈希表 key 中的域 field 的值设置为 value,当且仅当域 field 不存在。 |
#中文乱码解决方法
redis-cli.exe --raw
3.5 Zset(sorted set)
Redis 有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了。
因为元素是有序的,所以你可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
指令 | 功能 |
zadd <key> <score1> <value1> | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
zcard key | 获取有序集合的成员数 |
zcount key min max | 计算在有序集合中指定区间分数的成员数 |
zincrby key increment member | 有序集合中对指定成员的分数加上增量 increment |
zinterstore destination numkeys key [key...] | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 destination 中 |
zlexcount key min max | 在有序集合中计算指定字典区间内成员数量 |
zrange key start stop [withscores] | 通过索引区间返回有序集合指定区间内的成员 |
zrangebyscore key min max [limit offset count] | 通过字典区间返回有序集合的成员 |
zrangebyscore key min max [withscores] [limit] | 通过分数返回有序集合指定区间内的成员 |
zrevrange key member | 返回有序集合中指定成员的索引 |
zrem key member [member...] | 移除有序集合中的一个或多个成员 |
zremrangebylex key min max | 移除有序集合中给定的字典区间的所有成员 |
zremrangebyrank key strat stop | 移除有序集合中给定的排名区间的所有成员 |
zremrangebyscore key min max | 移除有序集合中给定的分数区间的所有成员 |
zrevrange key start stop [withscores] | 返回有序集中指定区间内的成员,通过索引,分数从高到低 |
zrevrangebyscore key max min [withscores] | 返回有序集中指定分数区间内的成员,分数从高到低排序 |
zrevrank key member | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
zscore key member | 返回有序集中,成员的分数值 |
zunionstore destination numkeys key [key...] | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
zscan key cursor [match pattern] [count count] | 迭代有序集合中的元素(包括元素成员和元素分值) |
4. Redis 配置文件
Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf
(Windows 名为redis windows.conf)。
#通过命令查看或设置配置项
redis 127.0.0.1:6379> CONFIG GET *
#编辑配置
redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
OK
redis 127.0.0.1:6379> CONFIG GET loglevel
1) "loglevel"
2) "notice"
配置项 | 说明 |
include /path/to/local.conf | 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件。 |
bind 127.0.0.1 | 绑定的主机地址。 默认情况下 bind=127.0.0.1 只能接受本机的访问请求。 不写的情况下,无限制接受任何 ip 地址的访问。 生产环境肯定要写你应用服务器的地址。 如果开启了 protected-mode,那么在没有设定 bind ip 且没有设密码的情况下,Redis 只允许接受本机的响应。 |
tcp-backlog | 可以理解是一个请求到达后至到接受进程处理前的队列。backlog 队列总和 = 未完成三次握手队列 + 已完成三次握手队列。 高并发环境 tcp-backlog 设置值跟超时时限内的 Redis 吞吐量决定。 |
timeout 300 | 当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能。 |
TCP keepalive | 对访问客户端的一种心跳检测,每隔 n 秒检测一次。 官方推荐设为 60 秒。 |
daemonize no | Redis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用 yes 启用守护进程(Windows 不支持守护线程的配置为 no ) |
pidfile /var/run/redis.pid | 当 Redis 以守护进程方式运行时,Redis 默认会把 pid 写入 /var/run/redis.pid 文件,可以通过 pidfile 指定 |
loglevel notice | 指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默认为 notice |
logfile | 日志文件名称 |
syslog | 是否将Redis日志输送到Linux系统日志服务中 |
syslog-ident | 日志的标志 |
syslog-facility | 输出日志的设备 |
database | 设定库的数量 默认16 |
maxclient | 最大客户端连接数 |
maxmemory <bytes> | 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区 |
maxmemory-policy | (1)volatile-lru:使用LRU(最近少使用)算法移除key,只对设置了过期时间的键。 (2)allkeys-lru:使用LRU算法移除key。 (3)volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键。 (4)allkeys-random:移除随机的key。 (5)volatile-ttl(即将过期):移除那些 TTL 值最小的 key,即那些最近要过期的key。 (6)noeviction:不进行移除。针对写操作,只是返回错误信息。 |
maxmemory-samples | 设置样本数量,LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小。 一般设置3~7的数字,数值越小样本越不准确,但是性能消耗也越小。 |