redis应用场景与最佳实践
2019独角兽企业重金招聘Python工程师标准>>>
Redis作为当下最流行的内存Nosql数据库,有着诸多的应用场景。在不同的应用场景,对Redis的部署、配置以及使用方式都存在的不同地方。根据我的工作经验,把队列、缓存、归并、去重等应用场景的“最佳实践”整理如下。
本文中的所有代码,均可在github上找到:https://github.com/huyanping/RedisStudy
队列
Redis的list数据结构经常会被用作队列来使用,常用的方法有:lpop/rpop、lpush/rpush、llen、lindex等。由于Redis提供的list是一个双向链表,我们也可以把list当做栈来使用。使用Redis的list作为队列时,需要注意以下几个问题:
- 队列中的数据一般具有比较高的可靠性要求,Redis的持久化机制最好使用AOF方式,保证数据不丢失
- 同样由于对数据的可靠性要求较高,内存监控尤为重要,如果出现队列堆积内存用光造成无法提供服务的情况
- 如果只有一个消费者在消费队列,推荐使用lindex先读取消息,消费完之后在lpop扔掉,这样可以保证事务性,避免消息处理失败后消息丢失
- 如果是多个消费者在消费队列,消息处理失败的情况下可以将消息重新写入队列,前期是消息没有有序性要求
通过批量(multi)和并行的方式可以提高生产者和消费者的处理能力。批量处理可以减少网络通信量,同时减少Redis在不同任务间切换的开销。并行的好处就是当一个客户端在准备或处理数据时并且Redis空闲时,另一个客户端可以从Redis读取数据;这样可以尽量保证Redis始终保持在繁忙状态。
如果通过以上优化,仍然有队列堆积的情况,建议启动多个Redis实例。由于Redis是单线程模型,无法利用多核CPU,开启多个实例能够明显提升吐吞量。Redis的集群方案有很多种,也可以简单的在客户端使用hash算法实现。具体实现方案已经超出本文叙述范围,不再累赘。
基于Redis list的消息队列使用示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
缓存
这里我们说的缓存,是可以丢失或过期的数据,不能丢失或过期的缓存(或者应该叫做数据库了)不在本文的叙述范围。Redis的字典结构常用来做缓存使用,常用的方法有:set/get、hget/hgetall/hset等。使用redis作为缓存时,需要注意以下几个问题:
- 由于Redis可用的内存是有限的,不能容忍redis内存的无限增加,最好设置最大内存maxmemory
- 在开启maxmemory的情况下,可以启用lru机制,设置key的expire,当到达Redis最大内存时,Redis会根据最近最少用算法对key进行自动淘汰;lru的策略有6种,可参考:http://www.aikaiyuan.com/7089.html
- Redis的持久化策略和Redis故障恢复时间是一个博弈的过程,如果你希望在发生故障时能够尽快恢复,应该启用dump备份机制,但dump机制要求你必须保留至少1/3(经验值)的可用内存(写时复制),所以你可能没办法分配尽可能多的内存给Redis;如果能够容忍Redis漫长的故障恢复时间,可以使用AOF持久化机制,同时关闭dump机制,这样可以突破保留1/3内存的限制。
关于缓存的使用方法,不属于本文叙述范围,可参考:http://tech.meituan.com/avalanche-study.html
示例代码太多,这里就只贴个地址:https://github.com/huyanping/RedisStudy/tree/master/src/spider
计算
Redis提供的原子递增递减方法以及有序集合等可以承担一些计算任务,例如访问量统计等。常用的方法有:incr/decr、hincrby、zadd/zcard等。
在使用redis作为计算服务时,需要注意一下几个问题:
- 计算场景的数据一般对可靠性要求比较高,建议启用AOF持久化机制,根据恢复时间和内容利用率的考虑确定是否开启dump机制。
- redis的单线程模型决定了redis无法利用多核CPU,这里建议引入redis集群解决方案,当然仍然可以在客户端通过hash方案解决。
- 批量发送、批量导出
去重
Redis的hset和HyperLogLog数据结构可以在使用少量内存的情况下对数据进行去重。在有大量数据需要去重的场景比较试用。Redis的HyperLogLog只需要使用12K的内存空间即可对2的64次方个记录进行去重。具体选用哈希字典还是HyperLogLog需要根据你需要去重的数据量综合决定,如果你需要去重的数据总体占用空间远小于12K,使用哈希字典即可,如果超过12K,推荐使用HyperLogLog。常用的命令有:pfadd/pfcount、hset/hlen。这里需要注意,pfadd返回的是布尔型,表示该值是否已经存在;不可以通过累加pfadd的结果判定唯一记录数,必须调用pfcount获取,这个应该是算法的原因,记住就好。有兴趣的童鞋可以深究一下HyperLogLog的算法。
两种方式的示例代码分别如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
发布订阅
Redis的发布订阅机制,在客户端与服务端由于某些问题链接失效时,中间订阅的数据会丢失;所以在实际生产环境中,很少应用这种机制。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
Redis lua应用
Lua 脚本功能是 Reids 2.6 版本的最大亮点, 通过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 CAS (check-and-set)命令的缺点, 并且可以通过组合使用多个命令, 轻松实现以前很难实现或者不能高效实现的模式。
优点:原子性(由于Redis是单线程模型,同一时刻只能处理一个lua脚本),更小的请求包
应用场景:事务实现,批量处理
以下示例代码实现了getAndSet命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
Dump故障
当Redis使用内存大于操作系统剩余内存的2倍时,使用dump持久化机制可能会造成服务器宕机、假死等情况。原因是dump时,Redis会fork一个子进程,根据写实复制原则,如果Redis中的数据会发生修改时,操作系统会把服务进程的内存copy一份给子进程,具体copy多少根据数据修改的覆盖度;这时如果内存不够用,操作系统会使用swap扩展内存,性能急剧下降,如果swap也不够了,则可能发生宕机、假死等情况。
解决方案:设置maxmemory,监控Redis内存使用(Redis info命令),场景允许的情况下开启lru机制。
maxmemory故障
故障描述:设置了maxmemory,内存用完,客户端无法写入
解决方案:对Redis内存使用进行监控,根据业务场景控制内存使用;如果内存确实不够用了,考虑引入分布式Redis集群方案
redis访问漏洞
这个漏洞的原理非常简单,只需执行以几条命令即可:
1 2 3 4 |
|
通过以上几条命令,可以将你的ssh公钥写入对方的Redis服务器,从而获取root权限。这个漏洞的利用条件也比较苛刻,需要满足以下几个条件:
- Redis需是root用户运行,或已知Redis运行用户
- 6379端口无防火墙拦截
- Redis无访问密码
- config set命令没有被禁用
根据以上利用条件,对应防御手段如下:
- 优先监听127.0.0.1网卡(如过redis是给本机访问),优先监听内网网卡
- 防火墙对6379端口访问进行限制
- 使用非root用户运行redis
- redis开启密码访问(养成好习惯)
- 禁用config set命令
一般情况下做到第二点,基本就不会被黑了,但我们应该尽量做到第四点,尽善尽美。
redis自动重连
RedisRetry是一个支持自动重连的redis客户端封装,项目地址:https://github.com/huyanping/RedisRetry
原理:使用__call方法对redis的原生方法封装,当发生RedisException时,自动关闭并重新建立连接,执行n次,每次相隔m毫秒。
常量:
REDIS_RETRY_TIMES 重试次数
REDIS_RETRY_DELAY 间隔时间,单位毫秒
使用方式:把使用Redis类的地方,添加’use \Jenner\RedisRetry\Redis’即可。
转载于:https://my.oschina.net/u/232595/blog/1788494
redis应用场景与最佳实践相关推荐
- 聊聊 Kafka:Kafka 消息重复的场景以及最佳实践
一.前言 上一篇我们讲了 聊聊 Kafka:Kafka 消息丢失的场景以及最佳实践,这一篇我们来说一说 Kafka 消息重复的场景以及最佳实践. 我们下面会从以下两个方面来说一下 Kafka 消息重复 ...
- 360开源的类Redis存储系统Pika的最佳实践
360DBA及基础架构团队根据360内部的Pika使用经验及社区用户的问题反馈,整理了以下这些Pika的最佳实践分享给大家. Pika最佳实践之一 在群里提问主动带上版本号能大幅度加快问题解决速度.( ...
- 阿里技术专家:数据一致性检测的应用场景与最佳实践
点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 后台回复"k8s",可领取k8s资料 来源:阿里巴巴中 ...
- 京东云分布式链路追踪在金融场景的最佳实践
微服务是近几年最流行的软件架构设计理念,和容器.devops一起构成了云原生的技术基础.微服务源于对产品快速交付的市场诉求,通过采取一系列的自动化测试.持续集成等敏捷开发实践,激活了组织效率,也增强了 ...
- hbase 页面访问_HBase在滴滴出行的应用场景和最佳实践
背景 对接业务类型 HBase是建立在Hadoop生态之上的Database,源生对离线任务支持友好,又因为LSM树是一个优秀的高吞吐数据库结构,所以同时也对接了很多线上业务.在线业务对访问延迟敏感, ...
- HBase在滴滴出行的应用场景和最佳实践
来源:极客头条,作者:李扬,滴滴出行资深软件开发工程师.2015年加入滴滴出行基础平台部,主要负责HBase和Phoenix以及相关分布式存储技术.在滴滴之前,曾在新浪担任数据工程师,专注于分布式计算 ...
- 案例篇-HBase 在滴滴出行的应用场景和最佳实践
1.背景 ** 1.1 对接业务类型** HBase 是建立在 Hadoop 生态之上的 Database,源生对离线任务支持友好,又因为 LSM 树是一个优秀的高吞吐数据库结构,所以同时也对接了很多 ...
- 智能投放系统之场景分析最佳实践
美团点评作为业内最大的O2O的平台,以短信/push作为运营手段触达用户的量级巨大,每日数以千万计. 美团点评线上存在超过千万的POI,覆盖超过2000城市.2.5万个后台商圈.在海量数据存在的前提下 ...
- webworker应用场景_典型应用场景 · OpenResty最佳实践-最新版 · 看云
# 典型应用场景 可以这样说,任何一个开发语言.开发框架,都有它存在的明确目的,重心是为了解决什么问题.没有说我们学习一门语言或技术,就可以解决所有的问题.同样的,`OpenResty`的存在也有其自 ...
- 华为架构师整理Redis数据结构的大厂最佳实践
1 概述 数据结构和内部编码 无传统关系型数据库的 Table 模型 schema 所对应的db仅以编号区分.同一 db 内,key 作为顶层模型,它的值是扁平化的.即 db 就是key的命名空间. ...
最新文章
- laravel homestead环境默认账号密码
- 如何查看笔记本电脑配置参数_教你如何查看 MacBook 配置,超简单
- 关于C#使用Shockwaveflash控件设计器不显示问题的解决方案
- Extjs4 actioncolumn只能显示图标,不能显示文字的暂时解决方法
- ubuntu apache2 的负载均衡和反向代理
- 滤波器开发之三:基于算数平均的阶进平滑滤波器
- 【Elasticsearch】es查看有问题的索引或者分片
- Bailian2723 不吉利日期(POJ NOI0113-02)【日期计算】
- 如何提高matlab的运算速度慢,如何提高MATLAB的运算速度
- linux文件实时同步(rsync+inotiy)
- 【Word】编号与文字间距过大
- 通过c语言求得一个英文句子中的单词数量
- 正则表达式系列:匹配正数、负数和小数 (正负整数)
- 一篇项目开发进度周报
- golang转换时间格式报missing Location in call to Date
- (8.2)利用Newton-Euler公式求解二连杆的动力学方程:
- Centos7安装cuda10.1
- 基于python高校学生管理系统
- 今天是十月十日卖萌日
- 七二法则-“莫道君行早,更有早行人”
热门文章
- [0418] 程序设计实训小结(更新1420)
- 新辰:传统行业进军互联网 怎样颠覆网络获得新生?
- Eclipse中servlet显示无法导入javax.servlet包问题的解决方案
- Google全球服务器根域名的IP地址
- 075 json和pickle模块
- Hotel 旅馆 题解(From luoguBlog)
- 洛谷P3649 [APIO2014]回文串(回文自动机)
- Gartner报告:多数CIO还未对数字化做好准备
- asp.net 利用jquery.form插件上传图片
- 转:开源项目学习方法ABC