Redis入门
- SQL与NOSQL
- Redis是什么
- Redis服务端安装(Linux)
- Redis的使用
- redis-cli命令
- redis clients推荐(Java)
- Redis的数据类型及使用
- String类型
- String类型常用的操作命令
- String的应用场景
- Hash
- Hash的基本介绍
- Hash的操作命令
- Hash的应用场景
- List
- List的操作命令
- List应用场景
- Set
- Set的操作命令
- Set的使用场景
- ZSet
- ZSet的操作命令
- ZSet的应用场景
- Geo Spatial
- Geo的操作命令
- HyperLogLogs
- HyperLogLogs的操作命令
- HyperLogLogs应用场景
SQL与NOSQL
SQL:指关系型数据库;1.基于行存储的二维结构化数据,2.有固定化模式,必须定义好表和字段结构后才能添加数据。3.表与表之间存在关联,4.有SQL语法。5.支持事务ACID,原子性、一致性、隔离性、持久性。
缺点:不支持动态的扩容缩容、表的结构难以修改,存储的数据格式不灵活。在高并发的场景下,磁盘读写压力大。
NOSQL:泛指非关系型数据库;1.非结构化的数据,2.数据与数据没有关联,3.没有事务性,遵循BASE理论,即最终一致性,4.海量数据存储、支持高并发读写,5.支持分布式:数据分片、扩缩容简单。
现在市面上常用的NOSQL数据库有以下几种类型:
- KV存储(redis)
- 文档存储(MongoDB)
- 列存储(HBase)
- 图存储(Graph、Neo4j)
- 对象存储
- XML存储
- ......
Redis是什么
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 带范围查询的有序集合(sorted sets), bitmaps, hyperloglogs ,带半径的地理空间索引查询和流(geospatial)。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
Redis服务端安装(Linux)
1.下载redis安装包
wget https://download.redis.io/releases/redis-5.0.5.tar.gz
2.解压缩
tar -zxvf redis-5.0.5.tar.gz
3.安装redis编译环境,因为redis是用c语言开发的,需要安装gcc依赖
yum install gcc
可以通过gcc -v
查看是否安装。(需要注意的是redis.6支持多线程,但是需要gcc版本大于4.9)
4.编译安装cd redis-5.0.5 make MALLOC=libc
将redis-5.0.5/src目录下的二进制文件安装到/usr/local/bin
cd src make install
5.修改配置文件redis.conf
- 是否后台启动:daemonize no 改为 daemonize yes
- 将 `bind 127.0.0.1` 注释或者改为 `bind 0.0.0.0`,否则将只能在本机被访问
- 如果连接时需要密码访问,取消requirepass的注释。改为 requirepass [password]
6.使用指定配置文件启动Redis(当想要运行多个redis时,只需要通过运行redis-server指定不同的conf文件即可)
/usr/local/soft/redis-5.0.5/src/redis-server /usr/local/soft/redis-5.0.5/redis.conf
如图即为运行成功,其默认端口号为6379
7.通过./redis-cli
可以进入默认的redis客户端(在src目录下)
8.停止redis命令:shutdown(在客户端中)或通过kill -9 portRedis的使用
ps:在部分redis可视化管理工具中,连接redis数据库成功后,会出现一串数据库。但是,redis与关系型数据库不同,这一串数据库并没有进行完全的隔离。所以,不需要对相关的业务进行指定数据库。
redis-cli命令
1.
flushall
清空所有数据库
2.flushdb
清空当前数据库
3.select [number]
跳转到相应编号的数据库
…推荐使用Redis 命令参考进行详细的命令查阅redis clients推荐(Java)
1.Jedis
一款轻量级的针对Redis的Java客户端。需要注意,在多个线程使用同一个Jedis链接去操作数据的时候,有可能出现数据干扰的情况。此时可以通过每个线程创建一个新的Jedis链接或通过数据库连接池进行处理。
Maven引入方式:<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.2.3</version> </dependency>
使用:
Jedis jedis = new Jedis(url, port);
连接池的使用
JedisPoolConfig config=new JedisPoolConfig(); //1.设置连接池的基本配置 config.setMaxTotal(10); config.setMaxIdle(1); //2.设置连接池目标数据库 JedisPool jedisPool = new JedisPool(config, url, port); //3.调用连接 Jedis resource = jedisPool.getResource(); //4.关闭,归还到连接池中 resource.close();
2.lettuce
可扩展的线程安全的客户端,支持异步模式。如果避免阻塞和事务操作,如BLPOP和MULTI/EXEC,多个线程就可以共享一个连接。lettuce 底层基于 Netty,支持高级的 Redis 特性,比如哨兵,集群,管道,自动重新连接和Redis数据模型。
在spring-boot 2.0版本中,Lettuce作为默认的Redis访问客户端,(2.0之前是Jedis)可以通过下面的方式引入:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
同步调用方法
//创建客户端 RedisClient client=RedisClient.create("redis://192.168.2.128:6379"); //线程安全的长连接,连接丢失时会自动重连 StatefulRedisConnection<String, String> connect = client.connect(); //获取同步执行命令,默认超时时间为60s RedisCommands<String, String> sync = connect.sync(); sync.set("key","value"); System.out.println(sync.get("key")); //关闭连接 connect.close(); //关闭客户端 client.shutdown();
异步调用与同步不同的是,其调用方法用RedisFuture进行了封装:
//创建客户端 RedisClient client=RedisClient.create("redis://192.168.2.128:6379"); //线程安全的长连接,连接丢失时会自动重连 StatefulRedisConnection<String, String> connect = client.connect(); RedisAsyncCommands<String, String> async = connect.async(); async.set("Lettuce", "async773"); RedisFuture<String> future = async.get("Lettuce"); String s = null; try { s = future.get(60, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { e.printStackTrace(); } System.out.println("--"+ s);
3.Redisson
在Redis 的基础上实现的 Java 驻内存数据网格,可以为Java提供分布式、可扩展的数据结构,以及提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列等。<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.5.4</version> </dependency>
private static RedissonClient redissonClient; static { Config config=new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); redissonClient= Redisson.create(config); } public static void main(String[] args) throws InterruptedException { RLock rLock=redissonClient.getLock("updateAccount"); // 最多等待100秒、上锁10s以后自动解锁 if(rLock.tryLock(100,10, TimeUnit.SECONDS)){ System.out.println("获取锁成功"); } Thread.sleep(20000); rLock.unlock(); redissonClient.shutdown(); }
Redis的数据类型及使用
字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 带范围查询的有序集合(zsets), bitmaps(位图), hyperloglogs(用来做基数统计的算法) ,带半径的地理空间索引查询和流(geospatial)
String类型
1.String类型可以存储的数据类型包括:String、INT、Float。
String类型常用的操作命令
1.对String数据类型的操作
set key value [过期时间:EX secends/PX milliseconds] [NX (当已经有当前key时, val不可以被设置,set不成功)/XX(只有key存在时,set才能成功)] mset key value key value ......#批量设置 mget key key.....#批量获取(程序返回list) strlen key #获取value的长度 append key value #在key原有的val上追加value getrange key [start] [end] #返回value的start下标到end下标的数据,end=-1表示获取value
2.对INT数据类型的操作
incr key #对value进行递增 incrby key [step] #对value按照步数step进行递增 decr key #对value进行递减 decrby key [step]#对value按照步数step进行递减
3.对Fload类型的操作
set key value incrbyfloat key [step]
4.位操作(String类型在Redis里是一个8位二进制进行存储的,可以通过位操作改变数据)
setbit key index bitval #将key的value的二进制数组中下标为index的数据改为bitval(1/0) getbit key index #获取value二进制数组中下标为index的bitval getpos key bitval #获取value中第一个bitval(1/0)的下标 bitcount key #统计value中1的个数 BITOP AND resultKEY KEY1 ... KEYN #对一个或多个key求逻辑与,并将结果保存到reusultKEY BITOP OR resultKEY KEY1 ... KEYN #对一个或多个key求逻辑或,并将结果保存到reusultKEY BITOP XOR resultKEY KEY1 ... KEYN #对一个或多个key求逻辑异或,并将结果保存到reusultKEY BITOP NOT resultKEY KEY1 ... KEYN #对一个或多个key求逻辑非,并将结果保存到reusultKEY
String的应用场景
1.缓存
2.分布式session
3.set NX EX 分布式锁
4.incr 全局ID/计数器/限流
5.位操作 统计Hash
1.String可以通过key的分层实现对一张表的数据存储:在redis里,我们可以通过
:
对key进行分层。
当然,这种做法的弊端也很明显,当表的数据结构过于复杂时,String类型会成为一个复杂的串。set key1:key2:key3 value set key1:key5:key6 value keys key1* #=>输出key1:key2:key3;key1:key5:key6 keys key1:key2* #=>输出key1:key2:key3
Hash的基本介绍
Hash类型的结构:
Hash相较于String类型,更加节省空间,同时通过一个key存储多个键值对的方式,减少了key的创建量,从而减少了key的命名冲突,在读取时,也可以通过一个key获取到一系列的相关数据,避免反复请求,减少了资源消耗。
当然,由于无法单独对Field进行精细化控制(如设置过期时间等),同时也Hash无法进行bit操作。
同时,由于Redis集群式通过KEY进行取模从而决定将它分布到不同Redis节点上,以达到平衡存储压力的。而Hash类型只能共用一个KEY,无法进行分散存储,当一个Hash过大时,会造成单个Redis节点存储压力过大。而String类型就没有这方面的顾虑,所以,在某些场景下,String类型依旧时不可替代的。Hash的操作命令
hset key field value #设置值 hmset key field1 val1 ... fieldN valN #一次性设置多个 hget key field1#取值 hmget key field1 ... fieldN #取多个值 hkeys key #输出key下的所有field hvals key#输出key下的所有value hgetall key#输出key下的所有field及value hdel key field #删除key下的某个元素 hlen key #返回key下的元素个数 hexists key field #返回1,表示key下有field这个键值对 hincrby key field1 step #对整型内容进行递增(hash未提供递减关键字,可以将step设为负数实现) hincrbyfloat key field1 step #对浮点型内容进行递增
== 在这里我们需要注意到,Redis直接删除集合类型大KEY时,一般每秒可清理100w到数百w的元素;如果数千w个元素的大KEY进行删除时,会导致Redis阻塞10s以上,使集群认为Redis故障,导致故障切换或者应用程序雪崩。(Redis是单线程的,耗时过大的命令会导致其他命令被阻塞,引起应用程序雪崩或Redis集群发生故障切换)。==
Hash的应用场景
1.存储一张表、一个复杂的对象
2.购物车功能List
Redis里的List,本质是一个双向链表,有序,左边是列表头,右边是列表尾,顺序是从左到右。因此,可以作为队列或者栈使用。一个List可以容纳 2 32 − 1 2^{32}-1 232−1的元素。
List的操作命令
lpush key val ...#在队列左侧添加一个或多个元素 rpush key val ...#在队列右侧添加一个或多个元素 lpop key #从队列左侧弹出一个元素 rpop key #从队列右侧弹出一个元素 lindex key index #通过下标获取队列中的对应元素(从左侧) lrange key start end #获取一定范围里对应的元素 blpop key timeout #弹出一个元素,有阻塞性质,如果没有数据,会一直阻塞等待,直timeout时间 brpop key timeout #右侧弹出,同上,这两种用法常用于消息队列 lrem key [count] value #移除 count>0,从左向右,移除与value相等的元素,数量为count #count<0,从右向左,移除与value相等的元素,数量为count的绝对值 #count=0,移除表中所有与value相等的值
List应用场景
1.消息队列
2.用户时间线Set
Set,一个无序的字符串集合,存储元素的容量与List一样
Set的操作命令
sadd key val1 ... valN #添加元素 smembers key #获取集合里所有元素 scard key#获取集合中元素的数量 srandmember key [count]#从集合中随机返回一个元素,如果带数量,则返回指定数量的元素 #这种返回,不会从集合中将元素删掉 spop key [count]#返回元素并删除 srem key val1 ... valN #直接移除指定元素 sismember key val # 判断集合中是否存在元素val ############集合之间的操作################### sdiff key1 key2 #获取差集,只在第一个集合中有的 sinter key1 key2 #获取交集 sunion key1 key2 #获取并集(合并去重) sdiffstroe desSet key1...keyN #将集合之间的差集存储到指定集合中
Set的使用场景
1.抽奖
2.点赞、签到、打卡一类的操作及统计
3.商品标签
4.电商的商品筛选
5.用户关注模型ZSet
ZSet,有序集合,每一个元素都有一个分值,分值越小越靠前,当分值相同时,通过元素的ASCII码进行排序
ZSet的操作命令
zadd key score1 val1 ... scoreN valN #添加元素,分值要写在元素的前面 zrange key start end withscores #获取范围内的元素,并显示分值 zrevrange key start end withscores#获取范围内的元素,分值大的在前面 zrangebyscore key min max #获取分值范围内的元素 zrem key val1 ... valN #移除指定元素 zcard key #获取元素数量 zincrby key score valn #增加元素的分值 zrank key valN #获取指定元素的下标 zscore key valN #获取元素的分值
ZSet的应用场景
1.排行榜
Geo Spatial
用来保存地理位置信息的数据类型,同时,Redis提供了一系列地理位置的计算方法,方便相关功能的实现。
Geo的操作命令
geoadd key [longitude] [latitude] valN ...#添加key中的经度 纬度 元素 geopos key valN #获取对应元素的经纬度 geodist key val1 val2 [unit]#计算两个元素的距离,unit表示单位 可以用m/km或mi(英里)/ft(英尺) georadius key [longtude] [latitude] num [unit] #key中距离输入的及维度指定距离num内的元素 georadiusbymember key valN num [unit]#距离valN元素位置不超过num距离的元素
HyperLogLogs
提供了一种基于基数的统计方法,可以用很少的内存统计很大的基数(不同元素),当然,代价是会产生一定的误差
HyperLogLogs的操作命令
pfadd key val1 ...valN pfcount key #元素数量 pfmerge resultkey key keyN #合并多个key并保存到resultkey中
HyperLogLogs应用场景
1.网站用户访问量统计