一.Redis 简介
1.REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
2.Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
3.它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
4.Redis 与其他 key - value 缓存产品有以下三个特点:
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
Redis支持数据的备份,即master-slave模式的数据备份。
二.Redis 安装
Windows中
①下载地址:https://github.com/MSOpenTech/redis/releases。
②Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包到 C 盘,解压后,将文件夹重新命名为 redis。
③打开一个 cmd 窗口 使用cd命令切换目录到 C:\redis 运行
redis-server.exe redis.windows.conf
④这时候另启一个cmd窗口,原来的不要关闭,不然就无法访问服务端了。
切换到redis目录下运行
redis-cli.exe -h 127.0.0.1 -p 6379
设置键值对
set myKey abc
取出键值对
get myKey
三.Redis 配置
Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf。
通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。
CONFIG SET 命令基本语法:
redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
实例
redis 127.0.0.1:6379> CONFIG SET loglevel "notice"OK redis 127.0.0.1:6379> CONFIG GET loglevel 1) "loglevel" 2) "notice"
四.Redis 数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
1.String(字符串)>SET+元素名+元素值 GET+元素名
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
redis 127.0.0.1:6379> SET name "runoob" OK redis 127.0.0.1:6379> GET name "runoob"
2.Hash(哈希)>HMSET+集合名+field1,2,3..... HGET+field1,2,3.....
Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
redis> HMSET myhash field1 "Hello" field2 "World" "OK" redis> HGET myhash field1 "Hello" redis> HGET myhash field2 "World"
3.List(列表)>lpush+列表名+元素 lrange+列表名+起始下标+结束下标
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。
redis 127.0.0.1:6379> lpush runoob redis(integer) 1 redis 127.0.0.1:6379> lpush runoob mongodb(integer) 2 redis 127.0.0.1:6379> lpush runoob rabitmq(integer) 3 redis 127.0.0.1:6379> lrange runoob 0 10 1) "rabitmq" 2) "mongodb" 3) "redis"
4.Set(集合) >sadd+集合名+元素名 smembers+集合名
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。
redis 127.0.0.1:6379> sadd runoob redis(integer) 1 redis 127.0.0.1:6379> sadd runoob mongodb(integer) 1 redis 127.0.0.1:6379> sadd runoob rabitmq(integer) 1 redis 127.0.0.1:6379> sadd runoob rabitmq(integer) 0 redis 127.0.0.1:6379> smembers runoob 1) "redis" 2) "rabitmq" 3) "mongodb"
注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。
集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。
5.zset(sorted set:有序集合) >zadd+集合名+score+元素名 ZRANGEBYSCORE+集合名+起始score+结束score
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。zset的成员是唯一的,但分数(score)却可以重复。
redis 127.0.0.1:6379> zadd runoob 0 redis(integer) 1 redis 127.0.0.1:6379> zadd runoob 0 mongodb(integer) 1 redis 127.0.0.1:6379> zadd runoob 0 rabitmq(integer) 1 redis 127.0.0.1:6379> zadd runoob 0 rabitmq(integer) 0 redis 127.0.0.1:6379> > ZRANGEBYSCORE runoob 0 1000 1) "mongodb" 2) "rabitmq" 3) "redis"
五.Redis 命令
Redis 客户端的基本语法为:
$ redis-cli
启动 redis 客户端,打开终端并输入命令 redis-cli。该命令会连接本地的 redis 服务。
$ redis-cli redis 127.0.0.1:6379>redis 127.0.0.1:6379> PING PONG
连接到本地的 redis 服务并执行 PING 命令,该命令用于检测 redis 服务是否启动。
如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。
$redis-cli -h 127.0.0.1 -p 6379 -a "mypass"redis 127.0.0.1:6379>redis 127.0.0.1:6379> PING PONG
六.Redis 发布订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
实例中我们创建了订阅频道名为 redisChat:
redis 127.0.0.1:6379> SUBSCRIBE redisChatReading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1
重新开启个 redis 客户端,然后在同一个频道 redisChat 发布两次消息,订阅者就能接收到消息。
redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"(integer) 1 redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"(integer) 1 # 订阅者的客户端会显示如下消息 1) "message" 2) "redisChat" 3) "Redis is a great caching technique" 1) "message" 2) "redisChat" 3) "Learn redis by runoob.com"
七.Redis 事务
Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:
批量操作在发送 EXEC 命令前被放入队列缓存。
收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
开始事务。
命令入队。
执行事务。
先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:
redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"QUEUED redis 127.0.0.1:6379> GET book-name QUEUED redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"QUEUED redis 127.0.0.1:6379> SMEMBERS tag QUEUED redis 127.0.0.1:6379> EXEC1) OK2) "Mastering C++ in 21 days"3) (integer) 34) 1) "Mastering Series" 2) "C++" 3) "Programming"
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
八.Redis 脚本
Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。
redis 127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second"
九.Redis 数据备份与恢复
备份
redis 127.0.0.1:6379> SAVE OK
该命令将在 redis 安装目录中创建dump.rdb文件。
创建 redis 备份文件也可以使用命令 BGSAVE,该命令在后台执行。
127.0.0.1:6379> BGSAVEBackground saving started
恢复
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令:
redis 127.0.0.1:6379> CONFIG GET dir 1) "dir" 2) "/usr/local/redis/bin"
以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin。
十.Redis 安全
可以通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证,这样可以让你的 redis 服务更安全。
可以通过以下命令查看是否设置了密码验证:
127.0.0.1:6379> CONFIG get requirepass 1) "requirepass" 2) ""
默认情况下 requirepass 参数是空的,这就意味着你无需通过密码验证就可以连接到 redis 服务。
你可以通过以下命令来修改该参数:
127.0.0.1:6379> CONFIG set requirepass "runoob" OK 127.0.0.1:6379> CONFIG get requirepass 1) "requirepass" 2) "runoob"
设置密码后,客户端连接 redis 服务就需要密码验证,否则无法执行命令。
十一.Java 使用 Redis
连接到 redis 服务
实例
import redis.clients.jedis.Jedis; public class RedisJava { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis jedis = new Jedis("localhost"); System.out.println("连接成功"); //查看服务是否运行 System.out.println("服务正在运行: "+jedis.ping()); } }
编译以上 Java 程序,确保驱动包的路径是正确的。
连接成功服务正在运行: PONG
①Redis Java String(字符串) 实例
实例
import redis.clients.jedis.Jedis; public class RedisStringJava { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis jedis = new Jedis("localhost"); System.out.println("连接成功"); //设置 redis 字符串数据 jedis.set("runoobkey", "www.runoob.com"); // 获取存储的数据并输出 System.out.println("redis 存储的字符串为: "+ jedis.get("runoobkey")); } }
编译以上程序。
连接成功redis 存储的字符串为: www.runoob.com
②Redis Java List(列表) 实例
实例
import java.util.List;import redis.clients.jedis.Jedis; public class RedisListJava { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis jedis = new Jedis("localhost"); System.out.println("连接成功"); //存储数据到列表中 jedis.lpush("site-list", "Runoob"); jedis.lpush("site-list", "Google"); jedis.lpush("site-list", "Taobao"); // 获取存储的数据并输出 List<String> list = jedis.lrange("site-list", 0 ,2); for(int i=0; i<list.size(); i++) { System.out.println("列表项为: "+list.get(i)); } } }
编译以上程序。
连接成功列表项为: Taobao列表项为: Google列表项为: Runoob
③Redis Java Keys 实例
实例
import java.util.Iterator;import java.util.Set;import redis.clients.jedis.Jedis; public class RedisKeyJava { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis jedis = new Jedis("localhost"); System.out.println("连接成功"); // 获取数据并输出 Set<String> keys = jedis.keys("*"); Iterator<String> it=keys.iterator() ; while(it.hasNext()){ String key = it.next(); System.out.println(key); } } }
编译以上程序。
连接成功runoobkey site-list
最后提一个小问题,是我在面试过程中遇到的:
mySQL里有1000万数据,redis中只存10万的数据,如何保证redis中的数据都是热点数据?
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据