什么是Redis
Key-Value型的数据库,和Mysql的二维表不一样,性能很好,数据存在内存中,支持通用数据结构,如队列,集合,哈希队列等
- 官网
- github安装地址
- 官网命令
- 书籍推荐:《Redis设计与实现》
基本命令
- set key value key为你想添加的键值,value为你想添加的键值对应的值,value可以为任何类型的数据结构
- get key找到key对应的value值
- select num选择一个数据库(默认为16个数据库,select 9表示选择第9个数据库)
- keys 正则表达式 找到满足正则表达式的所有键值
Redis config
- 打开安装文件夹中的redis.windows.conf,以下几行表示900秒中有一个key值发生变化,就会进行一次备份,300秒中有10个key值发生变化,就会进行一次备份,最后一行同理。因为Redis是内存型的数据库,所以需要一个机制来让改变的数据同步到文件中
save 900 1
save 300 10
save 60 10000
- 两种存储方式
RDB:某一时刻数据库当前状态,把最终结果保存起来,适合修改次数比较多的情况
AOF:不记最终结果,记录所有执行的命令(通过再执行一遍命令,来得到数据库当前状态),可以避免丢失数据
使用Jedis连接Redis
github地址
安装方法
1. 项目中添加依赖(在pom.xml中添加)
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2. 代码中使用方法
Jedis jd=new Jedis("redis://localhost:6379/6");
//连接第6个数据库(安装时默认端口为6379)
jd.flushDB(); //将该数据库中的数据清除,flushAll是将所有数据都清除
jd.set("hello","fsa"); //添加key value对
print(1,jd.get("hello")); //jd.get获取key值对应的value
3.List的使用
双向列表,适用于最新列表,关注列表
String name="list";
jd.del(name);
jd.lpushx(name,"ifexists");//如果name这个key存在才Push
print(0,jd.lrange(name,0,jd.llen(name)));//lrange得到下标从start到end的name中元素list
for(int i=0;i<10;i++)
{
jd.lpush(name,"a"+String.valueOf(i),"b"+String.valueOf(i));
//从左边压入,相当于栈,先进来的下标大
}
for(int i=11;i<20;i++)
jd.rpush(name,"a"+String.valueOf(i));
//从右边压入,相当于队列,先进来的下标小
print(1,jd.lrange(name,0,jd.llen(name)));//llen获取列表长度
print(2,jd.lindex(name,6));//获取下标为6的元素
jd.linsert(name, BinaryClient.LIST_POSITION.AFTER,"a8","hello");
jd.linsert(name, BinaryClient.LIST_POSITION.AFTER,"a8","hello");
//在“a8”元素后面插入两个hello,执行了两次
jd.linsert(name, BinaryClient.LIST_POSITION.BEFORE,"a8","you");
//在“a8”元素前面插入一个you
print(5,jd.lpop(name));//pop掉第一个元素,并返回第一个元素
jd.lrem(name,2,"hello");//删除两个hello
jd.lset(name,0,"me");//把下标为0的设为me
jd.ltrim(name,0,9);//裁剪,只留下下标0-9的元素
4.Hash的使用
String hset="hset";
jd.hset(hset,"name","ERIKA");//在hset中设置key-value对,name对应为ERIKA
jd.hset(hset,"age","21");
jd.hset(hset,"school","fdu");
print(1,jd.hgetAll(hset));//得到所有hset中的key-value对,结果类似dict
print(2,jd.hget(hset,"name"));//得到hset中name这个key对应的value
print(3,jd.hexists(hset,"family"));//判断hset中是否有family这个key,返回boolean
print(5,jd.hkeys(hset));//得到hset所有的keys的集合
print(6,jd.hlen(hset));//返回hset的长度
print(7,jd.hdel(hset,"school"));//删除hset的school这个key的键值对
jd.hsetnx(hset,"name","hello");//如果不存在就添加,存在则不再修改,可以防止篡改
jd.hsetnx(hset,"school","fduu");
5.Set的使用
String name="set";
String name2="set2";
for(int i=0;i<10;i++)
{
jd.sadd(name,String.valueOf(i));//在集合name中添加值
jd.sadd(name2,String.valueOf(i*i));
}
print(1,jd.scard(name));//返回name的长度
jd.srem(name,"4");//删除4这个元素
print(2,jd.smembers(name));//返回name中所有元素的集合
jd.smove(name2,name,"16");//把name2中的16移到name中,name2中删除,name中添加
print(5,jd.sismember(name,"9"));//判断9是否为name集合中的元素
print(7,jd.sunion(name,name2));//求并
print(8,jd.sinter(name,name2));//求交
print(9,jd.sdiff(name2,name));//求不同的元素
6.Sorted List的使用
String name="sortedlist";
jd.zadd(name,100,"Erika");//有序列表中添加名字和score的对应值
jd.zadd(name,80,"Lily");
jd.zadd(name,60,"Ben");
jd.zadd(name,40,"Jim");
print(1,jd.zcard(name));//返回list长度
print(2,jd.zcount(name,60,100));//计算score为60-100的人数
print(3,jd.zrange(name,0,2));//返回score从小到大第0-2名的名字
print(4,jd.zrangeByScore(name,60,100));//成绩从小到大60-100分的名字
print(5,jd.zrevrangeByScore(name,100,80));//成绩从大到小60-100分的名字
print(6,jd.zscore(name,"Erika"));//返回名叫Erika的成绩
jd.zincrby(name,5,"Lily");//给Lily的成绩加5分
print(7,jd.zrevrange(name,0,jd.zcard(name)));//输出所有成绩从大到小排序的人名
for(Tuple tuple:jd.zrevrangeByScoreWithScores(name,100,60))
{
print(8,tuple.getElement()+":"+String.valueOf(tuple.getScore()));
//输出 名字:成绩
}
print(9,jd.zrank(name,"Lily"));//得到Lily从小到大的排名
print(10,jd.zrevrank(name,"Lily"));//得到Lily从大到小的排名
String s="zset";
jd.zadd(s,1,"a");
jd.zadd(s,1,"g");
jd.zadd(s,1,"b");
jd.zadd(s,1,"d");
print(11,jd.zlexcount(s,"-","+"));//计算从负无穷到正无穷的个数
print(12,jd.zlexcount(s,"[b","[c"));//计算从b-c(左右都包)的个数,按照字典序,lex只有在score一样时有效
print(13,jd.zlexcount(s,"(b","[g"));//左不包右包
jd.zremrangeByLex(s,"(b","[g");//删除这个区间内的所有元素
7.链接池的使用
默认8个线程可以连接,从池中取出连接后如果不close掉线程8个之后的进不来,所以用好一定要关掉
JedisPool pool=new JedisPool();
for(int i=0;i<10;i++)
{
Jedis j=pool.getResource();
print(i,j.keys("*"));
print(i,j.get("pv"));
j.close();
}
使用这种方式,默认getresource是第0号数据库,使用下面的方法可以设定为第6号数据库
JedisPool pool=new JedisPool("redis://localhost:6379/6");
8.Json序列化实现对象的缓存和取出
User user=new User();
user.setPassword("1");
user.setHeadUrl("fd.png");
user.setSalt("fdsa");
user.setName("hello");
user.setId(10);
//转换成Json字符串
jd.set("user1",JSONObject.toJSONString(user));
//取出时使用parseObject来将json字符串回到class
User user2= JSON.parseObject(jd.get("user1"),User.class);
print(10,user2.getName());
集合实现赞踩功能
1.建立JedisService来实现数据库连接和具体操作的接口(其他功能又需要使用Redis数据库时,可以重复使用)
@Service
public class JedisService implements InitializingBean{
private static final Logger logger= LoggerFactory.getLogger(JedisService.class) ;
private JedisPool pool;
public long addkeyvalue(String key,String value)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.sadd(key,value);
}
catch (Exception e)
{
logger.error("redis添加失败"+e);
}
finally {
if(j!=null)
j.close();
}
return 0;
}
public long delvalue(String key,String value)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.srem(key,value);
}
catch (Exception e)
{
logger.error("删除失败"+e);
}
finally {
if(j!=null)
j.close();
}
return 0;
}
public boolean ismember(String key,String value)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.sismember(key,value);
}
catch (Exception e)
{
logger.error("获取是否为成员失败"+e);
}
finally {
if(j!=null)
j.close();
}
return false;
}
public long getcount(String key)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.scard(key);
}
catch(Exception e)
{
logger.error("获取总数失败"+e);
}
finally {
if(j!=null)
j.close();
}
return 0;
}
@Override
public void afterPropertiesSet() throws Exception {
pool=new JedisPool("redis://localhost:6379/6");
}
}
2. 建立LikeService来实现实际Like or DisLike的数据更新(多个页面位置需要实现赞踩功能时可以重复使用)
@Service
public class LikeService {
@Autowired
JedisService j;
public long addLike(int entity_type,int entity_id,int user_id)
{
String key= new RedisKeyUtil().getLikeKey(entity_type,entity_id);
return j.addkeyvalue(key,String.valueOf(user_id));
}
public long addDislike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getDislikeKey(entity_type,entity_id);
return j.addkeyvalue(key,String.valueOf(user_id));
}
public int isLikeorDislike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getLikeKey(entity_type,entity_id);
if(j.ismember(key,String.valueOf(user_id)))
return 1;
key=new RedisKeyUtil().getDislikeKey(entity_type,entity_id);
if(j.ismember(key,String.valueOf(user_id)))
return 2;
return 0;
}
public long getCountLike(int entity_type,int entity_id)
{
String key=new RedisKeyUtil().getLikeKey(entity_type,entity_id);
return j.getcount(key);
}
public long dellike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getLikeKey(entity_type,entity_id);
return j.delvalue(key,String.valueOf(user_id));
}
public long delDislike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getDislikeKey(entity_type,entity_id);
return j.delvalue(key,String.valueOf(user_id));
}
}
3. 建立RedisKeyUtil工具,来根据实际的功能和ID等参数,实现生成Keys的功能,以防止出现Key值重复而导致覆盖的问题
public class RedisKeyUtil {
private int entity_type;
private int entity_id;
public String getLikeKey(int entype,int id)
{
return "Like-"+String.valueOf(entype)+"-"+String.valueOf(id);
}
public String getDislikeKey(int entype,int id)
{
return "Dislike-"+String.valueOf(entype)+"-"+String.valueOf(id);
}
}
4.Controller中添加相关路径和方法
@Controller
public class LikeController {
@Autowired
HostHolder host;
@Autowired
LikeService like;
@RequestMapping(path={"/like"},method={RequestMethod.POST})
@ResponseBody
public String likeit(@RequestParam("commentId")int entity_id)
{
User user=host.getuser();
if(user==null)
return WendaUtil.generatejson(999);
if(like.isLikeorDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId())==2)
{
like.delDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
}
like.addLike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
return WendaUtil.generatejson(0,String.valueOf(like.getCountLike(EntityType.ENTITY_COMMENT,entity_id)));
}
@RequestMapping(path={"/dislike"},method={RequestMethod.POST})
@ResponseBody
public String dislikeit(@RequestParam("commentId")int entity_id)
{
User user=host.getuser();
if(user==null)
return WendaUtil.generatejson(999);
if(like.isLikeorDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId())==1)
{
like.dellike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
}
like.addDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
return WendaUtil.generatejson(0,String.valueOf(like.getCountLike(EntityType.ENTITY_COMMENT,entity_id)));
}
}