Redis-技术专题-Jedis实战入门

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Redis是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的Web应用程序。本文将概要介绍Redis的特性和语法,并以实例代码的形式介绍如何通过Jedis在java语言环境下控制Redis,帮助各位读者快速入门。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"NoSQL概述"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis是NoSQL数据库的代表之一,那什么是NoSQL?"}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"NoSQL = not only SQL,即非关系型数据库。"}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Why NoSQL?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和传统的关系型数据库相比,NoSQL具有以下的优势:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"High Performance:高并发读写;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"Huge Storage: 海量数据的高效存储和访问;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"High Scalability & High Availability:高可扩展和高可用性"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"NoSQL的分类:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"Key-Value,如Redis,快速查询,但是数据存储缺少结构化;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"列存储,如HBase, 扩展性强,查找速度快,但是功能局限;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"文档数据库,如MongoDB,数据格式灵活,查询性能不高,缺少统一的查询语法;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"图形数据库,如InfoGrid,基于图的算法,但是不容易做分布式的查询;"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Redis概述"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Redis是一个开源,高性能的键值对数据库, 其优点包括:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"异常快"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":" :Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"支持丰富的数据类型"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":" :Redis支持开发人员常用的大多数数据类型,例如"},{"type":"text","marks":[{"type":"italic"},{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"列表"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":","},{"type":"text","marks":[{"type":"italic"},{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"集合"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":","},{"type":"text","marks":[{"type":"italic"},{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"排序集"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"和"},{"type":"text","marks":[{"type":"italic"},{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"散列"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"等等。这使得Redis很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"操作具有原子性"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":" : 所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"多实用工具"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":" : Redis是一个多实用工具,可用于多种用例,如:"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"缓存"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":";"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"任务队列"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":";网站统计;"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"数据过期处理"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":";应用排行榜;"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"分布式集群的Session分离"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":";"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Redis与其他键值存储系统"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"Redis是键值数据库系统的不同进化路线,它的值可以包含更复杂的数据类型,可在这些数据类型上定义原子操作。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"Redis是一个内存数据库,但在磁盘数据库上是持久的,因此它代表了一个不同的权衡,在这种情况下,在不能大于存储器(内存)的数据集的限制下实现非常高的写和读速度。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"内存数据库的另一个优点是,它与磁盘上的相同数据结构相比,复杂数据结构在内存中存储表示更容易操作。 因此,Redis可以做很少的内部复杂性。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Redis的安装和使用"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis的安装是否简单,在Ubuntu上安装Redis,打开终端并键入以下命令即可"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"sudo apt-get update \nsudo apt-get install redis-server"}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"启动服务器:"},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"redis-server"}],"marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"启动客户端:"},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"redis-cli"}],"marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果是Windows环境下,则参照以下文章:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://link.jianshu.com/?t=http%3A%2F%2Fdownload.csdn.net%2Fdownload%2Ffengxinyixiao%2F9860813","title":null},"content":[{"type":"text","text":"http://download.csdn.net/download/fengxinyixiao/9860813"}]},{"type":"link","attrs":{"href":"https://link.jianshu.com/?t=http%3A%2F%2Fblog.csdn.net%2Fjoyhen%2Farticle%2Fdetails%2F47358999","title":null},"content":[{"type":"text","text":"http://blog.csdn.net/joyhen/article/details/47358999"}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Jedis入门"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Jedis是Redis官网首选的Java客户端开发包."}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d8/d8636d4b9df6615281dce3dcc6dd2062.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Jedis是Redis官网首选的Java客户端开发包"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其GItHub地址为:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fxetorthio%2Fjedis","title":null},"content":[{"type":"text","text":"https://github.com/xetorthio/jedis"}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Maven中,添加如下依赖即可使用:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"\n redis.clients\n jedis\n 2.9.0\n jar\n compile\n\n"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以下是官网是上给出的示例代码,连接本地Redis,进行操作."}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void ConnectionTest(){\n //1. Connecting to Redis server on localhost\n Jedis jedis = new Jedis(\"localhost\");\n System.out.println(\"Connection to server sucessfully\");\n //2. set the data in redis string\n jedis.set(\"username\", \"Roxin\");\n //3. Get the stored data and print it\n System.out.println(\"Stored string in redis:: \"+ jedis.get(\"username\"));\n //4. Close the Redis connection;\n jedis.close();\n }"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中通过调用"},{"type":"codeinline","content":[{"type":"text","text":"set"}]},{"type":"text","text":"方法来设置键值对,通过"},{"type":"codeinline","content":[{"type":"text","text":"get"}]},{"type":"text","text":"方法获取键值对。"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除此之外,Jedis还提供连接池的方式控制连接"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void ConnectionPoolTest(){\n //连接池设定\n JedisPoolConfig config = new JedisPoolConfig();\n //设定最大连接数\n config.setMaxTotal(30);\n //设置最大空闲连接数\n config.setMaxIdle(10);\n //创建连接池\n JedisPool jedisPool = new JedisPool(config, \"127.0.0.1\");\n //获得服务资源\n Jedis jedis = jedisPool.getResource();\n jedis.select(1);\n jedis.set(\"username\", \"Roxin By Jedis Pool\");\n System.out.println(jedis.get(\"username\"));\n jedis.close();\n jedisPool.close();\n }\n"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Redis的数据类型"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis中的数据类型有:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"字符串(String)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"列表(list)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"有序集合(sorted set)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"散列(hash)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"集合(set)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"无论哪种数据类型都需要为其设定键值Key,设置Key的注意点:"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"不要太长(<1024字节);"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"不要太短,有可读性;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":3,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"统一命名规范;"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"String"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Redis中的字符串是一个字节序列。Redis中的字符串是二进制安全的,这意味着它们的长度不由任何特殊的终止字符决定。因此,可以在一个字符串中存储高达512兆字节的任何内容。"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了上面提到的set/get方法,还有其他命令如下表:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a9/a93f1bef74bfdd7f3d585c8228b84119.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Hash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 相当于Map,在Redis中,每个哈希(散列)可以存储多达4亿个键-值对。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Jedis示例代码如下"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void HashTest(){\n Jedis jedis = jedisPool.getResource();\n String hashKey = \"hashKey\";\n //hset设置一个键值对\n jedis.hset(hashKey,\"user\",\"Roxin\");\n HashMap map = new HashMap<>();\n for (int i = 0; i < 10; i++) {\n map.put(\"field\"+i,\"value\"+i);\n }\n //设置多个键值对\n jedis.hmset(hashKey,map);\n //获得键值对的个数\n Long hlen = jedis.hlen(hashKey);\n System.out.println(\"Hash Size in redis:: \"+hlen);\n assert hlen==11;\n //得到全部键值对\n List user = jedis.hmget(hashKey, \"user\");\n System.out.println(\"Stored string in redis:: \"+ user);\n assert user.get(0).equals(\"Roxin\");\n //删除键值\n jedis.del(hashKey);\n jedis.close();\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis关于Hash类型的常见命令如下表:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/42/42e0f41957db0f35571891d10bcface1.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"list"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Redis列表只是字符串列表,按插入顺序排序。可以在列表的头部或尾部添加Redis列表中的元素。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"列表的最大长度为"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":"2^32 - 1个元素(即4294967295,每个列表可存储超过40亿个元素)"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Jedis中示例代码如下"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void ListTest(){\n Jedis jedis = jedisPool.getResource();\n String listKey = \"LISTKEY\";\n for (int i = 0; i < 10; i++) {\n //从头插入一个元素\n jedis.lpush(listKey,\"L-value\");\n }\n List list = jedis.lrange(listKey, 0, -1);//从第一个到最后一个,负数代表倒数第几个\n assert list.size() == 10;\n assert \"L-value\".equals(jedis.rpop(listKey));//从尾部取出一个元素\n assert 9==jedis.llen(listKey);\n jedis.rpush(listKey,\"R-valure\");//从尾部加入一个元素\n jedis.lrem(listKey,2,\"L-value\");//删除从左数2两个\"L-value\"元素\n jedis.lrem(listKey,0,\"L-value\"); //0表示删除全部\"L-value\"元素\n assert \"R-valure\".equals(jedis.lpop(listKey));//从头部加入一个元素\n jedis.del(listKey);\n jedis.close();\n }"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis中关于list的命令如下表:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e0/e05514f606453728165605da66d95ae8.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"需要特别说明下:"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"codeinline","content":[{"type":"text","text":"rpoplpush source destination"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}},{"type":"strong"}],"text":" 删除列表中的最后一个元素,将其附加到另一个列表并返回,在消息队列中,可以用于消息备份:当消息被发布后,一个消息从主消息队列中被取出,被放入到缓存队列中,当确认发生成功之后,再将其彻底删除,如果发送不成功,就恢复该消息。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/df/df48338166a31ec201e34e58656f0d14.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Set"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Redis集合是唯一字符串的无序集合。 唯一值表示集合中不允许键中有重复的数据。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 在Redis中设置添加,删除和测试成员的存在(恒定时间O(1),而不考虑集合中包含的元素数量)。列表的最大长度为2^32 - 1个元素(即4294967295,每组集合超过40亿个元素)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"存储Set的使用场景:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跟踪唯一性数据"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用于维护数据对象之间的关联关系;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Jedis的代码示例:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void SetTest(){\n Jedis jedis = jedisPool.getResource();\n String setKey1 = \"SETKEY-1\";\n for (int i = 0; i < 10; i++) {\n //添加一个元素\n jedis.sadd(setKey1,\"value-\"+i);\n }\n assert 10 == jedis.scard(setKey1); //获得元素个数\n jedis.sadd(setKey1,\"value-1\");//添加重复的元素将失效\n assert 10 == jedis.scard(setKey1);\n String s= jedis.srandmember(setKey1);//随机获取一个元素\n assert jedis.sismember(setKey1,s);//是否为集合成员\n String setKey2 = \"SETKEY-2\";\n for (int i = 1; i < 11; i++) {\n jedis.sadd(setKey2,\"value-\"+i);\n }\n assert jedis.sdiff(setKey1,setKey2).size() == 1;//补集\n assert jedis.sinter(setKey1,setKey2).size() == 9;//交集\n assert jedis.sunion(setKey1,setKey2).size() == 11;//并集\n jedis.del(setKey1,setKey2);\n jedis.close();\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis中关于Set的命令如下表:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a8/a8c34249ac27b28a31cb8d254726598b.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Sorted-Set"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Redis可排序集合类似于Redis集合,是不重复的字符集合。 不同之处在于,排序集合的每个成员都与分数相关联,这个分数用于按最小分数到最大分数来排序的排序集合。虽然成员是唯一的,但分数值可以重复。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Sorted-Set的使用场景:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大型在线游戏的积分排名;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"构建索引数据;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Jedis中的示例:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void SortedSetTest(){\n Jedis jedis = jedisPool.getResource();\n String sortedSetKey = \"SORTEDSETKEY\";\n for (int i = 0; i < 10; i++) {\n //添加一个元素\n jedis.zadd(sortedSetKey,i*10,\"v-\"+i);\n }\n assert 10 == jedis.zcard(sortedSetKey);//获得集合中元素个数\n assert 20 == (jedis.zscore(sortedSetKey,\"v-2\"));//获得集合中元素对应的分数\n Set set = jedis.zrange(sortedSetKey, 0, -2);//从第一个到倒数第二个\n assert 9 == set.size() ;\n assert !set.contains(\"v-9\");\n jedis.zincrby(sortedSetKey,20,\"v-1\");//让元素的分数增长20\n assert 30 == jedis.zscore(sortedSetKey,\"v-1\");\n assert 3 == jedis.zcount(sortedSetKey,20,30);//获得分数段中元素个数\n jedis.del(sortedSetKey);\n jedis.close();\n }"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Keys的通用操作"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Jedis中关于键值操作的实例:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void KeyTest(){\n Jedis jedis = jedisPool.getResource();\n String key = \"TESTKEY-1\";\n String key2 = \"TESTKEY-2\";\n jedis.set(key2,\"\");//设置键值\n jedis.rename(key2,key);//键值重命名\n System.out.println(\"Key Type:\"+jedis.type(key));//键值的类型\n assert jedis.exists(key);//键值是否存在\n jedis.expire(key,1);//设置键值过期时间\n assert 1 == jedis.ttl(key);//查看键值过期时间\n try {\n Thread.sleep(2000);//睡眠2s\n } catch (InterruptedException e) {\n e.printStackTrace();\n }\n assert !jedis.exists(key);//键值已过期,不存在\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis中关于键值的其他命令:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d1/d178f71e3dd7aaa93fc37d0cc053f492.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"KEYS pattern"}]},{"type":"text","text":" 查找与指定模式匹配的所有键:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"keys * 查看所有的key;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"keys xx? 模糊匹配key;"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Redis的特性"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"多数据"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"提供16个数据库(0-15),默认为0号数据库,可是通过"},{"type":"codeinline","content":[{"type":"text","text":"select index"}]},{"type":"text","text":"选择。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"事务"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和关系型数据库一样,Redis也提供事务性操作:"}]},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DISCARD 丢弃在MULTI之后发出的所有命令(放弃事务,回滚)"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"EXEC 执行MULTI后发出的所有命令(提交事务)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"MULTI 标记事务块的开始(开始事务)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"UNWATCH 取消 WATCH 命令对所有 key 的监视。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"WATCH key [key …] 监视给定的键以确定MULTI / EXEC块的执行"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis中示例代码如下:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" @Test\n public void TransactionTest(){\n //获得服务资源\n Jedis jedis = jedisPool.getResource();\n jedis.select(1);\n Transaction transaction = jedis.multi();//开启事务\n transaction.set(\"username\", \"Roxin in transaction1\");\n System.out.println(transaction.get(\"username\"));\n transaction.exec();//提交事务\n System.out.println(jedis.get(\"username\"));\n transaction = jedis.multi();//开启事务\n transaction.set(\"username\", \"Roxin in transaction2\");\n System.out.println(transaction.get(\"username\"));\n transaction.discard();//撤销事务\n System.out.println(jedis.get(\"username\"));\n jedis.close();\n }\n"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Redis持久化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis是一个内存数据库,但在磁盘数据库上是持久化的,持久化的方式分为两种:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RDB:默认方式,定时将内存数据集快照写入磁盘;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AOF:以日志的方式,记录所有操作;"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"RDB"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"优势"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"数据只存在一个文件中,便于数据归档和整理;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多线程启动,性能好;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"劣势"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果在两次快照写操作之间出现问题,将无法回复期间的数据;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多线程启动的时候,可能会有停顿;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"配置文件为Redis按照目录下的 redis.conf:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/07/072d7031ea58a258c192943923129609.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"redis.conf 保存频率的设施"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这是配置文件设置内存快照写入磁盘的条件"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# In the example below the behaviour will be to save:\n# after 900 sec (15 min) if at least 1 key changed\n# after 300 sec (5 min) if at least 10 keys changed\n# after 60 sec if at least 10000 keys changed\nsave 900 1 \nsave 300 10\nsave 60 10000\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"数据文件被定义为"},{"type":"codeinline","content":[{"type":"text","text":"dump.rdb"}]},{"type":"text","text":",保存路径为Redis的按照路径。"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# The filename where to dump the DB\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# Note that you must specify a directory here, not a file name.\ndir ./\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f1/f14c938786c276580504e348a944de73.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Redis数据文件,只有一个数据文件"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"AOF"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"优势:"}]},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"更高的数据安全性,有三种数据同步策略:"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"日志是追加(append)模式,即使有宕机,也不会用问题。 如果是数据写入一半出现问题,可以使用redis-check-aof,恢复数据一致;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"日志自动重写,以防止日志过大;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"日志格式清楚明了,可用于数据重建;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"劣势:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文件要更大;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"运行效率更低;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"配置文件中关于AOF的配置:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d6/d624d1b0b8adc62aaeaa52671526e096.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"关于AOF的配置"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"默认不使用;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"日志文件为 "},{"type":"codeinline","content":[{"type":"text","text":"appendonly.aof"}]}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# The name of the append only file (default: \"appendonly.aof\")\nappendfilename \"appendonly.aof\"\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面提高的三种同步策略;"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# no: don't fsync, just let the OS flush the data when it wants. Faster.\n# always: fsync after every write to the append only log. Slow, Safest.\n# everysec: fsync only one time every second. Compromise.\n#\n# The default is \"everysec\",If unsure, use \"everysec\".\n\n# appendfsync always\nappendfsync everysec\n# appendfsync no"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章