Redis
Nosql数据库
NoSql就是Not Only sql。Nosql是非关系型数据库,它是关系型数据库的良好补充,而不能替代关系型数据库。
NoSql是为了解决高并发、高可扩展、高可用以及高写入而产生的数据库解决方案。
Redis
Redis是用C语言开发的高性能的键值对存储的Nosql数据库。
redis是一个内存nosql数据库
redis中也是存储key-value形式的数据
redis中的key-value相比hbase等数据库来说,redis的value比较强大,它的value可以不仅仅是一个byte[]
redis的value可以有结构:可以是一个list,也可以是一个hash,也可以是set…
Redis存储的数据类型有五种:字符(string)、散列(hash)、列表(list)、集合(set)、有序集合(sorted set)
所以redis经常被称作为:数据结构服务器
Redis安装
1.安装GCC编译器(C的编译器)
yum -y install gcc
2.进入到Redis的源码包中
/usr/local/src/redis-6.2.6
3.执行make命令进行编译
make
4.然后安装
make install
5.创建一个保存redis运行时的数据可配置文件的目录
mkdir /usr/local/redis
6.将Redis的默认配置文件拷贝到/usr/local/redis
cp /usr/local/src/redis-6.2.6/redis.conf /usr/local/redis/
7.修改redis的配置文件(/usr/local/redis/下的redis.conf)
- bind 172.16.200.103 127.0.0.1
这里的bind指的是只有指定的网段才能远程访问这个redis - daemonize yes #redis后台运行
- requirepass 123456 #指定redis的密码
- dir /data/redis #redis数据存储的位置
- appendonly yes #开启aof日志,它会每次写操作都记录一条日志
8.创建数据存储的目录
mkdir -p /data/redis
9.启动redis
redis-server /opt/apps/redis-6.2.6/redis.conf
10.查看redis进程信息
ps -ef | grep redis
11.使用命令行客户端连接redis(-h指定的是ip地址或主机名,-p指定的是端口,默认就是6379)
redis-cli -h 127.0.0.1
12.输入密码
auth 123456
13.停止redis
- 强制结束程序。使用kill -9 进程的pid,强行终止Redis进程可能会导致redis持久化丢失;
- 在客户端下输入shutdown
make install后,可以将配置文件和数据存储目录提出来,原来的redis目录就可以删掉了
Redis操作
往redis中写数据,key、value必须都是String类型
idea连接Redis导入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${redis.version}</version>
</dependency>
String类型
- 存储数据:set k1 v1
- 获取数据:get k1
- 获取所有key:keys *
- 自增1(键不存在会创建):incr k1
- 自减1(键不存在会创建):decr k1
- 自增指定数值(键不存在会创建):incrby k1 数值
- 删除数据:del k1
- 同时设置多个键值:mset k1 v1 k2 v2 k3 v3
- 同时获取多个键值:mget k1 k3
- 删除所有的数据(慎用):flushdb
- 返回value的长度,如果键不存在则返回0:strlen k1
- 指定存储时间存储数据:set k1 v1 ex 时长(单位秒)
- 查看数据剩余存储时间,没有设置存储时间则返回-1:ttl k1
ttl:time to live 存活时间
def main(args: Array[String]): Unit = {
//建立连接
val jedis = new Jedis("linux1",6379);
//授权
jedis.auth("123456");
//存储数据
// jedis.set("lxl","123");
//自增
jedis.incr("lxl")
//获取数据
val str = jedis.get("lxl");
println(str)
}
Hash类型
hash叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。如下:
- 存储数据(属性值重复回覆盖):hset k1 f1 v1
- 获取数据:hget k1 f1
- 删除属性(value中的key):hdel k1 f1
- 删除key:del k1
- 增加数字:hincrby k1 f1 数值
- 存储多个:hmset k1 f1 v1 f2 v2
- 获取多个:hmget k1 f1 f2
- 获取所有属性及属性值:hgetall k1
- 只获取所有属性名:hkeys k1
- 只获取所有属性值:hvals k1
- 判断属性是否存在(存在返回1,不存在返回0):hexists k1 f1
- 获取长度(有多少个属性):hlen k1
def main(args: Array[String]): Unit = {
val jedis = new Jedis("172.16.100.100", 6379)
jedis.auth("123456")
//选择使用的DB
jedis.select(2)
//存储数据
jedis.hset("ln", "sy", "5000")
jedis.hset("ln", "dl", "6000")
jedis.hincrByFloat("ln", "sy", 88.88)
val mp: util.Map[String, String] = jedis.hgetAll("ln")
//隐式转换,使其支持Java和scala集合互相转换
import scala.collection.JavaConverters._
for(entry <- mp.asScala) {
println(s"key: ${entry._1}, value: ${entry._2}")
}
jedis.close()
}
List类型
Redis的list使用的是linkedlist,linkedlist有两种方式:队列、堆栈。
在linkedlist中的头插法 和尾插法
队列中的名称: 入栈 push,出栈(弹栈) pop
- 插入到队首(返回值为当前列表的容量):lpush k1 v1 v2 v3
最后v3为队首 - 插入到队尾:rpush k1 v1 v2
最后v2为队尾 - 查看数据(start、end为下标,从0开始,包括start和end):lrange k1 start end
lrange list1 0 -1 查看所有(-1表示最后一个) - 从左边删除n个数据(n不指定默认为1):lpop k1 n
- 从右边删除n个数据(n不指定默认为1):rpop k1 n
- 获取指定下标元素:lindex k1 index
- 从前往后在指定元素前面/后面加入值(只在第一个元素后加):linsert k1 before/after 元素 值
- 从前往后删除n个element元素:lrem k1 n element
- 修改数据:lset k1 index v1:将下标为index的值设置为v1
- 获取列表长度:llen k1
public static void main(String[] args) {
Jedis jedis = new Jedis("172.16.100.100", 6379);
jedis.auth("123456");
jedis.select(8);
jedis.rpush("lst8", "1", "2", "3", "4", "5", "6");
jedis.lpop("lst8", 1);
//在指定元素的后面
jedis.linsert("lst8", ListPosition.AFTER, "3", "5");
//获取指定下标的元素
String res1 = jedis.lindex("lst8", 5);
//删除指定位置的数据
// lrem lst8 2 5 (从左面开始删除,最多删除两个5)
jedis.lrem("lst8", 2 , "5");
jedis.close();
}
Set类型
List和set的区别:
List是有序且可重复
Set是无序唯一。
- 存储数据:sadd k1 v1 v2 v3 v4
- 取出所有数据:smembers k1
- 删除元素:srem k1 v1
- 判断元素是否存在(0不存在,1存在):sismember k1 v1
运算命令:在set中可以进行差集、交集、并集的运算
- 差集(属于k1并且不属于k2的元素构成的集合):sdiff k1 k2
- 交集(属于k1且属于k2的元素构成的集合):sinter k1 k2
- 并集(属于k1或者属于k1的元素构成的集合):sunion k1 k2
def main(args: Array[String]): Unit = {
val jedis = new Jedis("172.16.100.100", 6379)
jedis.auth("123456")
jedis.select(9)
//向set中添加数据
jedis.sadd("s1", "a", "b", "c", "d")
jedis.sadd("s2", "a", "f", "e", "d", "h")
//求交集
val res1: util.Set[String] = jedis.sinter("s1", "s2")
//导入隐式转换
import scala.collection.JavaConverters._
for (elem <- res1.asScala) {
println(elem)
}
//求差集
val res2: util.Set[String] = jedis.sdiff("s1", "s2")
for (elem <- res2.asScala) {
println(elem)
}
}
sortedset(zset)类型
有序集合和set以及list的区别
Zset是唯一且有序的。
Zset是通过 score 来进行排序的。
- 存储数据:zadd k1 score1 v1 score2 v2 score3 v3
在redis存储中通过分数升序排序 - 查看元素(升序排序,取从start到end的数据):zrange k1 start end
- 查看元素(降序排序,取从start到end的数据):zrevrange k1 start end
- 查看元素和值:zrange k1 start end withscores
- 查看指定元素的score值:zscore k1 v1
- 删除元素:zrem k1 v1
- 增加某元素的分数,返回值是更改后的分数:zincrby k1 count v1
- 根据升序排序,获取元素排名:zrank k1 v1
- 根据降序排序,获取元素排名:zrevrank k1 v1
def main(args: Array[String]): Unit = {
val jedis = new Jedis("172.16.100.100", 6379)
jedis.auth("123456")
jedis.select(11)
jedis.zincrby("phone", 3000.5, "nova9")
jedis.zincrby("phone", 3000.5, "nova9")
jedis.zincrby("phone", 6000, "p50")
jedis.zincrby("phone", 6000, "p50")
jedis.zincrby("phone", 8000, "ip13")
jedis.zincrby("phone", 8000, "ip13")
jedis.zincrby("phone", 4000, "mi11")
//按照得分的升序取数据(升序的前3)
val res1: util.Set[String] = jedis.zrange("phone", 0, 2)
import scala.collection.JavaConverters._
for (elem <- res1.asScala) {
println(elem)
}
//按照得分的降序取数据(topN)
val res2: util.Set[Tuple] = jedis.zrevrangeWithScores("phone", 0, 2)
for (tp <- res2.asScala) {
println(s"val: ${tp.getElement}, score: ${tp.getScore}")
}
}
Redis 连接池
object JedisConnectionPool {
//jedis连接池的配置
val config = new JedisPoolConfig()
//连接池的最多连接数量
config.setMaxTotal(50)
//连接池的最大活跃连接数量(最多保留20个连接。需要20个以下连接时,连接数量为20,需要20个以上时,再接着创建)
config.setMaxIdle(20)
//对使用的连接进行检查
config.setTestOnBorrow(true)
//从左到右参数分别是 配置对象 主机 端口号 连接超时时间 连接密码
val pool = new JedisPool(config, "linux1", 6379, 10000, "123456")
def getConnection(): Jedis = {
pool.getResource
}
}
//获取连接
val jedis = JedisConnectionPool.getConnection()
//释放连接
jedis.close()