前言: 日常Java Web中使用数据库来存储,一般不会有高并发的问题,可一旦涉及高并发的情况, 比如商品抢购,主页访问量瞬间较大,使用数据库会产生磁盘读写带来的性能瓶颈, 通过引入NoSql技术基于内存的数据库,可克服上述问题。 Redis是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。 Redis与其他key-value缓存产品比较有一下三个特点: 1.Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启后可加载使用。 2.不仅支持简单的key-value类型的数据,还提供list,set,zset,hash等数据结构的存储。 3.支持数据的备份,即master-slave模式的数据备份。 Redis的优势 1.性能极高,支持每秒十几万次读/写操作。 2.丰富的数据类型,支持二级制Strings,Lists,Hashes,Sets及Ordered Sets数据类型操作 3.原子,Redis所有操作都是原子性的,要么成功要么失败不执行,单个操作是原子性,多个操作 也支持事务。 4.丰富的特性,支持publish/subscribe,通知,key过期等等特性。 Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存 Redis能做什么: 1.存储缓存用的数据 2.需要高速读/写的场合使用它快速读/写 Redis不能做什么 1.数据量太大不适合 2.数据访问频率太低不适合 缓存的读写: 日常读写比例大约在1:9到3:7,读比写占的比重大,当使用数据库SQL语句读写时, 数据读写磁盘的速度相对较慢,若放在Redis中服务端可直接读取内存中的数据,速度提升较多,数据库压力减少, 但同时考虑内存的大小问题,一般只是使用Redis存储常用和主要的数据,比如用户登录信息。 一般使用Redis存储时,会考虑以下方面: 1.该业务数据常用么?命中率如何? 若命中率低,没有必要写入缓存; 2.该业务读操作多,还是写操作多? 若频繁需要写入数据库,也没有必要; 3.业务数据大小如何? 若存储几百兆文件会给缓存带来很大压力。 Redis缓存读取逻辑: 当第一次读取Redis数据时会找不到,触发程序读取数据库,把数据读取出来并写入Redis。 当第二次需要读取时会直接读取Redis,读到数据结束流程。 根据以上可知,Redis使用读大于写操作,同时经常读取且命中率较高的场景。 Redis缓存更新操作: Redis->更新/写入数据库->更新/写入Redis 当Redis更新或者写入操作,需要多个Redis的操作,若业务数据写次数大于读次数则 没有必要使用Redis。 Redis高速读写场合逻辑: 当一个请求到达服务器时,只是把业务数据库在Redis上读写,没有对数据库进行任何操作。 大大提高读写速度。 但这些缓存数据需要持久化,所以请求操作完Redis读/写后会判断该高速读/写业务是否结束, 这个判断通常在秒杀商品为0/红包金额为0时成立,若不成立则不会操作数据库, 若成立则触发事件将Redis的缓存数据以批量的形式一次性写入数据库,完成持久化工作。 下载Redis压缩包: https://github.com/ServiceStack/redis-windows/tree/master/downloads 解压后新建一个startup.cmd的文件,填写redis-server redis.windows.conf 这个命令是在调用redis-server.exe命令来读取redis.window.conf的内容。 启动redis-server后,打开redis-cli.exe客户端工具,输入以下表示测试成功。 127.0.0.1:6379> set key1 value1 OK 127.0.0.1:6379> get key1 "value1" 创建java Redis项目 Jedis是一个非常小而且正常的Redis java客户端,复制以下pom内容到maven项目中, https://mvnrepository.com/artifact/redis.clients/jedis/2.9.0 import redis.clients.jedis.Jedis; import java.util.Iterator; import java.util.List; import java.util.Set; public class HelloWorld { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis jedis = new Jedis("localhost"); System.out.println("连接成功"); jedis.set("runobj","yangeoo.iteye.com"); //查看服务是否运行 System.out.println("Redis存储的字符串: "+jedis.get("runobj")); //设置List字符串 jedis.lpush("site-list", "Runoob"); jedis.lpush("site-list", "Google"); jedis.lpush("site-list", "Taobao"); // 获取存储的数据并输出 List<String> list = jedis.lrange("site-list", 0 ,2); for(int i=0; i<list.size(); i++) { System.out.println("列表项为: "+list.get(i)); } // 获取数据并输出 Set<String> keys = jedis.keys("*"); Iterator<String> it=keys.iterator() ; while(it.hasNext()){ String key = it.next(); System.out.println(key); } } } Redis连接数据库: redis-cli -h host -p port -a password Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。 String(字符串) string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。 示例 127.0.0.1:6379> set runoob "HelloWorld!" OK 127.0.0.1:6379> get runoob "HelloWorld!" 127.0.0.1:6379> set runoob "123" OK 127.0.0.1:6379> del runoob //删除runoob变量 (integer) 1 127.0.0.1:6379> get runoobj (nil) Hash(哈希) Redis hash 是一个键值(key=>value)对集合。 Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象 实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。 每个hash可以存储键值对(40多亿). 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World!" (error) WRONGTYPE Operation against a key holding the wrong kind of value //DEL runoob 用于删除前面测试用过的 key,不然会报错 127.0.0.1:6379> del runoob (integer) 1 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World!" OK 127.0.0.1:6379> hget runoob field1 "Hello" 127.0.0.1:6379> hget runoob field2 "World!" List(列表) Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。 列表最多可存储4294967295元素 127.0.0.1:6379> lpush runoob redis (integer) 1 127.0.0.1:6379> lpush runoob mongodb (integer) 2 127.0.0.1:6379> lpush runoob rabitmq (integer) 3 127.0.0.1:6379> lpush runoob redis (integer) 4 127.0.0.1:6379> lrange runoob 0 10 1) "redis" 2) "rabitmq" 3) "mongodb" 4) "redis" Redis 的 Set 是 string 类型的无序集合。 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 sadd 命令 添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。 sadd key member 集合中最大可存储40多亿个成员。 127.0.0.1:6379> del runoob (integer) 1 127.0.0.1:6379> sadd runoob redis (integer) 1 127.0.0.1:6379> sadd runoob mongodb (integer) 1 127.0.0.1:6379> sadd runoob rabitmq (integer) 1 127.0.0.1:6379> sadd runoob rabitmq //添加相同的已存在的元素则返回0 (integer) 0 127.0.0.1:6379> smembers runoob 1) "mongodb" 2) "rabitmq" 3) "redis" zset(sorted set:有序集合) Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。 zset的成员是唯一的,但分数(score)却可以重复。 zadd 命令 添加元素到集合,元素在集合中存在则更新对应score zadd key score member 127.0.0.1:6379> del runoob (integer) 1 127.0.0.1:6379> zadd runoob 1 redis (integer) 1 127.0.0.1:6379> zadd runoob 3 rabitmq (integer) 1 127.0.0.1:6379> zadd runoob 2 redis (integer) 0 127.0.0.1:6379> zadd runoob 3 oracle (integer) 1 127.0.0.1:6379> zrangebyscore runoob 0 1000 1) "redis" 2) "oracle" 3) "rabitmq" 127.0.0.1:6379> zadd runoob 4 oracle (integer) 0 127.0.0.1:6379> zrangebyscore runoob 0 1000 1) "redis" 2) "rabitmq" 3) "oracle" 应用场景: String字符串 : 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M Hash(字典):键值对集合,即编程语言中的Map类型,适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值,适用场景:用于存储、读取、修改用户属性。 List(列表): 增删快,提供了操作某一段元素的API,适用场景:1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列 Set(集合):哈希表实现,元素不重复1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作。 适用场景:1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 Sorted Set(有序集合):将Set中的元素增加一个权重参数score,元素按score有序排列。数据插入集合时,已经进行天然排序。 1、排行榜 2、带权重的消息队列 Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享。 一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中,可以把每个字典都理解成一个独立的数据库。 每个数据库对外都是从0开始的递增数字命名,默认支持16个数据库,客户端连接自动选择0数据库,可以通过SELECT命令更换。比如 选择1号数据库: select 1 开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码, 所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的, 比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据. 综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据. Redis发布/订阅 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。 client1: 127.0.0.1:6379> subscribe redisChat //订阅redisChat频道 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1 1) "message" 2) "redisChat" 3) "123" client2: 127.0.0.1:6379> subscribe redisChat //订阅redisChat频道 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1 1) "message" 2) "redisChat" 3) "Redis is a great caching technique" 1) "message" 2) "redisChat" 3) "Learn redis by runoob.com" 1) "message" 2) "redisChat" 3) "123" client3: //向redisChat发布消息 127.0.0.1:6379> publish redisChat "Redis is a great caching technique" (integer) 1 127.0.0.1:6379> publish redisChat "Learn redis by runoob.com" (integer) 1 127.0.0.1:6379> publish redisChat "123" (integer) 2 Redis事务 Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证: 批量操作在发送 EXEC 命令前被放入队列缓存。 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。 一个事务从开始到执行会经历以下三个阶段: 开始事务。 命令入队。 执行事务 以下是一个事务的例子,它先以 MULTI 开始一个事务,然后将多个命令入队到事务中,最后由 EXEC 命令触发事务,一并执行事务中的所有命令: 127.0.0.1:6379> multi OK 127.0.0.1:6379> set book-name "Mastering C++ in 21 days" QUEUED 127.0.0.1:6379> get book-name QUEUED 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series" QUEUED 127.0.0.1:6379> SMEMBERS tag QUEUED 127.0.0.1:6379> EXEC 1) OK 2) "Mastering C++ in 21 days" 3) (integer) 3 4) 1) "Mastering Series" 2) "Programming" 3) "C++" 单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做 Redis分区 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。 分区的优势 通过利用多台计算机内存的和值,允许我们构造更大的数据库。 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。 分区的不足 redis的一些特性在分区方面表现的不是很好: 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。 涉及多个key的redis事务不能使用。 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。 增加或删除容量也比较复杂。 分区类型 范围分区 最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的Redis实例。 比如,ID从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1,以此类推。 这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表。这个表要被管理,同时还需要各种对象的映射表, 通常对Redis来说并非是好的方法。 哈希分区 另外一种分区方法是hash分区。这对任何key都适用,也无需是object_name:这种形式,像下面描述的一样简单: 用一个hash函数将key转换为一个数字,比如使用crc32 hash函数。对key foobar执行crc32(foobar)会输出类似93024922的整数。 对这个整数取模,将其转化为0-3之间的数字,就可以将这个整数映射到4个Redis实例中的一个了。93024922 % 4 = 2, 就是说key foobar应该被存到R2实例中。注意:取模操作是取除的余数,通常在多种编程语言中用%操作符实现。
相关推荐
以下是对 Redis 入门指南的一些关键知识点的详细说明: 1. **Redis 数据类型** - **字符串(String)**:Redis 最基本的数据类型,可以存储字符串、数字等,支持自增、自减操作。 - **哈希(Hash)**:用于存储...
本指南将帮助初学者理解 Redis 的基本概念、安装与配置、数据类型以及常用命令,从而快速入门 Redis。 1. **Redis 简介** - Redis 源自意大利程序员 Salvatore Sanfilippo,最初是为了提高网站性能而设计的。 - ...
本书是一本Redis入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史特性、在开发和生产环境中部署运行Redis、数据类型与命令、使用Redis实现队列、事务、复制、管道、持久化、优化Redis存储...
《Redis入门指南(第2版)》是一本Redis的入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史与特性、在开发和生产环境中部署运行Redis、数据类型与命令、使用Redis实现队列、事务、复制、...
Redis入门到精通最新教学视频!!!!!!!!!!!!!!!!!!!
Redis入门指南 第2版 高清PDF完整扫描版.pdf 。搜集整理自互联网,仅供个人学习,严禁用于商业用途,如有版权问题,请联系删除。
《Redis入门指南(第2版)》是一本Redis的入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史与特性、在开发和生产环境中部署运行Redis、数据类型与命令、使用Redis实现队列、事务、复制、...
《Redis入门指南》是一本Redis的入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史与特性、在开发和生产环境中部署运行Redis、数据类型与命令、使用Redis实现队列、事务、复制、管道、持久...
《Redis入门指南》是一本Redis的入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史与特性、在开发和生产环境中部署运行Redis、数据类型与命令、使用Redis实现队列、事务、复制、管道、持久...
redis 入门教程,高清扫描版。免费下载、
**Redis入门指南** Redis,全称Remote Dictionary Server,是一款开源的、高性能的键值存储系统。它被广泛用于数据缓存、消息队列、数据库等多个领域。本指南将基于《Redis入门指南第2版》的内容,详细介绍Redis的...
Redis入门简单实例,附带详细说明,代码可直接运行,欢迎交流。
**Redis入门第二版** Redis,全称Remote Dictionary Server,是一个开源的、高性能的键值存储系统,常被用作数据库、缓存和消息中间件。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,这使得Redis...
《Redis入门指南》是一本Redis的入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史与特性、在开发和生产环境中部署运行Redis、数据 ...