NoSQL数据库之Redis
NoSQL:Not Only SQL(不仅仅是SQL),也可以解释为Non-Relation(非关系型数据库),在NoSQL数据库中,数据之间是无关系,无联系的,数据是松散的,可变的.
NoSQL优势:
1:易扩展:NoSQL 数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。
2:高性能,大数据量:性能极高,在大数据量下的读写性能同样优秀.
3:灵活的数据模型:NoSQL 无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。尤其在快速变化的市场环境中,用户的需求总是在不断变化的。
4:高可用:在不太影响性能的情况下就可以快速实现高可用.
5:低成本:开源免费,无需支付昂贵的liceness
Redis是当今非常流行的基于KV结构的作为cache使用的NoSQL数据库.
Redis是一个开源的(BSD许可的)内存数据结构存储,用作数据库、缓存和消息代理。它支持数据结构,如字符串、哈希、列表、集合、带范围查询的排序集合、位图、超日志、带半径查询的地理空间索引和流。Redis具有内置的复制、Lua脚本、LRU逐出、事务和不同级别的磁盘持久性,并通过Redis Sentinel和带有Redis集群的自动分区提供高可用性。
$ wget http://download.redis.io/releases/redis-6.0.5.tar.gz $ tar xzf redis-6.0.5.tar.gz $ cd redis-6.0.5 $ make
以下命令可执行,可不执行.执行后,该操作则将 src下的许多可执行文件复制到/usr/local/bin 目录下,这样做可以在任意目录执行redis的软件的命令
$ make install
启动:. /redis-server (前台启动) ./redis-server & (后台启动) 关闭: ./redis-cli shutdown(客户端优雅关闭) kill pid(杀进程,不推荐) A、直接连接 redis (默认 ip127.0.0.1,端口 6379):./redis-cli 在 redis 安装目录\src, 执行 ./redis-cli 此命令是连接本机 127.0.0.1 ,端口 6379 的 redis B、指定 IP 和端口连接 redis:./redis-cli -h 127.0.0.1 -p 6379 -h redis 主机 IP(可以指定任意的 redis 服务器) -p 端口号(不同的端口表示不同的 redis 应用) 在 redis 安装目录\src, 执行 ./redis-cli -h 127.0.0.1 -p 6379
Redis的基本操作命令
ping 解释:输入 ping,redis 给我们返回 PONG,表示 redis 服务运行正常
A、keys 语法:keys pattern 作用:查找所有符合模式 pattern 的 key. pattern 可以使用通配符。 通配符: * :表示 0-多个字符 ,例如:keys * 查询所有的 key。 ?:表示单个字符,例如:wo?d , 匹配 word , wood [] :表示选择[]内的字符,例如 wo[or]d, 匹配 word, wood, 不匹配 wold
B、 exists 语法:exists key [key…] 作用:判断 key 是否存在 返回值:整数,存在 key 返回 1,其他返回 0. 使用多个 key,返回存在的 key 的数量。 例 1:检查指定 key 是否存在
C、 expire 语法:expire key seconds 作用:设置 key 的生存时间,超过时间,key 自动删除。单位是秒。 返回值:设置成功返回数字 1, 其他情况是 0 。 例 1: 设置红灯的倒计时是 5 秒
D、ttl 语法:ttl key 作用:以秒为单位,返回 key 的剩余生存时间(ttl: time to live) 返回值: -1 :没有设置 key 的生存时间, key 永不过期。 -2 :key 不存在 数字:key 的剩余时间,秒为单位
E、 type 语法:type key 作用:查看 key 所存储值的数据类型 返回值:字符串表示的数据类型 none (key 不存在) string (字符串) list (列表) set (集合) zset (有序集) hash (哈希表) 例 1:查看存储字符串的 key :wood
F、 del
语法:del key [key…]
作用:删除存在的 key ,不存在的 key 忽略。
返回值:数字,删除的 key 的数量。
Redis的5种数据类型
A、字符串类型 string 字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制 数据,序列化后的数据,JSON 化的对象甚至是一张图片。最大 512M。
基本操作命令:
SET key value 设置指定key的值
GET key 获取指定 key 的值。
GETRANGE key start end 返回 key 中字符串值的子字符
GETSET key valu 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
GETBIT key offset 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
MGET key1 [key2..] 获取所有(一个或多个)给定 key 的值。
SETBIT key offset value 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
SETEX key seconds value 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
SETNX key value只有在 key 不存在时设置 key 的值。
INCR key 将 key 中储存的数字值增一。
DECR key 将 key 中储存的数字值减一。
APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾。
B、 哈希类型 hash Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
基本操作命令:
HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。
HGET key field 获取存储在哈希表中指定字段的值。
HMSET key field1 value1 [field2 value2 ] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
HMGET key field1 [field2] 获取所有给定字段的值
HGETALL key 获取在哈希表中指定 key 的所有字段和值
HDEL key field1 [field2] 删除一个或多个哈希表字段
C、 列表类型 list
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头
部(左边)或者尾部(右边)
基本操作命令:
LPUSH key value1 [value2] 将一个或多个值插入到列表头部
LPUSHX key value 将一个值插入到已存在的列表头部
RPUSH key value1 [value2] 在列表中添加一个或多个值
LRANGE key start stop 获取列表指定范围内的元素
LPOP key 移出并获取列表的第一个元素
RPOP key 移除列表的最后一个元素,返回值为移除的元素。
LLEN key 获取列表长度
LINDEX key index 通过索引获取列表中的元素
D、集合类型 set Redis 的 Set 是 string 类型的无序集合,集合成员是唯一的,即集合中不能出现重复的数 据
基本操作命令:
SADD key member1 [member2] 向集合添加一个或多个成员
SCARD key 获取集合的成员数
SMEMBERS key 返回集合中的所有成员
SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素
SPOP key移除并返回集合中的一个随机元素
E、 有序集合类型 zset (sorted set) Redis 有序集合 zset 和集合 set 一样也是 string 类型元素的集合,且不允许重复的成员。 不同的是 zset 的每个元素都会关联一个分数(分数可以重复),redis 通过分数来为集合中的 成员进行从小到大的排序。
基本操作命令:
ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARD key 获取有序集合的成员数
ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
ZINTERSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
ZRANK key member 返回有序集合中指定成员的索引
ZSCORE key member 返回有序集中,成员的分数值
Redis的发布订阅:
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
A、publish 发布消息
语法: publish chanel message
作用: 将 message 消息发送到 channel 频道。 message 是要发送的消息, channel 是自定
义的频道名称(例如 cctv1 ,cctv5),唯一标识发布者。
返回值:数字。接收到消息订阅者的数量
B、 subscribe 订阅频道
语法:subscribe channel [channel…]
作用:订阅一个或多个频道的信息
返回值:订阅的消息
C、 unsubscribe 退订频道
语法:unsubscribe channel [channel]
作用:退出指定的频道,不订阅。
返回值:退订的告知消息
Redis事务
(1) multi 语法: multi 作用:标记一个事务的开始。事务内的多条命令会按照先后顺序被放进一个队列当中。 返回值:总是返回 ok
(2) exec 语法:exec 作用:执行所有事务块内的命令 返回值:事务内的所有执行语句内容,事务被打断(影响)返回 nil
(3) discard 语法:discard 作用:取消事务,放弃执行事务块内的所有命令
(4) watch 语法:watch key [key ...] 作用:监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动, 那么事务将被打断。 返回值:总是返回 ok
(5) unwatch 语法:unwatch 作用:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后, EXEC 命令 或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了 返回值:总是返回 ok
1)multi : 用 multi 命令告诉 Redis,接下来要执行的命令你先不要执行,而是把它们暂 时存起来 (开启事务) 2)sadd works john 第一条命令进入等待队列(命令入队) 3)sadd works rose 第二条命令进入等待队列(命令入队) 4)exce 告知 redis 执行前面发送的两条命令(提交事务)
Redis的Watch机制
A、Redis 的 WATCH 机制
WATCH 机制原理:
WATCH 机制:使用 WATCH 监视一个或多个 key , 跟踪 key 的 value 修改情况, 如果有key 的 value 值在事务 EXEC 执行之前被修改了, 整个事务被取消。EXEC 返回提示信息,表示事务已经失败。
WATCH 机制使的事务 EXEC 变的有条件,事务只有在被 WATCH 的 key 没有修改的前提下才能执行。不满足条件,事务被取消。使用 WATCH 监视了一个带过期时间的键, 那么即使这个键过期了, 事务仍然可以正常执行
大多数情况下, 不同的客户端会访问不同的键, 相互同时竞争同一 key 的情况一般都很少, 乐观锁能够以很好的性能解决数据冲突的问题。
B、 何时取消 key 的监视(WATCH)?
① WATCH 命令可以被调用多次。 对键的监视从 WATCH 执行之后开始生效,直到调用 EXEC 为止。不管事务是否成功执行, 对所有键的监视都会被取消。
② 当客户端断开连接时, 该客户端对键的监视也会被取消。
③ UNWATCH 命令可以手动取消对所有键的监视
Redis的持久化机制
(1) RDB 方式 Redis Database(RDB),就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。 RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。默认是 dump.rdb。RDB 技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响 Redis 的正常使用。RDB 恢复数据时比其他 AOF 速度快。
Redis的高可用架构
主从复制(master/slave)
include /usr/local/redis-3.2.9/redis.conf daemonize yes port 6380 pidfile /var/run/redis_6380.pid logfile 6380.log dbfilename dump6380.rdb
C、编辑 Slave 的配置文件 redis6382.conf 和 redis6384.conf: 在空文件加入如下内容
①:redis6382.conf: include /usr/local/redis-3.2.9/redis.conf daemonize yes port 6382 pidfile /var/run/redis_6382.pid logfile 6382.log dbfilename dump6382.rdb slaveof 127.0.0.1 6380
slaveof : 表示当前 Redis 是谁的从。当前是 127.0.0.0 端口 6380 这个 Master 的从。 ②:redis6384.conf: include /usr/local/redis-3.2.9/redis.conf daemonize yes port 6384 pidfile /var/run/redis_6384.pid logfile 6384.log dbfilename dump6384.rdb slaveof 127.0.0.1 6380
三台服务全部指定配置文件启动,查看当前服务信息在客户端的 Redis 内执行命令 info replication
服务器容灾处理:
设置密码:
redis.conf配置中的 requirepass 123456
<!-- redis依赖包 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
<!--配置属性配置文件-->
<context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true" />
<bean id="redisCache" class="com.xxx.RedisCache"> <constructor-arg name="host" value="${redis.hosts}"/> <constructor-arg name="port" value="${redis.port}"/> <constructor-arg name="timeOut" value="${redis.timeout}"/> <constructor-arg name="password" value="${redis.password}"/> </bean>
public class RedisCache { private static JedisPool pool; public RedisCache(String host, Integer port, Integer timeOut, String password) { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(10240); config.setMaxIdle(200); config.setMaxWaitMillis(5000); pool = new JedisPool(config, host, port, timeOut, password); }
public String get(String key) { Jedis jedis = null; try { jedis = pool.getResource(); return jedis.get(key); } catch (Exception e) { logger.error("读取redis异常,key:[{}]", key, e); throw new BusinessException("系统异常!"); } finally { if (jedis != null) { pool.returnResource(jedis); } } } public byte[] get(byte[] key) { Jedis jedis = null; try { jedis = pool.getResource(); return jedis.get(key); } catch (Exception e) { logger.error("读取redis异常,key:[{}]", key, e); throw new BusinessException("系统异常!"); } finally { if (jedis != null) { pool.returnResource(jedis); } } } public String setex(String key, int seconds, String value) { Jedis jedis = null; try { jedis = pool.getResource(); return jedis.setex(key, seconds, value); } catch (Exception e) { logger.error("redis存储数据异常,key:[{}]", key, e); throw new BusinessException("系统异常!"); } finally { if (jedis != null) { pool.returnResource(jedis); } } } }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
1.4.0之前
<!-- 加载spring boot redis包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE</version> </dependency>
2、在Springboot核心配置文件application.properties中配置redis连接信息:
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
redisTemplate.opsForValue();//操作字符串 redisTemplate.opsForHash();//操作hash redisTemplate.opsForList();//操作list redisTemplate.opsForSet();//操作set redisTemplate.opsForZSet();//操作有序set