Redis使用总结

一、Redis是什么?

官方回答:
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
redis的官网地址,非常好记,是redis.io。(域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地),Vmware在资助着redis项目的开发和维护。
一句话概括:
Redis是C语言开发的一个开源的(遵循BSD协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件......

二、Redis特点:

a、nosql 数据库
b、性能高,数据在内存中,读写快,支持10W QPS。
c、单线程,线程安全。
d、支持多种数据类型 strings、hashes、lists、set、zset(sorted set --有序集合)等
e、支持数据持久化
f、主从复制(哨兵监控,高可用)

三、五种数据类型 (strings、hashes、lists、set、zset)

redisObject 是Redis的核心对象 对象中包含:type(类型)、encoding(编码方式)、notused(不使用 对齐位)、lru(LRU 时间 相对于 server.lruclock)、refcount(引用计数)、*ptr(指向对象的值)
使用中我们关注的主要是type 也就是strings、hashes、lists、set、zset这五种数据类型,以及encoding 对象底层的编码 包含 raw、int、ht、zipmap、linkedlist、ziplist、intset。
底层参考:https://blog.csdn.net/u012394095/article/details/81205439 ,https://blog.csdn.net/hjjomiqpl/java/article/details/51911085
Java开发者角度来理解Redis五大数据类型
String类型
String类型是Redis最基本的类型,一个key对应一个value(可以是数字)。String类型是二进制安全的,意思是Redis的String类型可以存放任何数据(图片、序列化对象等),但是有大小限制 最大为512M。
Hash类型
hash是一个键值对(key-value)的集合,适合存放对象。hget、hset、hgetall等常用命令。
List类型
list列表存放的的是简单的字符串列表,安插入顺序排序。可以添加元素的头(lpush)和尾(rpush),也可以获取头(lpop)和尾(rpop),或者获取一部分(lrang)等。
Redis的list是一个双向链表,可以用作消息队列。
Set类型
set是String类型的无需集合。通过hashtable实现。set中的元素是无序的、不可重复的。常用命令 sadd(添加)、scard(获取元素个数)、 spop(获取元素)、smembers(查询所有)、sismember(判断是否在set集合)、sunion(集合并集)等。
Zset(Sorted Set)类型
Zset 是一个有序的不重复元素的集合,通过权重score参数来完成元素的排序。
Sorted Set 的内部使用 HashMap 和跳跃表(skipList)来保证数据的存储和有序,HashMap 里放的是成员到 Score 的映射。
而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 Score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

四、Java语言中Redis的使用

一种是通过Redis大Java API RedisTemplate 来使用,另一种是通过spring集成Redis通过注解使用(注解使用参考:https://www.cnblogs.com/xingtangxiaoga/p/11686355.html)

五、Redis的使用问题, 雪崩、穿透、击穿、数据一致性

Redis官方提供的数据可以达到 100000+ 的 QPS(每秒内的查询次数)
Redis雪崩,大量请求(一堆key)访问到Redis缓存层,而同一时间这一堆key的Redis缓存失效。缓存不起作用,直接访问到缓存的下层(例如:DB)。
问题解决:Redis缓存时间增加随机数,避免同时失效。或者将热点数据设置永不过期,通过程序更新缓存。总得来说,就是防止Redis缓存数据,大量同时过期。
Redis穿透,就是不断的请求缓存跟下层服务(例如:DB)没有的数据。请求就会直达下层服务(例如DB)导致下层服务压力过大而崩溃。
问题解决:系统程序上可以做访问前校验,拦截非法请求。Redis中布隆过滤器(Bloom filter)这个也可以有效防止Redis穿透。
布隆过滤器 原理是利用数据结构以及算法快速判断key是否存在,不存在直接返回,存在再去查下层服务。
Redis击穿,是不断并且大量的请求访问一个热点key,这个key在某一时间点失效,导致请求全部访问到下层服务,下层服务出现大并发,导致下层服不堪重负务宕机。
问题解决:设置热点key不过期,通过程序更新key,或者如果是Redis集群还可以分批更新各个节点的热点key。根本目的就是不让热点key缓存在大并发是失效。
数据强一致性,这个不能根本解决,只能看对数据延迟的容忍性。可以通过优化策略尽量保证数据一致性。

六、Redis的优缺点

Redis是基于内存的,单线程的,CPU不是瓶颈,内存以及网络带宽最有可能导致瓶颈。
Redis速度快,绝大部分请求是纯粹的内存操作,数据结构简单,单线程避免了上线问的切换和竞争,不存在CPU切换,不存在各种锁问题。使用多路复用IO,非阻塞IO。

七、Redis与memcached的对比

性能:都比较高,TPS方面redis和memcache差不多
操作的便利性:memcache数据结构单一,redis丰富一些
数据存储及持久化:memcached不支持内存数据的持久化操作,所有的数据都以in-memory的形式存储。
  redis支持持久化操作。
  1)RDB快照
  Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。我们可以通过Redis的save指令来配置RDB快照生成的时机,比如配置10分钟就生成快照,也可以配置有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。
Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。同时,Redis的RDB文件也是Redis主从同步内部实现中的一环。RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的。
  2)AOF日志
  AOF日志的全称是append only file,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。只有那些会导致数据发生修改的命令才会追加到AOF文件。每一条修改数据的命令都生成一条日志,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。
  AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的流程。在Redis中对AOF调用write写入后,通过appendfsync选项来控制调用fsync将其写到磁盘上的时间,下面appendfsync的三个设置项,安全强度逐渐变强。
  • appendfsync no 当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
  • appendfsync everysec 当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
  • appednfsync always 当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。
  对于一般性的业务需求,建议使用RDB的方式进行持久化,原因是RDB的开销并相比AOF日志要低很多,对于那些无法忍数据丢失的应用,建议使用AOF日志。
  Redis高可用参考:https://www.jianshu.com/p/7d5fbf90bcd7
数据一致性(事务支持)
  Memcache 在并发场景下,用cas保证一致性
  redis可以保证一串 命令的原子性,中间不会被任何操作打断
 

原文地址:https://www.cnblogs.com/xingtangxiaoga/p/12724975.html