一、背景
最近项目需要,需要数据库中的部分数据缓存到内存中,提高我们的查询与处理速度,传统的处理方式有两个方面拖慢了速度。
一、从web服务器到数据库服务器之间的网络请求
二、数据库服务器数据处理
缓存实际是内存,将状态置于内存而不是数据库。当我们将数据库数据加载到内存中以后,我们就不再面向关系数据库中数据表编程,而是真正直接面向模型对象编程。Java内存模型优点:基于内存的并发模型,多线程机制,大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁。
最后我们选择了redis。其实内存数据库挺多,常见的比如sqlite、redis、oracle timesTen。这里reids是key-value型的,读取速率快。特别是oracle timesTen是关系型数据库,和oracle整合得比较好。最后我们决定试用一下redis。
二、redis安装调试
http://blog.csdn.net/renfufei/article/details/38474435
安装其实很简单,解压缩官方包,先后启动服务器server.exe和cli.exe两个程序
redis-benchmark.exe #基准测试
redis-check-aof.exe # aof
redis-check-dump.exe # dump
redis-cli.exe # 客户端
redis-server.exe # 服务器
redis.windows.conf # 配置文件
注意:驱动Redis
很快你就会发现,Redis的API就如一组定义明确的函数那般容易理解。Redis具有让人难以置信的简单性,其操作过程也同样如此。这意味着,无论你是使用命令行程序,或是使用你喜欢的语言来驱动,整体的感觉都不会相差多少。因此,相对于命令行程序,如果你更愿意通过一种编程语言去驱动Redis,你不会感觉到有任何适应的问题。如果真想如此,可以到Redis的客户端推荐页面下载适合的Redis载体。
三、基础知识
Redis被认为是一种持久化的存储器key_value存储。Redis有5种数据结构,只有一个是典型的key_value型结构。理解Redis的关键就在于搞清楚这5种数据结构,明白这些数据结构的实际意义。
应用上面提及的数据结构概念到我们熟悉的关系型数据库里,我们可以认为其引入了一个单独的数据结构——表格。表格既复杂又灵活,基于表格的存储和管理,没有多少东西是你不能进行建模的。然而,这种通用性并不是没有缺点。具体来说就是,事情并不是总能达到假设中的简单或者快速。相对于这种普遍适用的结构体系,我们可以使用更为专门化的结构体系。当然,因此可能有些事情我们会完成不了(至少,达不到很好的程度)。但话说回来,这样做就能确定我们可以获得想象中的简单性和速度吗?
针对特定类型的问题使用特定的数据结构?我们不就是这样进行编程的吗?你不会使用一个散列表去存储每份数据,也不会使用一个标量变量去存储。对我来说,这正是Redis的做法。如果你需要处理标量、列表、散列或者集合,为什么不直接就用标量、列表、散列和集合去存储他们?为什么不是直接调用exists(key)去检测一个已存在的值,而是要调用其他比O(1)(常量时间查找,不会因为待处理元素的增长而变慢)慢的操作?
1、数据库
与关系型数据库相似,一直Redis有着相同的数据库基本概念,即一个数据库包含一组数据。典型的数据库应用案例是,将一个程序的所有数据组织起来,使之与另一个程序的数据保持独立。在Redis里,数据库简单的使用一个数字编号来进行辨认,默认数据库的数字编号是0,可以使用select来选择。
2、命令、关键字和值
命令有通用命令:比如del exist之类的是所有类型通用命令,他们和值类型没有关联。另外一种类型的命令是和具体的值类型有关的命令,命令结构非常清晰。每种值类型对应的命令都基本以相同的字母开头。
值得注意的是我们常用的keys命令实现模式匹配查询,del不可以,但是del可以通过管道来实现这个效果
key_value Redis不仅是一种简单的关键字-值型存储,从其核心概念来看,Redis的5种数据结构中的每个都至少有一个关键字和一个值。在转入其它关于Redis的有用信息之前,我们必须理解关键字和值的概念。
值(Values)是关联于关键字的实际值,可以是任何东西。有时候你会存储字符串,有时候是整数,还有时候你会存储序列化对象(使用JSON、XML或其他格式)。在大多数情况下,Redis会把值看做是一个字节序列,而不会关注它们实质上是什么。要注意,不同的Redis载体处理序列化会有所不同(一些会让你自己决定)。因此,在这本书里,我们将仅讨论字符串、整数和JSON。
在redis中,值共有五种类型,String、List 、Sets、Sorted Sets,每一种值类型都有其适合的应用场景。例如List是有序集合适合存储
3、查询
对于Redis而言,关键字就是一切,redis并不关心值的具体内容。更通俗来看就是,Redis不允许你通过值来进行查询。然而更多的时候对许多人来说,存储的目的就是为了查询。现实世界中,数据查询是如此的灵活和强大,而Redis的方式看起来是这么的麻烦和低效。但是我们要理解,Redis不是一种普遍使用的解决方案,确实存在这么一些事情是不应该由Redis来解决的(因为其查询的限制)。事实上,我们应该采用一种全新的理念去重新构建我们的数据。
文章后面有一个实际的用例。很重要的一点是,我们要明白关于Redis的这些基本事实。这能帮助我们弄清楚为什么值可以是任何东西,因为Redis从来不需要去读取或理解它们。而且,这也可以帮助我们理清思路,然后去思考如何在这个新世界里建立模型。
4、其他
流水线与关联命令:
许多命令能接受可变参数列表比如sadd,也有一种关联命令可以接受多个参数。例如早前我们看到过mget命令redis.mget(*keys.map {|u| “users:#{u}”})
Redis流水线功能:通常情况下,当一个客户端发送请求到Redis后,在发送下一个请求之前必须等待Redis的答复。使用流水线功能,你可以发送多个请求,而不需要等待Redis响应,这个有点类似于Linux管道。这不但减少了网络开销,还能获得性能上的显著提高。
值得一提的是,Redis会使用存储器去排列命令,因此批量执行命令是一个好主意。至于具体要多大的批量,将取决于你要使用什么命令(更明确来说,该参数有多大)。另一方面来看,如果你要执行的命令需要差不多50个字符的关键字,你大概可以对此进行数千或数万的批量操作。
**事务:**Redis实际上是单线程运行的,这就是为什么每一个Redis命令都能够保证具有原子性。当一个命令在执行时,没有其他命令会运行。在你考虑到一些命令去做多项事情时,这会特别的有用。例如:
incr命令实际上就是一个get命令然后紧随一个set命令。
getset命令设置一个新的值然后返回原始值。
setnx命令首先测试关键字是否存在,只有当关键字不存在时才设置值
虽然这些都很有用,但在实际开发时,往往会需要运行具有原子性的一组命令。若要这样做,首先要执行multi命令,紧随其后的是所有你想要执行的命令(作为事务的一部分),最后执行exec命令去实际执行命令,或者使用discard命令放弃执行命令。
性能:一直都说redis很快,能有多快?这依赖于很多东西,包括你正在使用着哪个命令,数据的类型等等。但Redis的性能测试是趋向于数万或数十万次操作每秒。你可以通过运行redis-benchmark(就在redis-server和redis-cli的同一个文件夹里)来进行测试。
**持久化**redis可以配置一定频率的数据库和内存中的数据同步
四、redis中的键值设计
1、项目:商城项目是使用该缓存来实现相关的查询功能。我们在内存中使用redis缓存了分类id->商品id;brand_id品牌->goods_id; keyword:name…->goods_id等其他维度的数据。在商城首页检索商品的时候,我们在在redis中对不维度的key所对应的值作交集,查出符合条件的商品id。
2、其他应用实例
这个是csdn上看到的一个用户登陆系统redis设计示例
这个例子简单但十分形象。
五、遇到的问题
1、 redis经常会出现服务器拒绝服务,这个应该是我使用的问题
2、 商城项目中随着条件的多元化,条件位数越来越多,代码整体结构越来越复杂
oracle timesTen据说和oracle整合得非常好,并且在内存中是关系型结构,平时oracle使用较多使用起来应该比较熟练。后面将会尝试使用 timesTen来在商城项目中试用。