前面使用到的mysql数据库会出现以下问题
由于用户量增大,请求数量也随之增大,数据压力过大
多台服务器之间数据不同步
多台服务器之间的锁,已经不存在互斥性了。
Redis(Remote Dictionary Server)即远程字典服务,Redis是C语言编写,Redis是一款基于Key-Value的NoSQL(非关系型数据库),而且Redis是基于内存存储数据的.Redis还提供了多种持久化机制,性能可以达到110000/s读取数据以及81000/s写入数据,Redis还提供了主从,哨兵以及集群的搭建方式,可以更方便的横向扩展以及垂直扩展。
关系型数据库是基于关系表的数据库,最终会将数据持久化到磁盘上,而nosql数据库是基于特殊的结构,并将数据存储到内存的数据库。
从性能上而言,nosql数据库要优于关系型数据库,从安全性上而言关系型数据库要优于nosql数据库,所以在实际开发中一个项目中nosql和关系型数据库会一起使用,达到性能和安全性的双保证。
./redis-server
客户端
关闭服务
若采用后台运行需要修改相应配置文件
由于软件安装位置为/usr/local,所以先进入/usr/local目录
进入redis-6.2.4目录
进入bin目录
启动服务端,注意这里的启动命令后带的redis.conf是我们前面为了后台形式启动所修改的配置文件,让启动命令运行指定的配置文件
启动客户端
5.2.1
常用的5种数据结构:
另外三种数据结构:
value最常用的五种数据类型:
set key value
设定key持有指定的字符串value,如果该key存在则进行覆盖操作,总是返回"OK"
setnx key value
只有在key不存在是添加
get key
获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,因为get命令只能用于获取String value,如果该key不存在,返回null
getset key value
先获取该key的值,然后在设置该key的值。
incr key
将指定的key的value原子性的递增1.如果该key不存在,其初始值为0,在incr之后其值为1。如果value的值不能转成整型,如hello,该操作将执行失败并返回相应的错误信息。
decr key
将指定的key的value原子性的递减1.如果该key不存在,其初始值为0,在incr之后其值为-1。如果value的值不能转成整型,如hello,该操作将执行失败并返回相应的错误信息。
incrby key increment
将指定的key的value原子性增加increment,如果该key不存在,器初始值为0,在incrby之后,该值为increment。如果该值不能转成整型,如hello则失败并返回错误信息。
decrby key decrement
将指定的key的value原子性减少decrement,如果该key不存在,器初始值为0,在decrby之后,该值为decrement。如果该值不能转成整型,如hello则失败并返回错误信息。
append key value
如果该key存在,则在原有的value后追加该值;如果该key不存在,则重新创建一个key/value。
setex key seconds value
expire key seconds
过期时间
ttl
查看生存时长
lpush key value1 value2...
在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。插入成功,返回元素的个数。
rpush key value1 value2…
在该list的尾部添加元素。
lrange key start end
获取链表中从start到end的元素的值,start、end可为负数,若为-1则表示链表尾部的元素,-2则表示倒数第二个,依次类推….
lpushx key value
当key存在时,在头部插入value,否则将不插入
rpushx key value
在key的尾部插入value
lpop key
返回并弹出指定的key关联的链表中的第一个元素,即头部元素。
rpop key
从尾部弹出元素。
rpoplpush resource destination
将链表中的尾部元素弹出并添加到头部。
llen key
返回指定的key关联的链表中的元素的数量。
lset key index value
设置链表中的index的脚标的元素值,0代表链表的头元素,-1代表链表的尾元素。
lrem key count value
删除count个值为value的元素,如果count大于0,从头向尾遍历并删除count个值为value的元素,如果count小于0,则从尾向头遍历并删除。如果count等于0,则删除链表中所有等于value的元素。
linsert key before|after pivot value
在pivot元素前或者后插入value这个元素。
sadd key value1 value2…
向set中添加数据,如果该key的值已有则不会重复添加。
smembers key
获取set中所有的成员。
scard key
获取set中成员的数量。
sismember key member
判断参数中指定的成员是否在该set中,1表示存在,0表示不存在或者该key本身就不存在。
srem key member1 member2…
删除set中指定的成员。
srandmember key
随机返回set中的一个成员。
sdiff key1 key2
返回key1中有但key2中无的成员,而且与key的顺序有关,即返回差集。
sdiffstore destination key1 key2
将key1、key2相差的成员存储在destination上。
sinter key[key1,key2…]
返回交集。
sinterstore destination key1 key2
将返回的交集存储在destination上。
sunion key1 key2
返回并集。
sunionstore destination key1 key2
将返回的并集存储在destination上
zadd key score member score2 member2 …
将所有成员以及该成员的分数存放到sorted-set中。
zcard key
获取集合中的成员数量。
zcount key min max
获取分数在[min,max]之间的成员。
zincrby key increment member
设置指定成员的增加的分数。
zrange key start end [withscores]
获取集合中脚标为start-end的成员,[withscores]参数表明返回的成员包含其分数。
zrangebyscore key min max withscores
返回分数在[min,max]的成员并按照分数从低到高排序。[withscores]:显示分数;[limit offset count]:offset,表明从脚标为offset的元素开始并返回count个成员。
zrank key member
返回成员在集合中的位置。
zrem key member[member…]
移除集合中指定的成员,可以指定多个成员。
zscore key member
返回指定成员的分数。
hset key field value
为指定的key设定field/value对(键值对)。
hgetall key
获取key中的所有filed-vaule。
hget key field
返回指定的key中的field的值。
hmset key fields
设置key中的多个filed/value。
hmget key fileds
获取key中的多个filed的值。
hexists key field
判断指定的key中的filed是否存在。
hlen key
获取key所包含的field的数量。
hincrby key field increment
设置key中filed的值增加increment,如:age增加20。
keys patten
获取所有与patten匹配的key,*表示任意字符,?表示一个字符。
del key1 key2....
删除指定的key。
exists key
判断该key是否存在,1表示存在,0表示不存在。
rename key newkey
为当前key重命名。
expire key second
为当前key设置过期时间(单位:秒)。
ttl key
查看当前key剩余过期时间。
type key
查看当前key类型。
flushall
删除所有key
Jedis:可以直接在IDEA中使用Redis
修改/usr/local/redis-5.0.4/bin目录下的redis.conf配置文件,然后启动redis服务端
将绑定127.0.0.1注释掉,然后把保护模式关掉
如需设置密码,可以使用以下两种方式:
方式一:通过修改 redis.conf 文件,设置Redis的密码校验
requirepass 密码
方式二:在不修改 redis.conf 文件的前提下,在第一次链接Redis时,输入命令:Config set requirepass 密码
取消密码 Config set requirepass ''
后续连接redis客户端的时候,需要先 AUTH 做一下校验
127.0.0.1:6379> auth 密码
创建Maven工程,导入依赖
redis.clients
jedis
3.1.0
com.alibaba
fastjson
1.2.58
org.projectlombok
lombok
1.18.12
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer uid;
private String username;
private String password;
}
测试类
public class JedisDemo {
// 通过java程序访问redis数据库
// 获得单一的jedis对象操作数据库
@Test
public void test1() {
//获得连接对象
Jedis jedis = new Jedis("192.168.153.132", 6379);
//认证密码
//jedis.auth("root");
//获得之前redis中存储的数据
String name = jedis.get("name");
System.out.println(name);
//存储数据
jedis.set("password", "123");
System.out.println(jedis.get("password"));
//关闭
jedis.close();
}
//通过jedis的pool获得jedis连接对象
@Test
public void test2() {
// 创建池子的配置对象
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(30);// 最大闲置个数
poolConfig.setMinIdle(10);// 最小闲置个数
poolConfig.setMaxTotal(50);// 最大连接数
// 创建一个redis的连接池
JedisPool pool = new JedisPool(poolConfig, "192.168.153.132", 6379);
// 从池子中获取redis的连接资源
Jedis jedisPoolResource= pool.getResource();
// 创建User类进行存储
User user = new User(1001, "李四", "123");
// 将对象转换成json存储
jedisPoolResource.set("user", JSON.toJSONString(user));
String db_user = jedisPoolResource.get("user");
// 返回json数据
System.out.println(db_user);
// 返回User类型
System.out.println(JSON.parseObject(db_user,User.class));
// 关闭资源
jedis.close();
pool.close();
}
}
Redis中的事务和MySQL中的事务有本质的区别,Redis中的事务是一个单独的隔离操作,事务中所有的命令都会序列化,按照顺序执行,事务在执行的过程中,不会被其他客户端发来的命令所打断,因为Redis服务端是个单线程的架构,不同的Client虽然看似可以同时保持连接,但发出去的命令是序列化执行的,这在通常的数据库理论下是最高级别的隔离。
Redis中的事务的作用就是串联多个命令,防止别的命令插队。
常用命令:multi、exec、discard、watch、unwatch
当输入multi命令时,之后输入的命令都会被放在队列中,但不会执行,直到输入exec后,Redis会将队列中的命令依次执行,discard用来撤销Exec之前被暂存的命令,并不是回滚。
watch/unwatch
在执行multi之前,先执行watch key1 [key2...] ,watch提供的乐观锁功能(初始时一个版本号,exec之后会更新当前版本号),在你exec的那一刻,如果被watch的键发生过改动,则multi到exec之间的指令全部不执行。
watch表示监控,相当于加锁,但在执行完exec时就会解锁。
unwatch取消所有锁。
1.单独的隔离操作
事务中的所有命令都会序列化,然后按顺序执行,在执行过程中,不会被其他客户端发送的命令打断。
2.没有隔离级别的概念
队列中的命令没有被提交之前都不会执行。
3.不能保证原子性
Redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,不会回滚