Redis入门指南
随着互联网业务对性能需求日益强烈,作为Key/Value存储的Redis具有数据类型丰富和性能表现优异的特点。如果能够熟练地驾驭它,不管是把它用做缓存还是存储,对很多大型应用都很多帮助。新浪作为世界上最大的Redis使用者,体会到了Redis为高并发在线业务带来的好处,但同时也遇到了很多挑战,新浪为推动Redis这种NoSQL产品在中国互联网产品技术架构中的使用做出了卓越的贡献。作为国内第一本推进Redis普及的书,此书比较详细地介绍了Redis入门必备的基础知识,同时拥有了一些实践性方面的章节。如果你对Redis感兴趣,推荐你阅读此书,此书会为你开启Redis的大门。
---- 杨海朝,新浪首席数据架构师
拿到这本书,看到豆瓣上8.3分的评价,Redis这个如此广泛运用的开源技术还是很吸引我的,所以读完吧,然后写个读书笔记,引言是新浪工程师对此书的评价,我看完这本书之后,果然收获颇丰,记录如下。
作学习交流之用,非盈利性质
第一章 Redis入门
Redis始于一个意大利创业公司Merzia,创始人Salvatore Sanfilippo以及另外一名主要代码贡献者Pieter Noordhuis目前在VMware,全职开发Redis。Redis代码托管在Github上。
Redis在性能上是单线程模型,而Memcached支持多线程,所以在多核服务器上后者的性能更高一些,然而Redis的性能已经足够优异,在绝大部分场合下其性能都不会成为瓶颈。所以在使用时更应该关心的是二者功能上的区别,如果需要用到高级的数据类型或是持久化等功能,Redis将会是Memcached很好的替代品。
第二章 Redis准备
首先找到linux机器,安装一个redis,依赖命令wget,gcc
wget http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make MALLOC=libc
make install redis-server (--port 6397) & //启动redis服务,可以指定端口,后台运行 redis-cli SHUTDOWN //停止Redis,Redis收到SHUTDOWN命令后,会先断开所有客户端连接,然后根据配置执行持久化,最后完成退出,“kill Redis进程PID”也可以正常结束Redis redis-cli -h 127.0.0.1 -p 6379 客户端可以指定连接服务端的ip和端口 redis-cli PING
如果接收到PONG说明一切正常,客户端请求收到服务端的响应。
Redis默认支持16个数据库,不同的应用应该使用不同的Redis实例存储数据。由于Redis非常轻量级,一个空Redis实例占用的内存只有1MB左右,所以不用担心多个Redis实例会占用很多内存。
第三章 Redis入门
一些基本命令就不介绍了
HSETNX 原子地实现了HEXISTS和HSET两个命令以避免竞态条件
LRANGE numbers 0 -1可以获取列表中的所有元素
列表类型可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段。列表类型内部使用双向链表实现,列表类型适合用来记录日志,可以保证加入新日志的速度不会受到已有日志数量的影响,但是不适合从中间获取数据,当列表元素非常多时访问中间元素效率并不高,适合场景是新鲜事这些只关心最新的内容。
有序集合类型是使用散列表和跳跃表实现的,增删改查都是Log(N),跳表的设计非常精彩,多个level的索引思想,用空间换时间。
场景1.记录日志时希望只保留最近的100条日志
LPUSH logs $newLog
LTRIM logs 0 99
场景2.网站监控系统
将元素从一个列表转到另一个列表 RPOPLPUSH source destination
当source和destination相同时,RPOPLPUSH命令会不断地将队尾的元素移到队首,借助这个特性我们可以实现一个网站监控系统:使用一个队列存储需要监控的网址,然后监控程序不断地使用RPOPLPUSH命令循环取出一个网址来测试其可用性。这里使用RPOPLPUSH命令的好处在于在程序执行过程中仍然可以不断地向网址列表中加入新网址,而且整个系统容易扩展,允许多个客户端同时处理队列。
场景3.用集合实现倒排索引
tag:Redis:posts->3
tag:MySQL:posts->2,3
tag:Java:posts->1,2,3
场景4.分页实现(按时间,按点击量)
ZRANGEBYSCORE key in min max [WITHSCORES] [LIMIT offset count]
可以用时间+offset作为score,然后就可以根据这个score进行分页展示了
第四章 Redis进阶
事务
MULTI //事务开始
....
EXEC //执行事务
Redis的事务没有关系数据库事务提供的回滚功能,不过由于Redis不支持回滚,也使得Redis在事务上可以保持简洁和快速,另外如果能够很好的规划数据库,保证键名规范的使用,是不会出现如命令与数据类型不匹配这样的运行错误的。
因为事务中每个命令的执行结果都是最后一起返回的,所以无法将前一条命令的结果作为下一条命令的参数,这时候问题出现了:如何原子的实现增1的功能?
watch命令!WATCH命令可以监控一个或多个键,一旦其中一个键被修改或删除,之后的事务就不会执行。监控一直持续到EXEC命令,通过事务实现incr函数,伪代码如下:
def incr($key)
WATCH $key
$value = GET $key
if not $value
$value =
$value = $value+ //如果在watch之后有其他线程修改了value,则事务失败
MULTI
SET $key, $value
result = EXEC //失败的话,需要重新执行
return result[]
场景1.实现访问频率限制
$isKeyExists = EXISTS rate.limiting:$IP
if $isKeyExists is
$times = INCR rate.limiting:$IP
if $time >
print 访问频率超过了限制,请稍后再试
exit
else
MULTI
INCR rate.limiting:$IP
EXPIRE $keyName, //这个用事务控制,否则这行如果没有执行,那用户最多只能访问100次博客了
EXEC //这段程序有一个临界问题,如果一个人在前一分钟的最后访问了99次,新的分钟开始访问了99次,虽然密集访问了198次,但是代码判断不出来,推荐的做法是,缩小时间窗口,比如把一分钟压缩成10秒钟。还有一种方式是记录每次访问的时间,然后用列表去存储最近的访问时间,这个方法会占用较多的存储空间,实际使用时还需要开发者自己去权衡。
场景2.实现缓存
如果命中用redis的值,否则重新计算出新值,两小时失效,伪代码如下
$rank = GET cache:rank
if not $rank
$rank = 计算排名...
MULTI
SET cache:rank, $rank
EXPIRE cache:rank,
EXEC
场景3.优先级队列
当确认邮件和发送通知邮件两种任务同时存在时,应该优先执行前者。伪代码如下:
BRPOP key [key ...] timeout 阻塞弹出
loop
$task = BRPOP queue:confirmation.email, queue:notification.email,
execute($task[])
场景4.发布/订阅 模式
SUBSCRIBE channel1 PUBLISH channel1 hi
第五章 Redis实践
列举了PHP、Ruby、Python、Node.js与Redis的一些应用场景,包括用户注册登录功能,自动提示功能(搜索补足提示功能),在线好友功能,IP地址查询功能,有兴趣的朋友可以再细看。
第六章 Redis脚本
Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。使用脚本的好处如下:
- 1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。
- 2.原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。
- 3.复用:客户端发送的脚本会永久存储在Redis中,意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑。
可以看例子:Lua脚本配合Redis的实践
第七章 Redis管理
Redis支持两种方式持久化,一种是RDB方式,一种是AOF方式。根据应用场景和对数据可靠性的要求,可以单独使用其中一种或将二者结合使用。
RDB方式
RDB方式的持久化是通过快照完成的,快照的过程如下
1.Redis使用fork函数复制一份当前进程的副本
2.父进程继续接手并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘的临时文件。
3.当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此一次快照操作完成。
在执行fork的时候操作系统(类UNIX操作系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的RDB文件存储的是执行fork一刻的内存数据。
Redis还支持手动发送SAVE或BGSAVE命令让Redis执行快照,前者是父进程进行快照,会阻塞其他请求,后者会通过fork子进程执行快照操作。
AOF方式
开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis会将命令写入硬盘中的AOF文件。按照一定的策略会重写AOF文件,因为对于变量的两次set,只需要保存后面的set即可,这样可以减小AOF文件的大小。
操作系统缓存的机制,数据并没有真正写入到硬盘,而是进入了系统的硬盘缓存,一般设置appendsync everysec每秒执行一次同步操作。flush缓存到硬盘。
集群,读写分离
在常见的场景中,读的频率大于写,当单机Redis无法应付大量的杜请求时(尤其是较耗资源的请求,比如SORT命令等)可以通过复制功能简历多个从数据库,主数据库只进行写操作,而从数据库负责写操作。
另一个相对耗时的操作是持久化,为了提高性能,可以通过复制功能建立一个(或若干个)从数据库,并在从数据库中启用持久化,同时在主数据库中禁用持久化。当从数据库崩溃时重启后主数据库会自动将数据同步过来,所以无需担心数据丢失。而当主数据库崩溃时,需要在从数据库中使用SLAVEOF NO ONE命令将从数据库提升成主数据库继续服务,并在原来的主数据库启动后使用SLAVEOF命令将其设置成新的主数据库的从数据库,即可将数据同步回来。perfect!
安全
Redis的安全设计是在”Redis运行在可信环境“这个前提下做出的,在生产环境运行时不能允许外界直接连接到Redis服务器上,虽然Redis支持密码,但是由于Redis性能极高,并且输入错误密码后Redis并不会进行主动延迟(考虑到Redis的单线程模型),所以攻击者可以通过穷举法破解Redis的密码(1秒内能够尝试十几万个密码)。
管理工具
一般用redis-cli命令行工具就可以,也有一些网页管理工具,比如phpRedisAdmin,但phpRedisAdmin在获取键列表时使用的是KEYS *命令,当键非常多的时候性能并不高,所以对生产环境下拥有大数据量的数据库来说不适宜使用phpRedisAdmin管理。
附上书封面
Redis入门指南的更多相关文章
- Redis入门指南之三(入门)
本节主要介绍Redis的5种数据类型,同时使用Python API来操作Redis,其中python版本为3.5, redis版本为4.0.2. redis-py 的API的使用可以分类为: (1)连 ...
- Redis入门指南之一(简介)
1. 简介 Redis是一个开源的.高性能的.基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同的场景下的缓存与存储需求.同时Redis的诸多高级功能使其可以胜任消息队列.任务队列等不同的 ...
- Redis入门指南之二(安装及配置)
本节主要内容 1. 前言2. redis安装3. 启动和停止Redis 1. 前言 安装Redis需要知道自己需要哪个版本,有针对性的安装,比如如果需要redis GEO这个地理集合的特性,那么red ...
- redis入门指南(二)—— 数据操作相关命令
写在前面 以下绝大部分内容取材于<redis入门指南>,部分结合个人知识,实践后得出. 只记录重要,明确,属于新知的相关内容,杜绝冗余和重复. 字符串 1.字符串类型是redis中最常见的 ...
- redis入门指南(三)—— 事务、过期时间、SORT命令、消息通知与管道
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 事务 1.redis中的事务由一组命令的集合组成,要么都执行,要么都不执行,同时redis的事务 ...
- redis入门指南(四)—— redis如何节省空间
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 节省空间 1.redis对于它所支持的五种数据类型,每种都提供了两种及以上的编码方式去存储(具体 ...
- redis入门指南(五)—— 复制与哨兵
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 一.复制 1.在复制中,数据库分为两类,一类主数据库,一类从数据库,主库用来读写,从库用来读,主 ...
- redis入门指南(六)—— 集群
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 配置集群 1.配置集群,集群解决了单点故障以及单台机器内存上限的问题,使用集群时,只需要将配置文 ...
- redis入门指南(七)—— 安全、协议、管理工具及命令属性
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 安全 1.可以使用bind参数绑定一个地址,使redis只接受这个地址的连接. 2.使用requ ...
随机推荐
- [Android Pro] Test win
http://www.cnblogs.com/mayingbao/ http://www.cnblogs.com/hyddd/
- C#冒泡排序
C#最简单的冒泡排序,需要的朋友可作参考: 思路: 使用两个for循环,就可以遍历数组,这样就可以确保每个数组元素都被使用 对比前后两个数,将小的数字和大的交换位置,引入一个临时变量temp来进行交换 ...
- shell之数值运算
Shell中声明变量默认是字符串, 要参与数值运算,可使用下面方式,简单,表示以数值方式.
- Swift - 文本输入框(UITextField)
1,文本框的创建,有如下几个样式: UITextBorderStyle.none:无边框 UITextBorderStyle.line:直线边框 UITextBorderStyle.roundedRe ...
- Ubuntu 14.04 Trusty安装java环境
原文:Install Oracle Java 6, 7, or 8 in Ubuntu 14.04 Trusty 命令如下: sudo add-apt-repository ppa:webupd8te ...
- MVC – 9.mvc整体请求流程
1.请求管道 2~5微软自己的验证,我们一般不用. 在全局配置文件中-已经配置一个路由过滤器-为第7个事件注册了路由方法 1.在application_start中向静态路由表注册了路由数据,在管 ...
- Error parsing 'file:///media/RHEL_5.5\\ x86_64\\ DVD/Server'
Error parsing 'file:///media/RHEL_5.5\\ x86_64\\ DVD/Server' http://lindows.iteye.com/blog/456637 ht ...
- SQL链表查询 数据库为空
查询出数据为空,解决方案:链表 对应字段长度不一致.
- 网站性能测试工具--MS Web Application Stress Tool
MS Web Applicaion Stress Tool 是一款网页测试的性能工具,具体的使用可以参考下面这篇博客文章 http://cuisuqiang.iteye.com/blog/193640 ...
- makefile基础(GNU)
makefile的核心 targets : prerequisites ; commands... //不分行的情况 targets : prerequisites ...