Redis在各个分布式数据库中,原理不算复杂,简单来说就是一句话:哈希切割再哈希切割再哈希。由于redis是内存数据库,所有数据都在内存中,所以什么索引,过滤器啊都不需要用,就是用多层哈希表来实现数据分发存储和快速查找的能力。本篇文章打算总结下redis应用方面的知识点。
1. redis支持的五种(或则说六种)数据类型的读写常用方法:
redis是key-value结构的,其中它的key只支持String类型和byte[]类型,value支持5种类型String(bitset),Map,List,Set,SortSet,其实就是这五种类型也被限制在String类型和byte[]类型内,所以可以认为redis底层只支持String类型和byte[]类型,要保留类型对象的话就必须先把它序列化成byte[],下面从五种类型的增删改查以及确定是否已经才存在五个功能进行总结.
创建redis连接池:
privatestatic JedisPoolConfig poolConfig;
private static JedisPool pool;
static{
poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(10);
poolConfig.setMaxIdle(5);
poolConfig.setMaxWaitMillis(1000);
poolConfig.setTestOnBorrow(true);
pool = newJedisPool(poolConfig,"127.0.0.1",6379);
}
Jedis jedis = pool.getResource();
五种value类型的常用方法,其实真正常用的类型是String和map
/************************String************************/
System.out.println(jedis.set("zrf","20082100218"));//增加
System.out.println(jedis.set("zrf","hello world"));//修改
System.out.println(jedis.get("zrf"));//查找
System.out.println(jedis.del("zrf"));//删除
System.out.println(jedis.exists("zrf"));//判断是否存在
/************************bitset************************/
System.out.println(jedis.setbit("bill",100, "1"));//设置bit位
System.out.println(jedis.getbit("bill",1));//查询bit位
// System.out.println(jedis.bitcount("bill"));//统计时报错,原因待查
/************************list************************/
System.out.println(jedis.lpush("list","hello"));//入队列
// System.out.println(jedis.lpop("list"));//出队列
System.out.println(jedis.lset("list",1, "world"));//指定位置设置值
System.out.println(jedis.lindex("list",1));//读取指定位置的值
System.out.println(jedis.lrem("list",2,"world"));//删除
/************************hashmap************************/
System.out.println(jedis.hset("hashmap","1", "hello"));//增加
System.out.println(jedis.hget("hashmap","1"));//查找
System.out.println(jedis.hdel("hashmap","1"));//删除
System.out.println(jedis.hexists("hashmap","1"));//判断是否存在
Map<String,String>map = new HashMap<String,String>();
map.put("2","world");
System.out.println(jedis.hmset("hashmap",map));//对key设置一个map
System.out.println(jedis.hgetAll("hashmap"));//读取一个key对应的map值
/************************set************************/
System.out.println(jedis.sadd("set","hello"));//加入
System.out.println(jedis.spop("set"));//取出
System.out.println(jedis.srem("set","hello"));//删除
System.out.println(jedis.scard("set"));//统计元素个数
/************************sortset************************/
System.out.println(jedis.zadd("sortset",1,"world"));//加入
System.out.println(jedis.zadd("sortset",0.5,"hello"));
System.out.println(jedis.zrem("sortset","world"));//删除
System.out.println(jedis.zrange("sortset",0,1));//范围查找
2. 对表的操作:
/************************表操作************************/
System.out.println(jedis.select(0));//选择表
System.out.println(jedis.dbSize());//统计所选择表的key的数量
System.out.println(jedis.keys("hash*"));//查询所选择表的key列表,参数为匹配符
System.out.println(jedis.flushDB());//清空表的数据
3. 事务:
jedis.watch("hashmap");
Transaction multi = jedis.multi();
multi.hset("hashmap","1", "hello");
Thread.sleep(100000);
multi.hset("hashmap","2", "world");
multi.exec();
jedis.unwatch();
--所谓的redis事务机制,跟传统数据库的事务机制类似,但是不完全相同,如果在事务操作之前调用jedis.watch("hashmap");监控对应的key数据,如果在执行该事务的过程中,key对应的value数据被修改了,则整个事务都失败,这里的失败产生“回滚”的现象,就是所有事务中的命令都没生效包括在修改事件产生之前的语句,跟传统数据库的区别,这是一种假回滚,因为传统数据库是再回滚前是真执行了命令,产生的数据放在回滚段中,事务的中止使数据被阻止写入真的数据库中,而这里的回滚现象是因为多条语句被攒成一次执行,而这一次执行被阻止了。需要注意的是如果是某个命令本身的错误并不会回滚整个事务,为什么会这样呢?原因就是刚才说的“假回滚”,当程序指令正常执行了multi.exec();时已经没人能回滚整个事务了,因为redis并不提供所谓的回滚段。redis事务保证命令的原子性是通过把多条命令攒成一次批量命令不中断地执行。还有一点就是multi.exec();的返回值是各个命令组成的列表。
4. 管道:
Pipelinepipline = jedis.pipelined();
pipline.hset("hashmap","1", "hello2");
pipline.hset("hashmap","2", "world2");
System.out.println(pipline.syncAndReturnAll());
--管道相对就而言就简单多了,说白了就是批量执行多条命令的方式以提高效率,并且不保证原子性。
上面说的都是单节点的知识总结,在目前分布式大数据的趋势下,上面的知识点中事务机制比较值得注意研究,因为分布式多线程中如何解决并发冲突是非常关键和容易出错的。