Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
1.下载地址:http://redis.io/download,下载最新版本的linux版本Redis。
2.本教程使用的最新文档版本为 4.0.6,下载文件后,上传到linux服务器上面,并解压安装。
操作指令为:$ tar xzf redis-4.0.6.tar.gz $ cd redis-4.0.6 $ make
3.make成功执行完后 redis- 4.0.6目录会生成src 目录,在一次执行命令:$ make install
4.启动redis服务,使用默认配置方式启动:进入到redis-4.0.6/src目录,执行启动命令:redis-server
注意:这里直接执行Redis-server 启动的Redis服务,是在前台直接运行的(效果如上图),也就是说,执行完该命令后,如果Linux关闭当前会话,则Redis服务也随即关闭。正常情况下,启动Redis服务需要从后台启动,并且指定启动配置文件。
后台启动redis服务
在本地电脑上,安装一个redis客户端连接工具,如:redisclient-win32.x86.1.5。利用连接工具可方便查看redis中设置的缓存数据,连接如图所示:
jedis 是 Redis 官方首选的 Java 客户端开发包,上手比较容易。jedis提供了以下三种操作方式:
jedis操作redis模式
(1)事务方式(Transactions)
所谓事务,即一个连续操作,是否执行是一个事务,要么完成,要么失败,没有中间状态。而redis的事务很简单,他主要目的是保障,一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令,也就是事务的连贯性。
测试截图
(2)管道(Pipelining)
管道是一种两个进程之间单向通信的机制。那再redis中,为何要使用管道呢?有时候,需要采用异步的方式,一次发送多个指令,并且,不同步等待其返回结果。这样可以取得非常好的执行效率。管道模式测试代码:
@Test public void jedisPipelined() { Jedis jedis = new Jedis("192.168.210.128", 6379); Pipeline pipeline = jedis.pipelined(); long start = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { pipeline.set("p" + i, "p" + i); } List
注意:事务和管道都是异步模式。在事务和管道中不能同步查询结果。如下代码操作为非法操作:
Transaction tx = jedis.multi(); for (int i = 0; i < 100000; i++) { tx.set("t" + i, "t" + i); } System.out.println(tx.get("t1000").get()); //不允许 List
(3)管道中调用事务
在某种需求下,需要异步执行命令,但是,又希望多个命令是有连续的,所以可采用管道加事务的调用方式。jedis是支持在管道中调用事务的。
(4)分布式直连同步调用与分布式连接池同步调用
这个是分布式直接连接,并且是同步调用,每步执行都返回执行结果。如果,分布式调用代码是运行在线程中,那么分布式直连同步调用方式就不合适了,因为直连方式是非线程安全的,这个时候需使用选择连接池调用。案例代码:
//分布式直接链接并同步调用 public void jedisShardNormal() { Listshards = Arrays.asList( new JedisShardInfo("localhost",6379), new JedisShardInfo("localhost",6380)); ShardedJedis sharding = new ShardedJedis(shards); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { String result = sharding.set("sn" + i, "n" + i); } long end = System.currentTimeMillis(); System.out.println("Simple@Sharing SET: " + ((end - start)/1000.0) + " seconds"); sharding.disconnect(); } //分布式结合线程池使用 public void jedisShardSimplePool() { List shards = Arrays.asList( new JedisShardInfo("localhost",6379), new JedisShardInfo("localhost",6380)); ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards); ShardedJedis one = pool.getResource(); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { String result = one.set("spn" + i, "n" + i); } long end = System.currentTimeMillis(); pool.returnResource(one); System.out.println("Simple@Pool SET: " + ((end - start)/1000.0) + " seconds"); pool.destroy(); }
(5)分布式直连异步调用与分布式连接池异步调用
操作与同步相对,案例代码如下:
//分布式连接池异步调用测试 线程池使用 public void jedisShardPipelinedPool() { Listshards = Arrays.asList( new JedisShardInfo("localhost",6379), new JedisShardInfo("localhost",6380)); ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards); ShardedJedis one = pool.getResource(); ShardedJedisPipeline pipeline = one.pipelined(); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { pipeline.set("sppn" + i, "n" + i); } List
(6)安全线程连接池(JedisPool)
注意Jedis对象并不是线程安全的,在多线程下使用同一个Jedis对象会出现并发问题。为了避免每次使用Jedis对象时都需要重新构建,Jedis提供了JedisPool
。JedisPool
是基于Commons Pool 2实现的一个线程安全的连接池。
//线程池模式使用测试: JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(10); JedisPool pool = new JedisPool(jedisPoolConfig, "localhost", 6379); Jedis jedis = null; try{ jedis = pool.getResource(); jedis.set("pooledJedis", "hello jedis pool!"); System.out.println(jedis.get("pooledJedis")); }catch(Exception e){ e.printStackTrace(); }finally { //还回pool中 if(jedis != null){ jedis.close(); } } pool.close();
(7)多机分布式集合连接池使用
此方式适用规模较大的系统,往往会有多个Redis实例做负载均衡。并且还实现主从备份,当主实例发生故障时,切换至从备用实例提供服务。如服务器1挂掉后,可用服务器2继续支撑redis缓存处理。测试代码:
** * Description: 多机分布式+连接池方式: * Copyright: 2018 CSNT. All rights reserved. * Company:CSNT * * @author wangling * @version 1.0 */ public class MultipleJedisPoolTest { static JedisPoolConfig config; static ShardedJedisPool sharedJedisPool; static { // 生成多机连接List Listshards = new ArrayList (); shards.add( new JedisShardInfo("127.0.0.1", 6379) ); shards.add( new JedisShardInfo("192.168.210.128", 6379) ); // 初始化连接池配置对象 config = new JedisPoolConfig(); config.setMaxIdle(10); config.setMaxTotal(30); config.setMaxWaitMillis(2*1000); // 实例化连接池 sharedJedisPool = new ShardedJedisPool(config, shards); } /** * @param args */ public static void main(String[] args) { // 从连接池获取Jedis连接 ShardedJedis shardedJedisConn = sharedJedisPool.getResource(); shardedJedisConn.set("Lemon", "Hello,my name is Lemon"); System.out.println(shardedJedisConn.get("Lemon")); // 释放连接 close(shardedJedisConn, sharedJedisPool); } private static void close(ShardedJedis shardedJedis,ShardedJedisPool sharedJedisPool){ if(shardedJedis!=null &&sharedJedisPool!=null){ sharedJedisPool.returnResource(shardedJedis); } if(sharedJedisPool!=null){ sharedJedisPool.destroy(); } } }
5.Redis常用命令
1 连接操作命令
2 持久化
3 远程服务控制
4 对key操作的命令
5 String
6 List
7 Set
8 Hash
Redis详解与常见问题解决方案