简介
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
Redis优势
-
性能极高-Redis能读的速度是110000次/s 写的速度是81000次/s
-
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
-
原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
-
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
Redis的安装
Window下安装(不推荐)
下载地址:https://github.com/MSOpenTech/redis/releases。
Linux下安装
下载地址:http://redis.io/download,下载最新稳定版本。
具体步骤如下:
下载 wget http://download.redis.io/releases/redis-5.0.5.tar.gz
解压 tar xzf redis-5.0.5.tar.gz cd redis-5.0.5
编译 make
在编译(make)过程中,可能会出现问题
https://blog.csdn.net/weixin_40493969/article/details/81150469
然后可以使用cp指令来复制一份配置文件,因为我们需要自定义一些配置,而 直接修改原生的配置的话不好 恢复
我们把conf文件复制到我们自己创建的目录去
cp redis.conf /myredis/redis.conf
之后我们运行也是运行我们自定义配置的redis.conf
启动redis的命令
redis-server /myredis/redis.conf
在这里我们可能会遇到没有权限启动的问题
chmod u+x *
redis的数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
String(字符串)
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储512MB。
实例
redis 127.0.0.1:6379> SET demo "str"
OK
redis 127.0.0.1:6379> GET demo
"str"
常用命令
Incr/decr/incrby/decrby 一定要是数字才能进行加减
getrange /setrange getrange拿部分值(getrange 开始下标 结束下标) setrange:覆盖部分值(setrange 开始下标 覆盖的值)
setex :设置过期时间 , 键 秒数
setnx:插入不存在的
mset : 批量插入
mget : 批量获取
msetnx: 批量插入不存在的 注:如果有一个存在那么全部插入失败
Hash(哈希,类似于java里的map)
Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
实例
redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World"
"OK"
redis 127.0.0.1:6379> HGET runoob field1
"Hello"
redis 127.0.0.1:6379> HGET runoob field2
"World"
实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。
每个 hash 可以存储 232 -1 键值对(40多亿)。
常用指令
HSET key_name field value:为指定的key设定field和value
hmset key field value[field1,value1]
hget key field
hmget key field[field1]
hgetall key:返回hash表中所有字段和值
hkeys key:获取hash表所有字段
hlen key:获取hash表中的字段数量
-hdel key field [field1]:删除一个或多个hash表的字段
list(列表)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
常用命令:
lpush key value1 [value2]
rpush key value1 [value2]
lpushx key value:从左侧插入值,如果list不存在,则不操作
rpushx key value:从右侧插入值,如果list不存在,则不操作
llen key:获取列表长度
lindex key index:获取指定索引的元素
lrange key start stop:获取列表指定范围的元素
lpop key :从左侧移除第一个元素
prop key:移除列表最后一个元素
blpop key [key1] timeout:移除并获取列表第一个元素,如果列表没有元素会阻塞列表到等待超时或发现可弹出元素为止
brpop key [key1] timeout:移除并获取列表最后一个元素,如果列表没有元素会阻塞列表到等待超时或发现可弹出元素为止
ltrim key start stop :对列表进行修改,让列表只保留指定区间的元素,不在指定区间的元素就会被删除
lset key index value :指定索引的值
set唯一、无序
常用命令
sadd key value1[value2]:向集合添加成员
scard key:返回集合成员数
smembers key:返回集合中所有成员
sismember key member:判断memeber元素是否是集合key成员的成员
srandmember key [count]:返回集合中一个或多个随机数
srem key member1 [member2]:移除集合中一个或多个成员
spop key:移除并返回集合中的一个随机元素
smove source destination member:将member元素从source集合移动到destination集合
sdiff key1 [key2]:返回所有集合的差集
sdiffstore destination key1[key2]:返回给定所有集合的差集并存储在destination中
zset(有序)
有序且不重复。每个元素都会关联一个double类型的分数,Redis通过分数进行从小到大的排序。分数可以重复
常用命令
ZADD key score1 memeber1
ZCARD key :获取集合中的元素数量
ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
ZRANK key member:返回有序集合指定成员的索引
ZREVRANGE key start stop :返回有序集中指定区间内的成员,通过索引,分数从高到底
ZREM key member [member …] 移除有序集合中的一个或多个成员
ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员(第一名是0)(低到高排序)
ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员
redis键(key)
常用命令
key * 查看全部key
exists key的名字,判断某个可以是否存在
move key db 移除
expire key 秒钟:给指定的key设置过期时间
ttl key 查看还有多少面过期,-1表示永不过期,-2 表示已经过期
type key 查看指定key 的数据类型
连接redis客户端
进入redis客户端
redis-cli 如果出现乱码就用
redis-cli --raw 就可以避免乱码的问题了
进入之之后可以用PING 该命令会连接本地的 redis 服务。
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING
PONG
可以检测是否启动redis命令
在远程服务器上连接redis
redis-cli -h host -p port -a password
实例
以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。
$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
备份与恢复(RDB/aof)
RDB
如有很重要的数据需要立马备份可以用 save /bgsave(后台备份) 这个命令
rdbSave
函数负责将内存中的数据库数据以 RDB 格式保存到磁盘中, 如果 RDB 文件已存在, 那么新的 RDB 文件将替换已有的 RDB 文件。
在保存 RDB 文件期间, 主进程会被阻塞, 直到保存完成为止。
SAVE 和 BGSAVE 两个命令都会调用 rdbSave
函数,但它们调用的方式各有不同:
- SAVE 直接调用
rdbSave
,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。 - BGSAVE 则
fork
出一个子进程,子进程负责调用rdbSave
,并在保存完成之后向主进程发送信号,通知保存已完成。因为rdbSave
在子进程被调用,所以 Redis 服务器在 BGSAVE 执行期间仍然可以继续处理客户端的请求。
但是rdb他有可能会,plushall shutdown rdb还是会有但是
AOF
以日志的形式记录每一个操作(读不记录),简单粗暴
AOF:Append-Only File:Redis会将没一个收到写命令都追加到文件中(默认是appendonly.aof)。当Redis重启时会通过重新执行文件中的写命令重建整个数据库的内容。AOF:Append-Only File:Redis会将没一个收到写命令都追加到文件中(默认是appendonly.aof)。当Redis重启时会通过重新执行文件中的写命令重建整个数据库的内容。
缺点:会产生一些多余命令
在aof和rdb同时存在的时候优先aof
恢复数据
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令
事务
可以一次执行多个命令,本质是一个组命令的集合,一个事务中的所有命令都会序列化,按顺序的串行化执行而不会被其他命令插入,不许加塞
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 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> EXEC //执行事务块里的命令
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
2) "C++"
3) "Programming"
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
简单的说 就是: 你在事务块里面,输入了命令并且按了回车那么如果说命令报错那么事务就会全部回滚,如果说过了这一关,exec的时候出错它就只会回滚出错的那个,其他的不影响
相关命名
DISCARD 取消事务,放弃执行事务块内的所有命令。
EXEC 执行所有事务块内的命令。
MULTI 标记一个事务块的开始。
UNWATCH 取消 WATCH 命令对所有 key 的监视。
WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
Redis 发布订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
应用场景
构建实时的消息系统,比如普通聊天、群聊等功能。
1、博客网站订阅,当作者发布就可以推送给粉丝
2、微信公众号模式
项目命令
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道。
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态。
PUBLISH channel message
将信息发送到指定的频道。
PUNSUBSCRIBE [pattern [pattern ...]]
退订所有给定模式的频道。
SUBSCRIBE channel [channel ...]
订阅给定的一个或多个频道的信息。
UNSUBSCRIBE [channel [channel ...]]
指退订给定的频道。PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道。
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态。
PUBLISH channel message
将信息发送到指定的频道。
PUNSUBSCRIBE [pattern [pattern ...]]
退订所有给定模式的频道。
SUBSCRIBE channel [channel ...]
订阅给定的一个或多个频道的信息。
UNSUBSCRIBE [channel [channel ...]]
指退订给定的频道。
更多命令请看这个链接
http://doc.redisfans.com/index.html
jedis
导入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
一个工具类
public class RedisUtil {
//服务器IP地址
private static String ADDR = "192.168.41.65";
//端口
private static int PORT = 6379;
//密码
private static String AUTH = "123456";
//连接实例的最大连接数
private static int MAX_ACTIVE = 1024;
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
private static int MAX_IDLE = 200;
//等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
private static int MAX_WAIT = 10000;
//连接超时的时间
private static int TIMEOUT = 10000;
// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
//数据库模式是16个数据库 0~15
public static final int DEFAULT_DATABASE = 0;
/**
* 初始化Redis连接池
*/
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT,AUTH,DEFAULT_DATABASE);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取Jedis实例
*/
public synchronized static Jedis getJedis() {
try {
if (jedisPool != null) {
Jedis resource = jedisPool.getResource();
System.out.println("redis--服务正在运行: "+resource.ping());
return resource;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/***
*
* 释放资源
*/
public static void returnResource(final Jedis jedis) {
if(jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
Q.E.D.
Comments | 0 条评论