redis是什么?
redis,开源的基于内存存储的数据结构服务器。可以用来做数据库,高速缓存,以及消息队列代理。
支持数据持久化(内存数据本地化),支持主从备份(高可用,分布式)
存储格式:key-value式存储
可以存储的数据类型:
这里不做详细介绍,官网上有详细的文档,需要的时候查询就可以了 Redis中文网站
简单key-value(string)
set key val
get key
hash
hset key field val
hget key field
hdel key field [field] 删除一个或多个hash表字段
hgetall key 获取哈希表中指定key的所有字段和值
hvals key 获取哈希表中所有的值
list(下标从0开始,负数代表重末尾往前,-1 代表最后一个值的下标)
lpush key val1 [val2] 将一个或者多个值插入列表头部
rpush key val1 [val2] 将一个或者多个值插入列表(从尾部插入)
lindex key index 根据下标查询
llen key 获得列表大小
lrange key start stop 查询指定范围内的元素(如果stop指定为-1或者超过列表最大值,则返回列表所有value,这和python的列表查询方式一致,负数代表从末尾往前数)
set
sadd key member1 [member2] 向集合添加一个或多个成员
scard key 获取集合成员数
sdiff key1 [key2] 获得给定集合的差集
sinter key1[key2] 获得给定集合的交集
smembers key 列出集合所有的成员
zset(有序集合 sorted set ,因为其操作命令都以z开头故有zset之称)
zadd key1 score1 member1 [score2 member2] 向集合中添加一个或者多个成员,或更新已存在成员的score(所谓的有序集合就是可以指定不同的score,按从大到小往下排,该值为整型,可以相同。相同情况下按添加顺序作为顺序)
zrange key start stop [withscores] 通过索引区间返回有序集合指定区间内的成员,加上withscores会连成员对应的score一并查询出来
zrank key member 返回有序集合中指定成员的索引
为什么用redis?
快啊,快到不能呼吸。基于内存的数据库,读取速度110000次/s 写入速度81000次/s 相比mysql几千的吞吐量来说,简直坐了火箭了。
理论上来说硬盘的容量高于内存的容量。数据量过于庞大的话,内存的容量有可能达不到,所以redis常用来做高速缓存,用来提高系统的读取性能,提高系统响应速度。而一些不经常查询的数据就放在关系型数据库中。
怎么用redis?
redis那么好,我们怎么用呢(基于集群)?
1、下载redis,这里提供redis的 windows版本的下载链接。redis官方现不提供windows版本的下载。
2、如果你需要搭建集群的话,需要Ruby的支持,去运行redis提供的Ruby脚本来搭建集群。如果你只使用单机,可以略过此步。这里提供Ruby的windows版本安装地址。
3、新建一个目录【redis-cluster】,基于redis有投票机制来判定一个master节点是否挂掉(若有半数的master投票通过,就认为这个master挂掉了。)
知识点:redis集群(redis cluster),分主从(master-slave)数据库,一个主节点(master)可以对应多个从节点(slave)。当有一台master节点挂掉后,通过投票机制来判定这个节点是否真的挂掉了,如果超过半数的master投票通过,则该节点被认为挂掉。问题节点可以灵活地进行主从切换。
4、我们拷贝6个redis放到【redis-cluster】下面,修改其中地配置文件。windows版的配置文件为redis.windows.conf(linux版地为reids.conf)。
①删除redis目录下地nodes.conf,appendonly.aof,dump.rdb(如果有这三个文件地话),让redis后面自动生成。如果不删除,留有旧信息地话会报以下错误。
[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0
②找到prot属性,默认为6379。我们把6个redis地端口改为6379-6384
③cluster-enabled yes 放开,如果为no改为yes 开启集群支持
④cluster-node-timeout 默认时间为15000毫秒,默认是关闭地,该属性用来判断节点响应超时地时间,如果响应超时则发起投票,判断该节点是否挂掉。
⑤appendonly yes 该属性更改为yes并放开
知识点: nodes.conf 节点配置文件,默认为nodes.conf可以通过修改cluster-config-file name.conf 来配置
redis数据本地化有两种方式:rdb(redis database),aof(append only filed)。rdb属于redis快照方式,每隔一段时间就将内存中地数据保存到本地,性能高,但是数据的安全性得不到保障。 aof 是性能和安全的一个折中办法,默认每隔一秒将redis操作中的写操作,保存到本地。rdb保存的是数据,aof保存的是操作。
5、拷贝一个redis-trib.rb到redis-cluster目录下,这是一个ruby配置redis的脚本文件。除此之外,我们还需要一个redis和ruby的接口工具包 redis-3.0.0.gem
6、将所需的redis全部启动 在每一个reids目录下cmd执行redis-server redis.windows.conf
7、启动ruby命令窗口,切换到redis-cluster目录 运行以下命令,把我们需要的地址都给写上。
redis-trib.rb create --replicas 1 host1:port1 [host2:port2]
出现 Can I set the above configuration? (type'yes' to accept): 填写yes
出现[OK] All nodes agree about slotsconfiguration.代表配置成功
检查集群:可以使用redis-trib.rb check host:port(集群中任意一个节点的地址都可以)
也可以使用redis-cli -h host -p port -c(-c表示以集群方式链接redis,如果不加就是单机的。host,port为集群中任一ip)链接上后 使用 cluster info 命令查看集群信息。
至此。集群就搭建完成了。
其他:
可以使用redis-trib.rb add-node new_host:port(新节点) existing_host:existing_port(集群中在运行的节点) 添加一个新节点
使用redis-trib.rb add-node --slave --master-id nodeid(master-node的id) new_host:port(新节点) existing_host:existing_port(集群中在运行的节点) 为指定master节点添加一个从节点。
关于槽的概念:总共有16384个槽(0-16383),槽上存数据,槽只存在master节点上。如果添加了新节点,重新分配槽,槽上的数据会随着槽移动走。
单机形式的redis, 配置了port 配置了aof后直接输入命令 redis-server redis.windows.conf 直接就执行了。
java中使用redis----jedis
1、导入jar包,我们使用jedis的包。maven的在pom中加入jedis的依赖。并在spring配置文件中添加相关配置。
<!-- redis 单机版 -->
<bean id="jedis" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6379"/>
</bean>
<!-- redis 集群 -->
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6380"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6381"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6382"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6383"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="127.0.0.1"/>
<constructor-arg name="port" value="6384"></constructor-arg>
</bean>
</set>
</constructor-arg>
</bean>
配置完后,写一个redisHandel接口
public interface RedisHandel {
String get(String key);
String set(String key, String value);
Long del(String key);
Long hSet(String hKey, String key, String value);
String hGet(String hKey, String key);
Long hDel(String hKey, String key);
Long incr(String key);
Long expire(String key, int seconds);
Long persist(String key);
}
写两个类分别实现redisHandel接口,一个单机版,一个集群版(篇幅问题,不大量拷贝代码)
注:jedisCluster用完之后不要close,一旦close那么集群就关闭了。
@Component(value="redisHandelCluster")
public class RedisHandelCluster implements RedisHandel {
@Autowired
private JedisCluster jedisCluster;
public String get(String key) {
String result = jedisCluster.get(key);
return result;
}
}
@Component(value="resisHandelSingle")
public class ResisHandelSingle implements RedisHandel {
@Autowired
private JedisPool jedisPool;
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
}
写测试类,注入任一想测试的。我测试的是集群。便注入集群工具类 redisHandelCluster。
调用里面的set方法向集群中添加一条数据,然后在集群中查看该数据有没有添加进去。
最后:
在使用redis的时候,在service层。
一、先去redis中查询,如果没有再去数据库。从数据库中查询出来后向redis中放一份。
二、可以再服务启动后,先放一部分数据到redis中,查询的时候做第一步的操作。
今天跟朋友讨论了以下大量数据的情况下如何将高频检索项放入redis中。
我的想法是,可以先查,然后放到redis中,并给其添加过期时间。当下一次再命中该条记录的时候,将其过期时间延长。以此类推,非高频检索项会随着时间的推移被redis清除。留下来的当然几乎全是高频命中的记录。
当然也可以项目启动后放一部分认为是将来可能高频命中的记录,并添加过期时间。再按过期排除。
关于保留热点数据其实redis给我们了一些更方便的操作:
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据