1.存储数据(内部编码)
(1)Redis内部使用一个redisObject对象来表示所有的key和value
<1>redisObject主要的信息包括数据类型(type) ,编码方式(encoding) ,数据指针(ptr),虚拟内存(vm)
<2>type代表一个value对象具体是何种数据类型(5种之一),encoding是不同数据类型在redis内部式
(2)将不同数据结构的数据编码成二进制数据存储在内存中
2.操作数据(命令、协议)
(1)Redis-cli:客户端命令
<1>Redis提供了redis-cli 可以在命令行操作数据
<2>Redis是一种基于键值对的NoSQL数据库,它的5种数据结构都是健值对中的值
<3>对于键来说有一些通用命令
1.keys *:查看所有健
2.dbsize:健总数
3.exists key:检查健是否存在
4.del key [key ...]:删除键
5.expire key seconds:键过期
6.type key:键的数据结构类型
7.object encoding key:值的内部编码
(2)客户端通信协议RESP
<1>Redis 定制了RESP协议实现客户端与服务端的正常交互,这是一种基于TCP协议之上简单高效的协议
<2>jedis实现了RESP协议
(3)Redis客户端:jedis(相当于MySQL的jdbc)用来连接客户端与服务端的桥梁
<1>获取jedis
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<2>Jedis基本使用
// 创建连接
Jedis jedis = new Jedis("localhost", 6379);
// 存储数据,key="foo",value="bar"
jedis.set("foo", "bar");
// 获取数据
String value = jedis.get("foo");
//使用完后释放资源
jedis.close();
<3>Jedis的使用
1.Redis作为缓存数据库理论上和MySQL一样需要客户端和服务端建立起来连接进行相关操作
2.使用MySQL的时候都会使用一款开源的连接池,例如C3P0.
3.Jedis连接Redis缓存库,有两种方式:直连,使用缓存池(实际开发中使用缓存池)
<4>使用Jedis直连
1.直连会消耗大量的数据库资源,每新建一个连接,使用后断开连接,这显然不是高效的
2.客户端连接Redis使用的是TCP协议,直连的方式每次需要建立TCP连接
3.直连的方式无法限制Jedis对象的个数,在极端情况下可能会造成连接泄露
<5>使用Jedis缓存池
1.使用连接池的方式对Redis连接进行管理,使用完后不需要释放资源,交于缓存池即可
2.所有Jedis对象先放在池子中每一次需要的时候连接Redis,只需要在池子中借,用完了再归还给池子
3.借用和归还操作是在本地进行的,只有少量的并发同步开销,远远小于新建TCP连接的开销
4.连接池的形式可以有效的保护和控制资源的使用
<6>JedisPool缓存池基本使用:有两种方式
1.连接池配置实例化代码:获取配置文件属性值
第一步:/*读取jedis.properties配置文件*/
static{
ResourceBundle rb = ResourceBundle.getBundle("jedis");
maxtotal = Integer.parseInt(rb.getString("maxtotal"));
maxwaitmillis = Integer.parseInt(rb.getString("maxwaitmillis"));
host = rb.getString("host");
port = Integer.parseInt(rb.getString("port"));
}
第二步:/*创建连接池*/
static{
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxtotal);
jedisPoolConfig.setMaxWaitMillis(maxwaitmillis);
JedisPool jedisPool= new JedisPool(jedisPoolConfig,host,port);
}
第三步:/*获取jedis*/
public static Jedis getJedis(){
return jedisPool.getResource();
}
第四步: /*关闭Jedis*/
public static void close(Jedis jedis){
if(jedis!=null){
jedis.close();
}
第五步:/*调用JedisPool获取Jedis实例*/
//获取redis客户端连接
Jedis jedis = jedisPoolUtils.getJedis();
//从缓存池获取缓存实例对象
String userJson = jedis.get("user");
//2从redis中查数据,判断否为null
if (userJson == null || userJson .length() == 0) {
//redis中没有数据
System.out.println("redis无数据,执行查库操作");
//查询数据并且存入redis
List<User> user = userDao.findAll();
//将list序列化为json
ObjectMapper mapper = new ObjectMapper();
try {
userJson = mapper.writeValueAsString(user);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//将json数据存入redis
jedis.set("user", userJson );
//归还jedis连接
jedis.close();
} else {
System.out.println("redis中有数据,走缓存查询");
}
return userJson;
2.通过spring注入进行配置
第一步:/*二级缓存引入类:第三方缓存Redis,实现官方提供的默认Redis接口Cache*/
public class RedisCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id;
private static JedisConnectionFactory jedisConnectionFactory;
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;}
public String getId() {
return this.id;}
//存入缓存
public void putObject(Object key, Object value) {
JedisConnection conn = null;
try{
conn = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
conn.set(serializer.serialize(key), serializer.serialize(value));
}catch (Exception e) {
e.printStackTrace();
}finally{
if(conn != null){
conn.close(); } }}
//获取缓存
public Object getObject(Object key) {
JedisConnection conn = null;
Object res = null;
try{
conn = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
byte[] bs = conn.get(serializer.serialize(key));
res = serializer.deserialize(bs);
}catch (Exception e) {
e.printStackTrace();
}finally{
if(conn != null){
conn.close(); } } return res; }
//移除缓存
public Object removeObject(Object key) {
JedisConnection conn = null;
Object res = null;
try{
conn = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
conn.expire(serializer.serialize(key), 0);
}catch (Exception e) {
e.printStackTrace();
}finally{
if(conn != null){
conn.close();}}
return res; }
//清空缓存
public void clear() {
JedisConnection conn = null;
try{
conn = jedisConnectionFactory.getConnection();
conn.flushDb();
conn.flushAll();
}catch (Exception e) {
e.printStackTrace();
}finally{
if(conn != null){
conn.close();} } }
//获取缓存大小
public int getSize() {
JedisConnection conn = null;
int res = 0;
try{
conn = jedisConnectionFactory.getConnection();
res = Integer.parseInt(conn.dbSize().toString());
}catch (Exception e) {
e.printStackTrace();
}finally{
if(conn != null){
conn.close(); }}
return res; }
//缓存获取读写锁
public ReadWriteLock getReadWriteLock() {
return readWriteLock; }
public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.jedisConnectionFactory = jedisConnectionFactory;}
第二步:/*将第三方缓存实现类注入spring管理*/
public class RedisCacheTransfer {
@Autowired
public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.setJedisConnectionFactory(jedisConnectionFactory);}}
第三步:/*在spring.xml配置文件中引入实现spring-redis注入*/
<bean id="jedisConnectionFactory" class="com.tp.soft.redis.RedisCacheTransfer">
<property name="jedisConnectionFactory" ref="connectionFactory" />
</bean>
第四步:/*注入缓存接口实现类,调用对应方法即可*/
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private RedisTemplate<String, String> redisTemplate;
//连接redis缓存服务器
redisConnectionFactory.getConnection());
//向缓存服务器存储数据
redisTemplate.opsForValue().set("name", "fsx");
//获取缓存服务器中存储的数据
System.out.println(redisTemplate.opsForValue().get("name"));
3.Jedis与JedisPool总结
(1)Jedis线程不安全,JedisPool线程安全
(2)Redis Client拥有众多对接版本,目前使用Jedis为官方推荐Java对接客户端
(3)基于其对Redis良好的版本支持和API对接,另外编码中尽量避免使用废弃接口