赞
踩
1.它可以作为数据库。实现点赞,关注,排行等对性能要求极高的互联网需求
2.它最长用来做缓存,是实现分布式缓存的首先中间件。
3.它可以用来做计算工具,能用很少的代价计算用户在线的天数等数据。
4.它还可以实现分布式锁,可以作为消息队列使用。
redis是一种基于键值对的NoSQL数据库,而键值对的值有多种数据结构和算法构成
redis存放在内存中,因此它的速度非常惊人,远超关系型数据库。
关系型数据库是基于二维数据表来存储数据的,他的数据格式更加严谨,并且支持关系查询
关系型数据库的数据存储在硬盘上,可以存放大量数据,但是他的性能没有redis强大。
1.redis支持5种核心的数据类型。分别是列表,字符串,哈希,集合,有序集合。
2.redis还提供了Geo,Bitmap,HyperLogLog等。他们都是有上面的5种核心数据类型来实现的。
3.redis在5.0新增加了Streams数据类型,他是一个功能强大的,支持多播的,可持久化的消息队列。
1.redis的大部分操作都是在内存中实现的。
2.对服务端程序来说,切换线程和锁通常是性能杀手,而单线程避免了线程切换和竞争所产生的消耗。
3.redis在IO多路复用的机制。使其在网络IO操作中能并发的处理大量的客户端请求,实现高吞吐率。
关于Redis的单线程架构实现,如下图:
redis是单线程的,主要指的是网络IO和键值对的读写是有一个线程实现的,
而Redis的其他功能如持久化,异步删除,集群数据同步等,则是依赖其他线程来执行的
所以说redis是单线程的只是一种说法,而它的底部实现并不是单线程的。
set
1.集合中的元素是无序的,不可重复的。一个集合中最多保存2^32-1个元素。
2.除了支持元素的增删改查,还支持对多个集合去交集,并集,差集。
zset
1.有序集合保留了元素不可重复的特点。
2.有序集合给每个元素一个分数,并以此作为排序的依据。
3.有序集合不能包含相同的元素,但是元素的分数可以相同。
很多时候,要确保事务中的数据没有被其他客户端修改才执行该事务。redis提供了watch命令来解决这类问题。
这是一种乐观锁的机制,客户端通过watch命令,要求服务器对一个或多个key进行监视。
如果客户端在执行事务之前,这些key值发生了变化,则服务器将拒绝执行客户端提交的事务,并向他返回一个空值。
列表是线性有序的数据结构,它内部的元素是可以重复的,并且一个列表最多存储2^32-1个元素。
列表的常用命令:
lpop/rpop : 从列表的左侧或右侧弹出一个元素。
lpush/rpush : 从列表的左侧或右侧添加数据。
lindex : 返回指定索引处的数据。
lrange : 指定索引范围,并返回这个范围内的数据。
blpop/brpop : 从列表左侧或右侧弹出一个元素,若列表为空,则进入阻塞状态。
1.对于热点数据不设置过期时间。使其达到"物理"上的永不过期,进而避免缓存击穿的问题。
2.在设置过期时间时,附加一个随机数,避免大量的key同时过期,导致缓存雪崩。
sexnx返回的是整数类型,返回1表示设置值成功。返回0表示设置值失败(key已经存在)。
一般我们不建议使用sexne来实现分布式锁。为了避免出现死锁的情况,我们要给锁设置一个过期时间。
而sexnx命令和设置过期时间的命令不是原子的。可能加锁成功,而设置过期时间失败,依然存在死锁隐患。
对与这种情况,redis改进了set命令,给他增加了nx选项,启用该选项set命令的效果就跟setnx一样了。
采用redis实现分布式锁,就是在redis里村一份代表锁的数据,通常用字符串即可。采用改进后setnx来实现。
问题:
看起来已经很完美了,但实际上还有隐患,如下图。进程A在任务没有执行完毕时,锁已经到期被释放了。等进程A的任务执行结束后,它依然会尝试释放锁,因为它的代码逻辑就是任务结束后释放锁。但是,它的锁早已自动释放过了,它此时释放的可能是其他线程的锁。
在加锁时就要给锁设置一个标识,进程要记住这个标识。当进程解锁的时候,要进行判断,是自己持有的锁才能释放,否则不能释放。可以为key赋一个随机值,来充当进程的标识。
解锁时要先判断、再释放,这两步需要保证原子性,否则第二步失败的话,就会出现死锁。而获取和删除命令不是原子的,这就需要采用Lua脚本,通过Lua脚本将两个命令编排在一起,而整个Lua脚本的执行是原子的。
redis支持RDB持久化,AOF持久化,RDB-AOF混合持久化这三种持久化方式。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。