首页 > 数据库 >关于Redis的应用

关于Redis的应用

时间:2023-05-21 14:05:53浏览次数:62  
标签:缓存 hash string Redis memcache 关于 应用 内存


写这篇文章主要是在开发www.ximalaya.com的feed(登录首页看到的好友动态,未登录是看不到的

关于Redis的应用_Redis

)模块使用Redis的一些经验。(www.ximalaya.com是音频为传播介质的SNS网站,喜欢的同学不妨用一用,也有APP的,还是一款非常不错的产品。音乐,相声,有声小说等等 一网打尽)。关于Feed本身的讨论以后再专门发博,有兴趣的同学也可以先开博,然后共同讨论。

Redis这个神器已经在互联网名声大作了,主要是对关系型数据库的补充。因为在大并发下,IO往往是性能的瓶颈,所以把数据尽量放到离cpu近的地方,是解决IO瓶颈的有效途径。呵呵,谁都想把数据放到寄存器,L1 L2 L3cache上,因为这些都是离cpu很近的地方,在一到几十个cpu时钟周期内能读到数据,但是这些缓存空间实在太小了。所以只能把最热的数据去征用这部分缓存。那么比这些数据稍微"冷"一点,但又经常访问的数据怎么办呢?目前最好的途径就是放在内存中。redis,memcache这类的内存数据库就是这样做的。放到内存中就意味着cpu可以在几百个时钟周期内能读到数据。一般服务器配置也是16个G内存吧,在64位系统下,理论可以让你的程序完全占用这16G内存。既然可以在这么快速的读到数据,那么采用什么算法读数据呢?线性查找?那又是浪费cpu时钟周期的。查找最快的莫过于hash表,它的时间复杂度是O(1)。所以本质来说Redis,memcache都是在内存上的hash数据库。Redis和memcache在互联网的应用都比较多,如何选择呢?当然两个都是解决缓存问题的神器,我更趋向于Redis这个神器。原因如下: 

1,丰富的数据结构,string,hash,list,set,sortset等数据结构都支持,而memcache仅支持string(相当于key-value结构,这里说string是说的redis中的string),而其他数据结构也是在互联网中常用的。如果你想用就只能选Redis了。

2,可持久化,memcache是不支持持久化的。那么对于缓存的应用,一旦memcache服务挂掉了,内存的数据就丢失了,那么可以快速重启是吧,内存的数据全没了,这时候就有一个热点故障。或许你说可以通过预热来解决这个问题。但是Redis可以不需要预热,他会从rdb或aof中自动重建内存。之前的Redis版本中重启是需要花费很长时间的,但是在2.6版本后这个过程非常快了。即使是开启aof的情况下重启,9G的数据也只需要六分半的时间(www.ximalaya.com的真实案例)。这主要是Redis作者对aof的命令进行了合并,加快了重启的速度。对于需要持久化的应用,memcache就无能为力了,或许你可以选择memcached,当然Redis任然是更好的方案。

3,至于速度方面,Redis不会差于memcache,主要是Redis采用了epoll进行通信吧。

4,memcache是多线程的,Redis是单线程的,虽然更喜欢多线程的应用。但貌似Redis在单线程的操作下速度一点也不逊色,而且让操作更安全了,不需要锁,也不需要线程切换的开销了。Redis在备份rdb的时候会fork一个进程出来,让主进程不受任何影响。

Redis这个服务器,对于高并发快速读写,原子计数,消息队列,实时排名都是实用的。对于互联网网站来说这些都是频繁使用,也是关系型数据库比较头疼的。恰好以上提到的用途都在生成环境中有用到。根据实际经验来看,Redis还是实用于缓存,原子计数。对于持久化存储真的不太适合。因为它会把数据都加载到内存中(如果内存不够用会load到虚拟内存,但这是一个悲剧)。当然如果你用于持久存储的数据是有限的,那么也是非常适合的。但是对于数据需要无限增长的业务,这个真不太适合。网站登录首页的feed,收件箱列表全部放在Redis中。收件箱列表随着注册用户的增长而增长,需要消耗的内存也是逐步增长。为了缓解这个内存压力,客户端做了sharding,实现内存分片。这虽然能够解决内存问题,但需要更多的机器来做。所以我也一直在想怎么来缓解这块内存的问题。扯远了以后在把关于这方面的思考写出来吧。现在还是讲一讲Redis的应用。

在缓存中的应用:

缓存中的应用在memcache中就是对key-value的缓存。它之所以能快,是因为它是存放在内存中的hash数组。内存,hash。这两个关键词就足够解释为什么读写快了。现在对于速度和容量都比合适的存储也就内存最合适吧。ssd的速度快,容量也大。但需要在价格和寿命上有更大的突破才能被广泛使用。况且,ssd的速度比起主存来说还是有一定差距的。

下面对redis中string hash list set sortset分别说下使用场景。

string:这是使用最简单,也是非常频繁的一种数据类型。它就是一种单纯的key-value对。适用于那些通过键直接找值得业务场景。get string的时候需要用到mutil get,这是可以减少网络通信的,也是非常高效的。

hash:hash类型是对于string类型的补充,主要是有些key有共同的特征,不如一个用户对应的多个值,那么用户id只需要出现一次就可以了,对于string来说是需要出现多次的。所以hash是比string更节约了存储。同样hash也可以对多列mutil get,一次网络传输就可以得到所有值。

list:适用于不排重,且有序的操作。这其实就是一个队列,先进先出。放不排重的列表很有用。曾经还用它来做过队列。但队列还是用专门的消息队列更好,因为list不支持消息应答的,也就是不能确保你的消息被处理成功。

set:相当于java中的HashSet,用于排重的列表,但是无序的,在无序的列表还是很适合的。

sortset:这是有序,排重的列表,相当于java中的TreeSet。不过TreeSet是用的红黑树算法,sortset是用的skip table。sortset是很有用的一种数据结构,之前提到的收集箱列表就是用的sortset存放。不过这个数据结构很耗存储。特别是不是用ziplist时。后面谈优化的时候具体说。

 

Redis中的一些常见优化:

Redis中最好不要开启VM,在2.6版本也是默认关闭的。即使把vm指定到ssd中,redis作者也是反对的。

对于cache的redis,一定要设置最大内存。这样后台线程的LRU数据淘汰策略才能被触发。所以在未设置最大内存的情况下,对数据设置过期时间往往是无效的。这是一个坑,曾经跳到这个大坑里面,通宵解决性能问题。切记!

ziplist很有必要设置大一点。比如之前提到的收件箱长度是500条,但有些时候长度可能达到700条,所以把ziplist设置成1024会是一个好的策略。下面具体介绍下这几个参数:

 



hash-max-ziplist-entries:针对hash类型,只要hash的filed在这个范围内使用紧凑存储,这可以节约存储,也是为什么要尽量使用hash少使用string的理由,特别是在原子计数的时候,对一个用户可能要记录很多数量,一定要采用hash的策略,这是非常有用的。当然这个值绝不是越大越好,通常不要超过1024



hash-max-ziplist-value:hash的value的大小,在这个大小内会使用紧凑存储。这个值也不是越大越好,最好不要超过512。



list-max-ziplist-entries



list-max-ziplist-value



这两个参数和hash用法一样。不过这是针对list类型的。



zset-max-ziplist-entries



这个参数是针对sortset。在这个范围内,将不使用红黑树,是线性查找,所以这个值也不能太大,一般不要超过1024。




Redis的扩容问题:
Redis扩容目前来还是比较麻烦一点的。因为服务端是不支持数据的sharding的。需要在客户端做sharding。通常有两种sharding策略。一致性hash和非一致性hash。
对于非一致性hash:
可以实现把Redis实例事先切分成多个数据库,比如32或64个库。或者在同一个机器上启多台Redis实例,这样还可以利用多核系统多进程的优势提高并发。当单台机器上的Redis难以支撑时。把这些实例迁移到其他机器上,这样就变相的减轻了单台机器的压力。还可以把数据库切分开,分别放到多台机器上启动。这种做法最大的缺点是,当单台Redis实例的每个数据库都无法支撑数据时,麻烦就来了。这是需要程序把数据迁移出来,这个迁移往往是很耗时的,也是很容易出错的。对于线上的产品这往往是不可以接受的。那么就一致性hash登场吧。
对于一致性hash:
对于一致性hash的介绍可以搜索一下。主要的优势就是,在扩容的时候只需要移动受影响的节点。对于整个集群来说,这些受影响节点的数据是非常少的。如果对于cache来说,加一台机器,几乎不需要移动数据。让cache miss重建缓存也是可以的。当然这个得针对具体应用评估。不要因此而热点故障,挂网站了,呵呵。一致性hash的优势是可以任意加机器解决容量问题。理论上只要机器够,容量就不是问题。

嗯,暂时就写到这里吧,redis中的注意事项还很多,应用也绝不限于此,具体的官方文档已经介绍的很详细。用到的同学,可以发表和补充下Redis的其他用途。如有任何纰漏还多多指出,谢谢!

标签:缓存,hash,string,Redis,memcache,关于,应用,内存
From: https://blog.51cto.com/u_2700990/6319180

相关文章

  • ExtJS应用架构设计(三)
    原文:http://www.sencha.com/learn/architecting-your-app-in-ext-js-4-part-3/?mkt_tok=3RkMMJWWfF9wsRonuKrLZKXonjHpfsX56uolXaS2lMI%2F0ER3fOvrPUfGjI4AT8t0dvycMRAVFZl5nR9dFOOdfQ%3D%3D      在该系列文章的前两篇文章中(一、二),我们探讨了如何使用ExtJS4的新特性构建一......
  • ExtJS应用架构设计(二)
    原文:http://www.sencha.com/learn/architecting-your-app-in-ext-js-4-part-2/      在《ExtJS应用架构设计》一文,我们探讨了如何使用ExtJS构建一个潘多拉风格的应用程序。我们采用了MVC架构,并将它应用到一个比较复杂的用户界面,应用中带有多个视图和模型。在这篇文章中,我......
  • HTML5应用性能调优工具WAPA – 使用篇
    utm_campaign=CSDN&utm_source=intel.csdn.net&utm_medium=Link&utm_content=others-WAPAHTML5应用性能调优工具WAPA–使用篇DaweiCheng程大伟... 于 星期四,27/02/2014-18:42 提交本篇文章将介绍怎样来使用WAPA进行分析。WAPA提供了两种使用方式,一种是图形化的web使......
  • web应用开发 -- 课堂作业 个人简介
    文章目录文件结构下载[https://api.hongbin.xyz:3002/downloadSource/code.zip](https://api.hongbin.xyz:3002/downloadSource/code.zip)代码文件结构下载https://api.hongbin.xyz:3002/downloadSource/code.zip代码jianjie.cssbody{min-height:140vh;}header{back......
  • 阿里云轻量应用服务器端口开通教程
    阿里云轻量应用服务器端口怎么开启?轻量应用服务器端口在防火墙中打开,云服务器ECS端口在安全组中开启,阿里云百科以80端口为例来详细说下阿里云轻量应用服务器端口开放图文教程,其他的端口如8080、3306、443、1433也是同样的方法进行开启端口:轻量应用服务器开通端口教程1、登录到轻量......
  • 在java中使用lua脚本操作redis
    前言众所周知,redis可以执行lua脚本,至于为什么要用lua脚本来操作redis,自行百度咯开始Bean类packagecn.daenx.myadmin.common.config.redis;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.......
  • redis-cli 使用lua脚本笔记
    前言众所周知,redis可以执行lua脚本,至于为什么要用lua脚本来操作redis,自行百度咯先来讲一下最简单的方式,关于如何在javaspringboot里用lua脚本,请查看我另一篇文章:https://www.cnblogs.com/daen/p/17418024.html更为详细的资料请参考以下文章https://blog.csdn.net/jiayibingd......
  • 关于Java接口实现问题
    publicinterfaceInterfaceClass{/***jdk1.7只能有抽象方法,子类是**抽象类**时,方法就可以实现也可以不实现*/publicabstractvoidmethod();/***jdk1.8新增静态方法,默认方法**静态方法子类不能实现*/publicstaticvoidmethod1(){}/**......
  • 场论的基本公式与应用
    场论的基本内容与应用场论的基本公式梯度我们导出过标量函数\(f\)的全微分和偏导数的关系:\[df(x,y,z)=\dfrac{\partialf}{\partialx}dx+\dfrac{\partialf}{\partialy}dy+\dfrac{\partialf}{\partialz}dz\]它表示函数增量的线性部分可以表示为各个坐标方向的偏导数与自......
  • golang操作redis
    首先,基于docker查看redis镜像dockerps-a然后执行dockerrun-p6379:6379-dredis:latestredis-server,将端口映射到本机最后执行dockerexec-ti13e638ea1036redis-cli-h0.0.0.0-p6379执行链接操作......