NoSql数据库--Redis入门
Redis入门
1、NoSQL概述【重点了解】
1.1 什么是NoSQL
NoSQL(NoSQL=Not Only SQL),意即"不仅仅是SQL"是一项全新的数据库理念,泛指非关系型数据库。
【关系型数据库】关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
优点:1、易于维护:都是使用表结构,格式一致;2、使用方便:SQL语言通用,可用于复杂查询;3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:1、读写性能比较差,尤其是海量数据的高效率读写;2、固定的表结构,灵活度稍欠;3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。// 35万/s【非关系型数据库】非关系型数据库严格上讲不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
优点:1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;3、高扩展性;4、成本低:nosql数据库部署简单,基本都是开源软件。
缺点:1、不提供sql支持,学习和使用成本较高;2、无事务处理;3、数据结构相对复杂,复杂查询方面稍欠
1.2 为什么要用NoSQL
随着互联网的高速崛起,网站的用户群的增加,访问量的上升,传统数据库上都开始出现了性能瓶颈,web程序不再仅仅专注在功能上,同时也在追求性能。所以NOSQL数据库应运而上,具体表现为对如下三高问题的解决:
【High performance 】- 对数据库高并发读写的需求 web2.0网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。其实对于普通的BBS网站,往往也存在对高并发写请求的需求,例如网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,因此这是一个相当普遍的需求。【Huge Storage 】- 对海量数据的高效率存储和访问的需求 类似Facebook,twitter,Friendfeed这样的SNS网站,每天用户产生海量的用户动态,以Friendfeed为例,一个月就达到了2.5亿条用户动态,对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。 【High Scalability && High Availability】- 对数据库的高可扩展性和高可用性的需求 在基于web的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移。
1.3 主流的NoSQL产品
【NoSQL数据库分类】
- 键值(Key-Value)存储数据库;Map
- 列存储数据库;
- 文档型数据库;
- 图形(Graph)数据库;
1、【键值(Key-Value)存储】相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB典型应用: 内容缓存,主要用于处理大量数据的高访问负载。 数据模型: 一系列键值对优势: 快速查询劣势: 存储的数据缺少结构化2、【列存储数据库】相关产品:Cassandra, HBase, Riak典型应用:分布式的文件系统数据模型:以列簇式存储,将同一列数据存在一起优势:查找速度快,可扩展性强,更容易进行分布式扩展劣势:功能相对局限3、【文档型数据库】相关产品:CouchDB、MongoDB典型应用:Web应用(与Key-Value类似,Value是结构化的)数据模型: 一系列键值对优势:数据结构要求不严格劣势: 查询性能不高,而且缺乏统一的查询语法4、【图形数据库】相关数据库:Neo4J、InfoGrid、Infinite Graph典型应用:社交网络数据模型:图结构优势:利用图结构相关算法。劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
1.4 NoSQL的特点
NoSQL数据库在大数据存储上具有关系型数据库无法比拟的优势:
1、易扩展NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。2、大数据量,高性能NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。3、灵活的数据模型NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的Web2.0时代尤其明显。4、高可用NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。比如Cassandra,HBase模型,通过复制模型也能实现高可用。
综上所述,NoSQL的非关系特性时期成为了后web2.0时代的宠儿,助力大型的web2.0网站的再次起飞,是一项全新的数据库革命性运动。
web1.0—传播信息(静态网页)
web2.0—微博(交互性)-- 功能实现,用户体验(性能–NoSQL)
2、Redis概述
2.1 Redis的由来
2008年,意大利的一家创业公司Merzia推出了一款基于MySQL的网站实时统计系统LLOOGG,然而没过多久该公司的创始人Salvatore Sanfilippo便对MySQL的性能感到失望,于是他决定亲自为LLOOGG量身订做一个数据库,并于2009年开发完成,这个数据库就是Redis。不过Salvatore Sanfilippo并不满足只将Redis用于LLOOGG这一款产品,而是希望更多的人使用它,于是在同一年Salvatore Sanfilippo将Redis开源发布,并开始和Redis的另一名主要的代码贡献者Pieter Moordhuis一起继续着Redis的开发,今天。Salvatore Sanfilippo自己也没想到,短短的几年时间,Redis就拥有了庞大的用户群体。Hacker News在2012年发布了一份数据库的使用情况调查,结果显示有近12%的公司在使用Redis。国内如新浪微博,街旁网,知乎网,国外如GitHub,Stack Overflow,Flickr等都是Redis的用户。VMware公司从2010年开始赞助Redis的开发,Salvatore Sanfilippo和Pieter Noordhuis也分别在3月和5月加入VMware,全职开发Redis。
2.2 什么是Redis
Redis是用C语言开发的一个开源的高性能键值对(Key-Value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的值数据类型如下:
1. 字符串类型 string(常用:json/xml)
2. 散列类型 hash(key--value)map
3. 列表类型 list linkedlist 用户列表
4. 集合类型 set
5. 有序集合类型 sortedset
Redis: 软件--C语言--存储数据
特点:key-value ,内存存储
2.3 Redis的应用场景
Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;在一些需要大容量数据集的应用,Redis并不适合,因为它的数据集不会超过系统可用的内存。我们通常把它融入到系统中来,这就能够解决很多问题,比如那些你现有的数据库处理起来感到缓慢的任务。这些你就可以通过Redis来进行优化,或者为应用创建些新的功能。
1、缓存(数据查询,端链接,新闻内容,商品内容等等);--使用最多
2、聊天室的在线好友列表;
3、任务队列;(秒杀,抢购,12306等等)
4、应用排行榜;
5、网站访问统计;
6、数据过期处理(可以精确到毫秒);
7、分布式集群架构中的session分离;
3、window版Redis的安装与使用
3.1 window版Redis下载
官方提倡使用Linux版的Redis,所以官网只提供了Linux版的Redis下载,我们可以从GitHub上下载window版的Redis,具体链接地址如下:
官网下载地址: http://redis.io/download
github下载地址: https://github.com/MSOpenTech/redis/tags
3.2 window版Redis的目录结构
将上述压缩包解压后得到如下目录:
【Redis目录介绍】
目录或文件 | 作用 |
---|---|
redis-benchmark | 性能测试工具 |
redis-check-aof | AOF文件修复工具 |
redis-check-dump | RDB文件检查工具(快照持久化文件) |
redis-cli | 命令行客户端 |
redis-server | redis服务器启动命令 |
redis.windows.conf | redis核心配置文件 |
3.3 window版Redis的安装
window版的Redis是免安装的,将压缩包解压完成即可使用。
3.4 window版Redis的启动与关闭
启动:双击redis-server.exe
关闭:Ctrl+C 或者 将服务窗口关闭
3.5 连接Redis服务
Redis数据库服务的连接有两种方式:
- 命令行工具:
- 图形化界面工具:
【命令行工具使用】
双击redis-cli.exe文件,会弹出命令行客户端窗口,我们可以在这个窗口中书写redis的命令:ping 。如果服务器能够返回PONG说明,连接成功!
【图形化界面工具】
开发中,我们往往会使用图形化界面工具连接Redis服务,对Redis中的数据进行更加直观地操作。图形化界面工具是一个独立的软件,使用之前需要先进行安装。软件在资料中:
【使用步骤】
安装:双击,下一步即可完成安装;
连接:新建连接,配置连接信息;
查看Redis实例:双击刚刚创建的连接,如果出现16个db实例,即说明连接成功。
【注意】
- redis服务器中默认的数据库数量是16,如果不指定数据库,默认使用id为0的数据库;
- 切换数据库的命令:SELECT ;
4、Redis的数据结构
Redis是一种高级的Key-Value类型的存储系统,其中key值是字符串类型,value值支持5种常用的数据类型。
redis中文网:http://www.redis.net.cn/order/
4.1 Redis中的Key值
Redis中的key值是字符串类型,key值是Redis中数据查询和存储的依据。我们在往Redis中存储数据时,关于key值的命名需要注意以下几点:
key不要太长,最好不要超过1024个字节,这不仅会消耗内存还会降低查找效率
key不要太短,如果太短会降低key的可读性
key命名规范,在项目中key最好有一个统一的命名规范
4.2 Redis中的Value值
Redis中的Value值是用来存储具体数据的,常用的数据类型有以下5种:
· 字符串(String)
· 哈希(hash)
· 字符串列表(list)
· 字符串集合(set)
· 有序字符串集合(sorted set)
在日常开发中主要使用比较多的有字符串、哈希、字符串列表、字符串集合四种类型,其中最为常用的是字符串类型。
4.3 字符串类型(String)
应用场景:
常规key-value缓存应用。常规计数: 微博数, 粉丝数,json格式的数据。
1. 字符串类型string概述
字符串类型是Redis中最为基础的数据存储类型,字符串在Redis中是二进制保存,因此是安全的,这便意味着该类型存入和获取的数据相同。在Redis中字符串类型的Value最多可以容纳的数据长度是512M。
2. 字符串类型string常用命令
功能 | 命令 | 说明 |
---|---|---|
设置(修改)值 | set key value | 该key存在则进行覆盖操作,该操作总是返回"OK"。 |
获取值 | get key |
获取该key关联的字符串value值。如果value值不是字符串 会报错,如果key不存在则返回nil。 |
删除数据 | del key [key2 key3…] | 根据指定的key删除对应的数据。可一次删除多个 |
批量设置值 | mset key1 value1 key2 value2 | 同时设置多对键值对 |
批量取值 | mget key1 key2 | 同时获取过个key值对应的value值 |
设置值(返回原来的值) | getset key value | 给指定的key设置value值,返回原来的值(如果原来没有值返回nil) |
注:查看redis中的所有key值: keys *
【命令】 :set key value
设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回”OK”。
注意:value值可以可以不用添加双引号。value值在redis中都是以字符串的形式进行存储;
127.0.0.1:6379> set name "zhangsan"
OK
127.0.0.1:6379> set addr shanghai
OK
127.0.0.1:6379> set age 13
OK
【命令】 : get key
获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,因为get命令只能用于获取String value;如果该key不存在,返回(nil)。
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> get addr
"shanghai"
127.0.0.1:6379> get age
"13"
127.0.0.1:6379> get company
(nil)
【命令】 : del key
根据指定的key删除对应的数据。
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> del name
(integer) 0
【扩展】
- 设置多个值:mset key1 value1 [key2 value2 …]
127.0.0.1:6379> mset name zhangsan age 13
OK
- 获取多个值:mget key1 [key2…]
127.0.0.1:6379> mget name age
1) "zhangsan"
2) "13"
- 设置值(返回原值):getset key value
127.0.0.1:6379> getset name lisi
"zhangsan"
127.0.0.1:6379>
4.4 Hash类型数据
4.4.1 Hash类型数据概述
Redis中的Hash类型可以看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如username、password和age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。
Key是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。
4.4.2. 哈希类型hash常用命令
使用场景:
存储部分变更数据,如用户信息等。
常用命令
功能 | 命令 | 说明 |
---|---|---|
为指定的key设定field/value | hset key field value | 设置单个值 |
获取指定key的field对应的value值 | hget key field | 获取单个值 |
删除指定key的field对应的value值 | hdel key field [field2 …] | 可以删除多个值 |
为指定的key批量设置值 | hmset key field value [field2 value2] | 批量设置值 |
获取指定key的多个值 | hmget key field[field2 field3 …] | 批量获取值 |
获取指定key的所有键值对 | hgetall key | 获取所有的键值对 |
【命令】 : **hset key field value **
为指定的key设定field/value对(键值对)。
127.0.0.1:6379> hset stu name zhangsan
(integer) 1
127.0.0.1:6379>
【命令】 hget key field
返回指定的key中的field的值
127.0.0.1:6379> hget stu name
"zhangsan"
127.0.0.1:6379>
【命令】 hmset key field value[field2 value2 …]
批量给指定key设置多个key-value值
127.0.0.1:6379> hmset stu name zhangsan age 13
OK
127.0.0.1:6379>
【命令】 hmget key field[field2 …]
批量获取指定key的多个key-value值
127.0.0.1:6379> hmget stu name age
1) "zhangsan"
2) "13"
127.0.0.1:6379>
【命令】 **hgetall key **
批量获取指定key的所有key-value值
127.0.0.1:6379> hgetall stu
1) "name"
2) "zhangsan"
3) "age"
4) "13"
127.0.0.1:6379>
【命令】 hdel key field [field2 … ]
可以删除一个或多个字段,返回值是被删除的字段个数
127.0.0.1:6379> hdel stu name age
(integer) 2
127.0.0.1:6379>
4.5 列表类型list
应用场景:
list集合: 存取有序(存入时的顺序),有索引,可以重复 ------- 查询快,增删慢
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。List 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用List结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列,可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。
4.5.1. 列表类型list概述
在Redis中,List类型是按照插入顺序排序的字符串链表,可保存重复数据。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键不存在,Redis将为该键创建一个新的链表。如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295
4.5.2 列表类型list常用命令
功能 | 命令 | 说明 |
---|---|---|
头部插入数据 | lpush key value1 value2… | 从list的头部开始插入数据 |
尾部插入数据 | rpush key value1 value2… | 从list的尾部开始插入数据 |
查看list中所有数据 | lrange key 0 -1 | 索引0指的是列表中第一个元素,-1指列表中最后一个元素 |
查看list中指定索引区间的元素 | lrange key start end | start:开始索引,从0开始;end:结束索引; |
查看指定索引的值 | lindex key index | index:值在list中的索引 |
从list的头部弹出一个值 | lpop key | 获取并移除list头部的第一个值 |
从list的尾部弹出一个值 | rpop key | 获取并移除list头部的最后一个值 |
【命令-头部插入】 lpush key value1 value2 …
在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。如果插入成功,返回元素的个数。
127.0.0.1:6379> lpush stus zhagnsan lisi wangwu
(integer) 3
127.0.0.1:6379>
【命令-尾部插入】 rpush key value value value
在指定的key对应的list的尾部插入所有的value,如果该key不存在,该命令在插入之前创建一个与该key对应的空链表,再从尾部插入数据。如果插入成功,返回元素的个数。
127.0.0.1:6379> rpush strs zhangfei guanyu liubei
(integer) 3
127.0.0.1:6379>
【命令-查看列表】 lrange key 0 -1 和 lrange key start end
查看list中的所有数据;
127.0.0.1:6379> lrange stus 0 -1
1) "wangwu"
2) "lisi"
3) "zhagnsan"
127.0.0.1:6379>
查看list中索引为start到end的数据;
127.0.0.1:6379> lrange stus 0 2
1) "wangwu"
2) "lisi"
3) "zhagnsan"
127.0.0.1:6379>
【命令-从list头部取出元素】 lpop key
返回并弹出指定的key关联的链表中的第一个元素,即头部元素。
如果该key不存在,返回nil;
若key存在,则返回链表的头部元素。
127.0.0.1:6379> lpop stus
"wangwu"
127.0.0.1:6379>
【命令-从list尾部取出元素】rpop key
从尾部弹出元素。
127.0.0.1:6379> rpop stus
"zhagnsan"
127.0.0.1:6379>
5.6 集合类型set
set集合: 存取无序 ,不重复 --增删快,查询慢
应用场景:
Redis set对外提供的功能与list类似是一个列表的功能, 特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
5.6.1 集合类型set
在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。需要说明的是,这些操作的时间复杂度为O(1),即常量时间内完成次操作。Set可包含的最大元素数量是4294967295。
和List类型不同的是,Set集合中不允许出现重复的元素。
5.6.2 集合类型set的常用命令
功能 | 命令 | 说明 |
---|---|---|
设置值 | sadd key value [value1,value2…] | |
查看set中的所有值 | smembers key | |
移除并返回集合中的任意一个元素 | spop key | |
删除值【set集合中是元素删除完后set消失】 | srem key members[member1、member2…] | |
获取集合中的成员数 | scard key |
【命令-设置值】sadd key values[value1,value2…]
向set中添加数据,如果该key的值已有则不会重复添加
127.0.0.1:6379> sadd myset zhagnsan lisi wangwu
(integer) 3
127.0.0.1:6379>
【命令-获取值】smembers key
获取set中所有的成员
127.0.0.1:6379> smembers myset
1) "wangwu"
2) "lisi"
3) "zhagnsan"
127.0.0.1:6379>
【命令-删除值】 srem key members[member1、member2…]
删除set中指定的成员
127.0.0.1:6379> srem myset wangwu lisi
(integer) 2
127.0.0.1:6379> smembers myset
1) "zhagnsan"
127.0.0.1:6379>
5.7 有序集合 sorted set
5.7.1 有序集合sorted set应用场景
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。它用来保存需要排序的数据。例如排行榜,一个班的语文成绩,一个公司的员工工资,一个论坛的帖子等。有序集合中,每个元素都带有score(权重),以此来对元素进行排序。它有三个元素:key、member和score。以语文成绩为例,key是考试名称(期中考试、期末考试等),member是学生名字,score是成绩。有序集合有两大基本用途:排序和聚合
5.7.2 sorted set的常用命令
功能 | 命令 | 说明 |
---|---|---|
添加一个或多个成员 | zadd key score1 member1[score2 member2 …] | |
获取有序集合的成员数 | zcard key | |
通过索引区间返回有序集合成指定区间内的成员 | zrange key start stop [withscores] | |
通过索引区间返回有序集合成指定区间内的成员【顺序排列】 | zrange key start stop withscores | |
通过索引区间返回有序集合成指定区间内的成员【倒序排列】 | zrevrange key start stop withscores | |
移除有序集合中的一个或多个成员 | zrem key member[member1 … ] |
【命令-设置值】zadd key score member[score1 member1,score2 member2…]
往有序集合中添加元素: score member
127.0.0.1:6379> zadd scores 60 chinese 100 english 80 math
(integer) 3
127.0.0.1:6379>
【命令-获取集合成员数】zcard key
127.0.0.1:6379> zcard scores
(integer) 3
127.0.0.1:6379>
【命令-查询集合中的元素】zrange key start stop [withscores]
注:zrange key 0 -1 是查询所有元素;
127.0.0.1:6379> zrange scores 0 2
1) "chinese"
2) "math"
3) "english"
127.0.0.1:6379> zrange scores 0 2 withscores
1) "chinese"
2) "60"
3) "math"
4) "80"
5) "english"
6) "100"
127.0.0.1:6379> zrange scores 0 -1
1) "chinese"
2) "math"
3) "english"
127.0.0.1:6379>
【命令-删除集合中的元素】 zrem key member[member1 … ]
127.0.0.1:6379> zrem scores math english
(integer) 2
127.0.0.1:6379> zrange scores 0 -1
1) "chinese"
127.0.0.1:6379>
5. Redis的通用命令
【查询key】 keys pattern
获取所有与pattern匹配的key,返回所有与该key匹配的keys。*表示任意一个或多个字符,?表示任意一个字符
127.0.0.1:6379> keys *
1) "stu"
2) "strs"
3) "mylist"
4) "scores"
5) "cityData"
6) "stus"
7) "myset"
8) "name"
127.0.0.1:6379> keys name
1) "name"
127.0.0.1:6379>
【根据key值删除】del key1 key2…
删除指定key值的数据
127.0.0.1:6379> del company
(integer) 1
【判断key值是否存在】exists key
判断该key是否存在,1代表存在,0代表不存在
127.0.0.1:6379> exists compnay
(integer) 0
127.0.0.1:6379> exists mylist
(integer) 1
127.0.0.1:6379>
【获取指定key的数据类型】type key
获取指定key的类型。该命令将以字符串的格式返回。 返回的字符串为string、list、set、hash,如果key不存在返回none
127.0.0.1:6379> type name
string
127.0.0.1:6379> type strs
list
127.0.0.1:6379> type stu
hash
127.0.0.1:6379> type myset
set
127.0.0.1:6379> type scores
zset
http://www.redis.net.cn/order/
6. Jedis的基本使用
6.1. jedis的介绍
jedis是官方首选的java客户端开发包。
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java、C、C#、C++、php、Node.js、Go等。 在官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推荐使用Jedis和Redisson。 在企业中用的最多的就是Jedis,Jedis同样也是托管在github上,地址:https://github.com/xetorthio/jedis。下载jedis解压后得到jar包如下:java操作redis数据库API(Jedis)
6.2. jedis的基本操作
6.2.1. jedis常用API
方法 | 解释 |
---|---|
new Jedis(host, port) | 创建jedis对象,参数host是redis服务器地址,参数port是redis服务端口 |
set(key,value) | 设置字符串类型的数据 |
get(key) | 获得字符串类型的数据 |
hset(key,field,value) | 设置哈希类型的数据 |
hget(key,field) | 获得哈希类型的数据 |
lpush(key,values) | 设置列表类型的数据 |
lpop(key) | 列表左面弹栈 |
rpop(key) | 列表右面弹栈 |
del(key) | 删除指定的key |
6.2.2. jedis的基本操作
导入开发包:
package com.heima.jedis;import redis.clients.jedis.Jedis;public class JedisTest {public static void main(String[] args) {//1.创建redis核心对象:arg1-host arg2-端口Jedis jedis = new Jedis("localhost",6379);//2.存值jedis.set("name","黑马程序员");//3.取值String name = jedis.get("name");System.out.println(name);//4.释放资源jedis.close();}
}
7.3. jedis连接池的使用
7.3.1. jedis连接池的基本概念
jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的池化技术--jedisPool。jedisPool在创建时初始化一些连接资源存储到连接池中,使用jedis连接资源时不需要创建。而是从连接池中获取一个资源进行redis的操作,使用完毕后,不需要销毁该jedis连接资源,而是将该资源归还给连接池,供其他请求使用。
7.3.2. jedisPool的基本使用
package com.heima.jedis;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class JedisPoolTest {public static void main(String[] args) {//1 获得连接池配置对象,设置配置项JedisPoolConfig config = new JedisPoolConfig();// 1.1 最大连接数config.setMaxTotal(30);// 1.2 最大空闲连接数config.setMaxIdle(10);//2 获得连接池JedisPool jedisPool = new JedisPool(config, "localhost", 6379);//3 获得核心对象Jedis jedis = null;try {jedis = jedisPool.getResource();//4 设置数据jedis.set("name", "itcast");//5 获得数据String name = jedis.get("name");System.out.println(name);} catch (Exception e) {e.printStackTrace();} finally{if(jedis != null){jedis.close();}// 虚拟机关闭时,释放pool资源if(jedisPool != null){jedisPool.close();}}}
}
7.4. 案例-编写jedis连接池工具类
JedisUtils.java
package com.heima.utils;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;import java.util.ResourceBundle;/*** Jedis工具类*/
public class JedisUtil {private static JedisPool jedisPool;private static int maxtotal;private static int maxwaitmillis;private static String host;private static int port;//加载配置文件static {ResourceBundle jedisPorperties = ResourceBundle.getBundle("jedis");maxtotal = Integer.valueOf(jedisPorperties.getString("maxtotal"));maxwaitmillis = Integer.valueOf(jedisPorperties.getString("maxwaitmillis"));port = Integer.valueOf(jedisPorperties.getString("port"));host = jedisPorperties.getString("host");}//初始化连接池static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(maxtotal);config.setMaxIdle(maxwaitmillis);jedisPool = new JedisPool(config,host, port);}/*** 获取jedis客户端操作对象* @return*/public static Jedis getJedis() {return jedisPool.getResource();}/*** 释放资源* @param jedis*/public static void close(Jedis jedis) {if (null != jedis) {jedis.close();}}}
jedis.properties(src目录下配置文件,编写配置文件)
maxtotal=100
maxwaitmillis=3000
host=127.0.0.1
port=6379
如何快速读取properties配置文件信息
使用jdk提供 ResourceBundle加载 通过getBundle(“文件名”) 通过 getString(“key”)获取目标数据
src下添加Properties配置文件
内容:
username=lisi
password=123
url=http://xxx
driverclass=com.mysql.jdbc.Driver
加载代码实现 : ResourceBundle.java
使用说明
package cn.itheima.jedis.demo;import java.util.ResourceBundle;public class PropertiesDemo {// java 专属类 ResourceBundle 对象 jdk 提供public static void main(String[] args) {//getBundle源码查询 src路路径下的properties文件 传递文件名默认 .properties 所有不需要写扩展名String s = ResourceBundle.getBundle("db").getString("driverclass");String url = ResourceBundle.getBundle("db").getString("url");String aa = ResourceBundle.getBundle("db").getString("username");String bb = ResourceBundle.getBundle("db").getString("password");System.out.println(s);System.out.println(url);System.out.println(aa);System.out.println(bb);}
}
7.案例:Redis实战之查询所有学生
1、需求
index.html页面加载完成之后,使用ajax请求将所有的学员信息加载到页面的table中;
2、需求分析
实现如上需求有两种方案,分别如下:
页面加载完成之后,ajax发送异步请求从数据库查询数据,以后每次请求都从数据库中查询;
页面加载完成之后,ajax发送异步请求从数据库中查询数据后返回,并把数据存储在redis中,以后的查询直接从redis中获取;
由于,学生的信息在很长一段时间内是固定不变的,且数据量比较大。如果每次查询都从数据库查询,比较消消耗数据库性能,而且查询速度不快。所以,最佳方案是将数据查询出来后存储在redis中,后面的查询直接从redis中获取。
3、实现步骤
1、index.html页面加载完成之后,使用ajax技术向后台发送请求查询数据;
2、第一次查询时,直接从数据库中查询,查询到数据后将数据存储在redis中;
3、再次加载index.html页面时,请求发送到后台时,先判断redis中是否有数据,如果有则直接返回;如果没有,从数据库中查询;
4、index.html中拿到数据后,解析数据,将数据插入到页面的table中;
4、代码实现
1、前端页面:
【index.html】
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
<br><br><br><br><br>
<div class="text-center"><a href="stus.html" class="btn btn-primary">学生列表</a>
</div>
</body>
</html>
【stu_list.html】
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>layui</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><link rel="stylesheet" href="css/bootstrap.css"><!-- 注意:如果你直接复制所有代码到本地,上述css路径需要改成你本地的 --><style>.stuTable{width: 70%;margin: 20px auto;}</style>
</head>
<body>
<table class="stuTable table table-bordered " id="stuTable" ><caption class="text-center h2">学员列表</caption><tr><th>ID</th><th>姓名</th><th>学号</th><th>性别</th><th>班级</th><th>学科</th></tr>
</table><script src="js/jquery-3.3.1.js" charset="utf-8"></script>
</body>
</html>
2、后台环境搭建
2.1 数据库
【创建数据库】
CREATE TABLE `stu_info` (`id` int(11) NOT NULL AUTO_INCREMENT,`student_name` varchar(255) DEFAULT NULL,`student_no` varchar(255) DEFAULT NULL,`sex` int(11) DEFAULT NULL COMMENT '1-男 2-女',`class_id` int(11) DEFAULT NULL,`test_id` int(11) DEFAULT NULL,`subject_no` int(11) DEFAULT NULL COMMENT '学科编号:1-java 2-php 3-python 4-UI 5-前端 6-其他',`password` varchar(255) DEFAULT NULL,`test_status` int(11) DEFAULT NULL COMMENT '考试状态:0-结束 1-未结束',`test_type` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7969 DEFAULT CHARSET=utf8;
【导入数据】
2.2 创建实体类Student.java
package com.heima.domain;
public class Student {private Integer id;private String student_name;private String student_no;private Integer sex;private Integer class_id;private Integer subject_no;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getStudent_name() {return student_name;}public void setStudent_name(String student_name) {this.student_name = student_name;}public String getStudent_no() {return student_no;}public void setStudent_no(String student_no) {this.student_no = student_no;}public Integer getSex() {return sex;}public void setSex(Integer sex) {this.sex = sex;}public Integer getClass_id() {return class_id;}public void setClass_id(Integer class_id) {this.class_id = class_id;}public Integer getSubject_no() {return subject_no;}public void setSubject_no(Integer subject_no) {this.subject_no = subject_no;}
}
2.3 导入jar包
2.4 连接池和工具类
配置文件
【c3p0-config.xml】
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><default-config><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql:///stu_list?useUnicode=true&characterEncoding=UTF8</property><property name="user">root</property><property name="password">root</property><property name="acquireIncrement">2</property><property name="initialPoolSize">5</property><property name="minPoolSize">1</property><property name="maxPoolSize">5</property></default-config>
</c3p0-config>
【jedis.properties】
maxtotal=100
maxwaitmillis=3000
host=127.0.0.1
port=6379
注意:以上两个配置文件放置到src目录下。
工具类
【JdbcTemplateUtils.java】
package com.heima.utils;import com.mchange.v2.c3p0.ComboPooledDataSource;import javax.sql.DataSource;/*** JdbcTemplate工具类*/
public class JdbcTemplateUtils {private static final DataSource ds = new ComboPooledDataSource();/*** 获取DataSources* @return*/public static DataSource getDataSources() {return ds;}}
【JedisUtil.java】
package com.heima.utils;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;import java.util.ResourceBundle;/*** Jedis工具类*/
public class JedisUtil {private static JedisPool jedisPool;private static int maxtotal;private static int maxwaitmillis;private static String host;private static int port;//加载配置文件static {ResourceBundle jedisPorperties = ResourceBundle.getBundle("jedis");maxtotal = Integer.valueOf(jedisPorperties.getString("maxtotal"));maxwaitmillis = Integer.valueOf(jedisPorperties.getString("maxwaitmillis"));port = Integer.valueOf(jedisPorperties.getString("port"));host = jedisPorperties.getString("host");}//初始化连接池static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(maxtotal);config.setMaxIdle(maxwaitmillis);jedisPool = new JedisPool(config,host, port);}/*** 获取jedis客户端操作对象* @return*/public static Jedis getJedis() {return jedisPool.getResource();}/*** 释放资源* @param jedis*/public static void close(Jedis jedis) {if (null != jedis) {jedis.close();}}
}
3、代码实现
3.1 【stu_list.html】加载完成后发送ajax请求
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>layui</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><link rel="stylesheet" href="css/bootstrap.css"><style>.stuTable{width: 70%;margin: 20px auto;}</style>
</head>
<body>
<table class="stuTable table table-bordered " id="stuTable" ><caption class="text-center h2">学员列表</caption><tr><th>ID</th><th>姓名</th><th>学号</th><th>性别</th><th>班级</th><th>学科</th></tr>
</table>
<script src="js/jquery-3.3.1.js" charset="utf-8"></script><script>$.get("/getStuListServlet",function (stuData) {//遍历数据$(stuData).each(function (index, element) {element.sex==1?element.sex="男":element.sex="女";element.class_id = "就业班";element.subject_no = "java";$("<tr><td>"+element.id+"</td><td>"+element.student_name+"</td><td>"+element.student_no+"</td><td>"+element.sex+"</td><td>"+element.class_id+"</td><td>"+element.subject_no+"</td></tr>").appendTo($("#stuTable"));})});
</script></body>
</html>
【GetStuinfoServlet.java】 web层代码实现
package com.heima.servlet;import com.heima.service.StudentService;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet(urlPatterns = "/getStuListServlet")
public class GetStuinfoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//查询所有学员信息StudentService studentService = new StudentService();String stuJsonData = studentService.queryAllStudent();//响应数据resp.setContentType("text/json;charset=utf-8");resp.getWriter().println(stuJsonData);}
}
**【StudentService.java】**service层代码
package com.heima.service;import com.alibaba.fastjson.JSON;
import com.heima.dao.StudentDao;
import com.heima.domain.Student;
import com.heima.utils.JedisUtil;
import redis.clients.jedis.Jedis;import java.util.List;public class StudentService {StudentDao studentDao = new StudentDao();/*** 查询所有学员信息* @return*/public String queryAllStudent() {//先从redis中获取Jedis jedis = JedisUtil.getJedis();long redisBegin = System.currentTimeMillis();String stusData = jedis.get("stusData");if(null!=stusData){long redisEnd = System.currentTimeMillis();System.out.println("从redis中查询耗时:"+(redisEnd-redisBegin));}//从数据库中查询if (null == stusData) {long begin = System.currentTimeMillis();List<Student> studentList = studentDao.queryAll();long end = System.currentTimeMillis();System.out.println("从数据库中查询耗时:"+(end-begin));//将数据转化成json字符串stusData = JSON.toJSONString(studentList);//将数据存到redis中jedis.set("stusData", stusData);}//释放资源jedis.close();return stusData;}
}
【StudentDao.java】dao层代码
package com.heima.dao;import com.heima.domain.Student;
import com.heima.utils.JdbcTemplateUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;public class StudentDao {/*** 查询所有数据* @return*/public List<Student> queryAll() {JdbcTemplate jdbcTemplate = new JdbcTemplate(JdbcTemplateUtils.getDataSources());String sql = "select * from stu_info";List<Student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));return studentList;}
}
测试:分别测试从数据库查询和从redis中查询消耗的时间;
附: 安装Redis到系统服务中
win+R==》运行:services.msc
打开redis的官方安装文档:RedisService.docx
文档中有如下安装服务和卸载服务的说明:
【安装服务】
cmd进入到Redis的安装目录下,输入以下命令:
redis-server --service-install redis.windows.conf --loglevel verbose
安装完成后,查看系统服务列表(win+r 输入:services.msc),找到redis后右击启动:
NoSql数据库--Redis入门相关推荐
- NoSQL数据库Redis使用命令简介
NoSQL 数据库Redis使用命令简介 NOSQL数据库可以按照它们的数据模型分成4类: 1.键-值对存储库(Key-Value) redis-- 2.BigTable实现(BigTable-imp ...
- application实现网页计数_SpringBoot整合NoSQL 数据库(Redis)实现缓存
1.概述 随着互联网技术的发展,对技术要求也越来越高,所以在当期情况下项目的开发中对数据访问的效率也有了很高的要求,所以在项目开发中缓存技术使用的也越来越多,因为它可以极大的提高系统的访问速度,关于缓 ...
- 5.1.8 NoSQL数据库-Redis(键值key-value)-Redis配置详解
目录 1.写在前面 2.具体信息 2.1 单位 2.2 包含 2.3 网络 2.4 通用 GENERAL 2.5 快照 2.6 REPLICATION 主从复制 2.7 SECURITY 安全 2.8 ...
- 【捷哥浅谈PHP】第十八弹---NoSQL数据库Redis之莫问剑(String类型)的修炼
上文我给大家详细介绍了Redis数据库以及它的安装过程,及适用场景,上文我们说了,Redis数据库是基于 内存的数据库,速度极快,那今天我们来看看这种超级牛X的数据库的操作使用方法,还记得我上文提过的 ...
- Redis:Nosql数据库
Redis Nosql技术 redis介绍 什么是NoSql NoSql是为了解决高并发.高可扩展.高可用以及高写入而产生的数据库解决方案. NoSql就是Not Only sql.Nosql是非关系 ...
- TechTarget数据库Redis
2019独角兽企业重金招聘Python工程师标准>>> http://www.searchdatabase.com.cn/topic/redis.htm Redis NoSQL标准缺 ...
- 1.NoSQL之Redis配置与基础命令
文章目录 前言 一.关系数据库与非关系型数据库 1.关系型数据库 2.非关系型数据库 3.关系型数据库和非关系型数据库区别 3.1数据存储方式不同 3.2 扩展方式不同 3.3 对事务性的支持不同 4 ...
- 介绍非关系型数据库redis
介绍非关系型数据库redis 关系型和非关系型数据库 关系型数据库 非关系型数据库 两个数据库的区别 数据存储方式不同 扩展方式不同 多事务支持性不同 非关系型数据库的产生背景 基于"三高& ...
- 刘瑜《NoSQL数据库入门与实践 基于MongoDB、Redis》PDF下载
NoSQL数据库入门与实践 基于MongoDB.Redis [作 者]刘瑜,刘胜松著 [形态项] 483 [出版项] 北京:中国水利水电出版社 , 2018.03 [ISBN号]978-7-5170- ...
最新文章
- PointPillars:点云物体识别的快速编码
- C#定时清理内存,net网页端可以尝试使用
- Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16
- Spring请求参数校验
- 转载的孩子们注意节操哈!!!
- 创建外部快照_快照事件:现在如何仅通过拍照即可创建日历事件
- ABP入门系列(17)——使用ABP集成的邮件系统发送邮件
- easyui label显示不全_easyui 元素遍历问题
- java stringbuffer数组_Java中字符数组、String类、StringBuffer三者之间相互转换
- 带锚点进度条android,Axure:实现可拖动进度条
- SQL Server中的查询优化技术:数据库设计和体系结构
- QQ空间自动点赞代码
- 从国家大剧院古典音乐频道下载音乐
- 论文作业(1):VOIP 中Speex/ILBCISAC/SILK比较
- 使用sklearn处理经纬度的三种距离计算与地图可视化
- mysql操作语句类型DQL\DML\DDL\DCL
- 《MLB棒球创造营》:走近棒球运动·德州游骑兵队
- 阿里云CentOS7下载地址
- Mel spectrum梅尔频谱与MFCCs
- Cas实现子系统登录互踢