Redis入门指南一

在互联网的迅速发展,网民的群体越来越庞大,互联网公司的需要各种横向扩展,分层架构等等技术去满足用户快速访问的体验,那么就不得不说器缓存,缓存有许多种方案在整体的应用架构中部署的位置,应用场景都不同,例如页面缓存,nginx缓存等等,那么我们今天学学Redis数据库前端缓存(更准确说Redis不只是一个缓存的作用,就是一个数据库,读完此文会深有感触)。

 

以前在没深入学习redis的时候认为redis 就是一个纯粹的数据库前端的key-value 缓存中间件,可以代替memcached的缓存中间件,但是深入学习redis后我的认识发生了改变,它不止一个缓存中间件,它是一个数据库。

 

2008年,意大利的一家创业公司Merzia.① 推出了一款基于MySQL的网站实时统计系统

LLOOGG② ,然而没过多久该公司的创始人Salvatore Sanfilippo便开始对MySQL的性能感到失

望,于是他决定亲自为LLOOGG量身定做一个数据库,并于2009年开发完成,这个数据库就是

Redis。不过Salvatore Sanfilippo并不满足只将Redis用于LLOOGG这一款产品,而是希望让更多

的人使用它,于是在同一年Salvatore Sanfilippo将Redis开源发布,并开始和Redis的另一名主要

的代码贡献者Pieter Noordhuis一起继续着Redis的开发,直到今天。

 

 

------------------------------------------------------------------------------------------

Redis存储结构

到目前为止Redis支持的键值数据类型如

下:

●字符串类型

●散列类型

●列表类型

●集合类型

●有序集合类型

 

字符串类型

 介绍

字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数

据。你可以用其存储用户的邮箱、JSON化的对象甚至是一张图片。一个字符串类型键允许存

储的数据的最大容量是512MB① 。

注释:①在Redis 3.0版本中可能会放宽这一限制,但无论如何,考虑到Redis的数据是使用

内存存储的,512MB的限制已经非常宽松了。

字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来

说只是组织字符串的形式不同。例如,列表类型是以列表的形式组织字符串,而集合类型是以

集合的形式组织字符串。学习过本章后面几节后相信读者对此会有更深的理解。

命令

1.赋值与取值

SET key value

GET key

SET和GET是Redis中最简单的两个命令,它们实现的功能和编程语言中的读写变量相

似,如key="hello"在Redis中是这样表示的:

redis>SET key hello

OK

想要读取键值则更简单:

redis>GET key

"hello"

当键不存在时会返回空结果。

2.递增数字

INCR key

前面说过字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时,Redis

提供了一个实用的命令INCR,其作用是让当前键值递增,并返回递增后的值,用法为:

redis>INCR num

(integer) 1

redis>INCR num

(integer) 2

当要操作的键不存在时会默认键值为0,所以第一次递增后的结果是1。当键值不是整数

时Redis会提示错误:

redis>SET foo lorem

OK

redis>INCR foo

(error) ERR value is not an integer or out of range

有些读者会想到可以借助GET和SET两个命令自己实现incr函数,伪代码如下:

def incr( key)

value=GET key

if not value

value=0

value= value+1

SET key, value

return value

如果Redis同时只连接了一个客户端,那么上面的代码没有任何问题(其实还没有加入错

误处理,不过这并不是此处讨论的重点)。可当同一时间有多个客户端连接到Redis时则有可能

出现竞态条件(race condition)① 。例如,有两个客户端A和B都要执行我们自己实现的incr函数

并准备将同一个键的键值递增,当它们恰好同时执行到代码第二行时二者读取到的键值是一

样的,如“5”,而后它们各自将该值递增到“6”并使用SET命令将其赋给原键,结果虽然对键执

行了两次递增操作,最终的键值却是“6”而不是预想中的“7”。包括INCR在内的所有Redis命令

都是原子操作(atomic operation)② ,无论多少个客户端同时连接,都不会出现上述情况。之后

我们还会介绍利用事务(4.1 节)和脚本(第6章)实现自定义的原子操作的方法。

注释:①竞态条件是指一个系统或者进程的输出,依赖于不受控制的事件的出现顺序或者

出现时机。

注释:②原子操作取“原子”的“不可拆分”的意思,原子操作是最小的执行单位,不会在执

行的过程中被其他命令插入打断。

3.存储文章数据

由于每个字符串类型键只能存储一个字符串,而一篇博客文章是由标题、正文、作者与发

布时间等多个元素构成的。为了存储这些元素,我们需要使用序列化函数(如PHP中的serialize

和JavaScript中的JSON.stringify)将它们转换成一个字符串。除此之外因为字符串类型键可以

存储二进制数据,所以也可以使用MessagePack② 进行序列化,速度更快,占用空间也更小。

注释:②MessagePack和JSON一样可以将对象序列化成字符串,但其性能更高,序列化后

的结果占用空间更小,序列化后的结果是二进制格式。MessagePack的项目地址是

http://msgpack.org。

至此我们已经可以写出发布新文章时与Redis操作相关的伪代码了:

#首先获得新文章的ID

postID=INCR posts:count

#将博客文章的诸多元素序列化成字符串

serializedPost=serialize( title, content, author, time)

#把序列化后的字符串存一个入字符串类型的键中

SET post: postID:data, serializedPost

获取文章数据的伪代码如下(以访问ID 为42的文章为例):

#从Redis 中读取文章数据

serializedPost=GET post:42:data

#将文章数据反序列化成文章的各个元素

title, content, author, time=unserialize( serializedPost)

#获取并递增文章的访问数量

count=INCR post:42:page.view

你可能感兴趣的:(redis 缓存 java)