redis是一个key-value存储系统,目前提供几种数据类型:string,list,set及zset(sorted set),hash。周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
安装及各数据类型及cli命令的使用可参考官网。
redis是一个可以替代memcached的内存库,拥有更多的功能,更好的性能。
需要排序时可使用集合list,set和sorted set,redis对此提供较多的支持。
redis支持简单的事务,高版本有类似乐观锁同步的实现。
redis可以以pipeline方式打包命令发送,在处理完所有命令前先缓存起所有命令的处理结果。
支持发布订阅(pub/sub)消息通道模式。
redis的持久化有快照和aof两种方式,前一种是默认的,后一种类似实现了oracle的redo-log,可在恢复数据时用于前滚。aof由appendonly参数决定。
redis实现了类似mysql的master-slave模式的主从复制,mysql用的是binlog文件,redis也是用的数据库快照文件,第一次连接,master检测到有slave存在时,启动进程保存数据,然后发给所有的slave,slave加载到内存。
redis有虚拟内存的配置,不同于os的vm,物理内存用满之后可选中部分数据进vm。
在java web 里使用redis,我们要选用jedis客户端和封装其使用的spring-data-redis。
下面是jedis的简单使用例子:
- public void TestSimple(){
- Jedis jedis = new Jedis("192.168.1.112");
- String keys = "name";
- jedis.del(keys);
- jedis.set(keys, "cuirong");
- String value = jedis.get(keys);
- System.out.println(value);
- }
public void TestSimple(){
Jedis jedis = new Jedis("192.168.1.112");
String keys = "name";
jedis.del(keys);
jedis.set(keys, "cuirong");
String value = jedis.get(keys);
System.out.println(value);
}
以下是jedispool的使用,显得过于臃肿,用spring管理更好些:
- public void TestJedisPool(){
- Properties pro = new Properties();
- try {
- pro.load(this.getClass().getResourceAsStream("/redis.properties"));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- JedisPool pool;
- ResourceBundle bundle = ResourceBundle.getBundle("redis");
- if (bundle == null) {
- throw new IllegalArgumentException(
- "[redis.properties] is not found!");
- }
- JedisPoolConfig config = new JedisPoolConfig();
- config.setMaxActive(Integer.valueOf(bundle.getString("redis.pool.maxActive")));
- config.setMaxIdle(Integer.valueOf(bundle.getString("redis.pool.maxIdle")));
- config.setMaxWait(Long.valueOf(bundle.getString("redis.pool.maxWait")));
- config.setTestOnBorrow(Boolean.valueOf(bundle.getString("redis.pool.testOnBorrow")));
- config.setTestOnReturn(Boolean.valueOf(bundle.getString("redis.pool.testOnReturn")));
- pool = new JedisPool(config, bundle.getString("redis.ip"),
- Integer.valueOf(bundle.getString("redis.port")));
- Jedis jedis = pool.getResource();
- String keys = "name";
- jedis.del(keys);
- jedis.set(keys, "haha");
- String value = jedis.get(keys);
- System.out.println(value);
- // 释放对象池
- pool.returnResource(jedis);
- }
public void TestJedisPool(){
Properties pro = new Properties();
try {
pro.load(this.getClass().getResourceAsStream("/redis.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
JedisPool pool;
ResourceBundle bundle = ResourceBundle.getBundle("redis");
if (bundle == null) {
throw new IllegalArgumentException(
"[redis.properties] is not found!");
}
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(Integer.valueOf(bundle.getString("redis.pool.maxActive")));
config.setMaxIdle(Integer.valueOf(bundle.getString("redis.pool.maxIdle")));
config.setMaxWait(Long.valueOf(bundle.getString("redis.pool.maxWait")));
config.setTestOnBorrow(Boolean.valueOf(bundle.getString("redis.pool.testOnBorrow")));
config.setTestOnReturn(Boolean.valueOf(bundle.getString("redis.pool.testOnReturn")));
pool = new JedisPool(config, bundle.getString("redis.ip"),
Integer.valueOf(bundle.getString("redis.port")));
Jedis jedis = pool.getResource();
String keys = "name";
jedis.del(keys);
jedis.set(keys, "haha");
String value = jedis.get(keys);
System.out.println(value);
// 释放对象池
pool.returnResource(jedis);
}
- public class TestSharedJedis {
- private ApplicationContext app;
- private ShardedJedisPool pool;
- ShardedJedis jedis;
- @Before
- public void before() throws Exception {
- app = new ClassPathXmlApplicationContext("redis_AppContext.xml");
- pool = (ShardedJedisPool) app.getBean("shardedJedisPool");
- }
- @Test
- public void TestList(){
- ShardedJedis jedis = pool.getResource();
- jedis.lpush("list2", "a","b","c");
- }
- @Test
- public void test() {
- // 从池中获取一个Jedis对象
- ShardedJedis jedis = pool.getResource();
- String keys = "10101";
- String value = "hehe";
- for(int i=4;i<9;i++){
- keys = keys+i;
- value = value+i;
- jedis.del(keys);
- jedis.set(keys, value);
- String v = jedis.get(keys);
- System.out.println(v);
- keys = "1001";
- value = "haha";
- }
- // 释放对象池
- pool.returnResource(jedis);
- pool.destroy();
- //assertEquals(value, v);
- }
- @After
- public void after(){
- pool.returnResource(jedis);
- pool.destroy();
- }
- }
public class TestSharedJedis {
private ApplicationContext app;
private ShardedJedisPool pool;
ShardedJedis jedis;
@Before
public void before() throws Exception {
app = new ClassPathXmlApplicationContext("redis_AppContext.xml");
pool = (ShardedJedisPool) app.getBean("shardedJedisPool");
}
@Test
public void TestList(){
ShardedJedis jedis = pool.getResource();
jedis.lpush("list2", "a","b","c");
}
@Test
public void test() {
// 从池中获取一个Jedis对象
ShardedJedis jedis = pool.getResource();
String keys = "10101";
String value = "hehe";
for(int i=4;i<9;i++){
keys = keys+i;
value = value+i;
jedis.del(keys);
jedis.set(keys, value);
String v = jedis.get(keys);
System.out.println(v);
keys = "1001";
value = "haha";
}
// 释放对象池
pool.returnResource(jedis);
pool.destroy();
//assertEquals(value, v);
}
@After
public void after(){
pool.returnResource(jedis);
pool.destroy();
}
}
关于pool的使用有两个地方要注意,一个是get之后使用完后要return,第二个是jedisPoolConfig要设置属性 <property name="testOnBorrow" value="true"/ >, 取之前先检查连接,如果断了再从池中取出一个,这样做也避免了bean中配置getPool时始终使用同一个连接的错误用法。
当使用redis集群时,jedis客户端亦实现了一致性hash来保证负载均衡。