redis

本文详细介绍了 Redis 的下载、运行及常用命令,包括字符串、列表、哈希、集合、有序集合、位图、HyperLogLog 等数据类型的操作。同时,展示了如何在 Java 中使用 Jedis 和 Spring Data Redis 操作 Redis,以及事务和流水线的使用。此外,还提及了 Redis 的主从复制和过期时间设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis下载

官网没有window版的,这里可以window版本下载
https://github.com/tporadowski/redis/releases
官网下载
https://download.redis.io/releases/

运行redis

  1. 进入redis命令目录
  2. redis-server.exe运行服务,redis-cli.exe运行客户端

命令的使用

遇到不会的,就在客户端打help

redis键

  • Redis键是二进制的
  • 很长的键不是一个好主意。
  • 非常短的键通常不是一个好主意, 尝试坚持使用架构。例如,"object-type:id"是一个好主意,就像"user:1000"一样。
  • 允许的最大密钥大小为 512 MB。

数据类型

  • string
  • list(有序的,用链表实现的,增删好,查询一般)
  • hashes(哈希,键值对结构)
  • set(无序的,唯一)
  • sorted sets(无序的,唯一,这里的有序指根据分数进行排序; 排序集是通过包含跳过列表和哈希表的双端口数据结构实现;因此每次添加元素时,Redis都会执行O(log(N))操作;排序集适用于有大量更新的情况)
  • bitmaps
  • hyperLogLogs(HyperLogLog是一种概率数据结构,用于计算唯一事物(从技术上讲,这指的是估计集合的基数),我现在的理解是用更少的内存干与set相同的事,但并不存储元素,只是统计不同元素的个数)

操作数据的常用命令

字符串

  • 设置值
    set key value
  • 获取值
    get key
  • 当值存在时,设置失败
    set key newval nx
  • 仅当值存在时。设置成功
    set key newval xx
  • incr增加1
    incr num
  • incrby增加指定数值
    incrby num val
  • 得到旧值并设置新值
    getset num newval
  • 一次设置多个值(m-> multi)
    mset key1 val1 key2 val2 key3 val3
  • 一次得到多个值,以数组形式
    mget key1 key2 key3
  • 判断值存在
    exists key
  • 删除值
    del key
  • 获取值的类型
    type key
  • 过期时间,到期自动删除,单位秒
    expire key seconds
    set key val ex seconds
  • 查看剩余时间,单位秒
    ttl key
  • 过期时间,到期自动删除,单位毫秒
    pexpire key millisecond
    set key val px millisecond
  • 查看剩余时间,单位毫秒
    pttl key

列表

  • 往链表头添加数据(lpush -> left push)
    lpush key val1 val2 val3
  • 往链表尾添加数据(rpush -> right push)
    rpush key val1 val2 val3
  • 获取链表的数据(lrange -> list range),获取所有数据: lrange 0 -1,从最后一个元素逆序遍历,最后一个元素为-1,倒数第二个元素为-2,依此类推
    lrange start end
  • 在左边弹出元素
    lpop key
  • 在右边弹出元素
    rpop key
  • 保留指定范围的元素
    ltrim key satrt end
  • 阻塞弹出元素(blpop -> block left pop)(链表无元素时阻塞请求, 达到指定时间返回,返回的数据形式为[key, val],因为此命令从多个链表拿元素,哪个链表先返回元素就返回哪个链表元素的key和val)
    blpop key1 key2 seconds
    brpop key1 kye2 seconds
  • 获取链表的长度
    llen key

哈希(hashes)

ps:操作方式挺像hbase

  • 设置单个键对值(hset -> hashes set)
    hset key filed value
  • 获取
    hget key field
  • 设置多个键对值(hashes multi set )
    hmset key fileld1 val1 fileld2 val2
  • 获取
    hmget key field1 fileld2
  • 增加值(hincrby -> hashes increase by)
    hincrby key fileld increment

集合(set)

  • 添加
    sadd key val1 val2 val3
  • 获取所有
    smembers key
  • 检查某个元素是否在集合里(sismember ->set exists member)
    sismember key member
  • 随机弹出指定个数的随机元素
    spop key count
  • 求交集
    sinter key1 key2 key3
  • 求并集
    sunion key1 key2 key3
    ps: 要把结果存到另一个集合中,只需在命令后加store,例如sinterstore resultset key1 key2 key3
  • 获取元素个数
    scard key
  • 获取指定个数的随机元素且不删除
    srandmember key count

有序集合(sorted set)

  • 添加(按照score排序)
    zadd key score val
  • 获取
    zrange key start end
  • 逆序获取
    zrevrange key start end
  • 获取结果带score
    zrange key start end withscores
  • 获取指定分数范围的数据
    zrangebyscore key minscore maxscore
  • 删除指定分数范围的数据
    zremrangebyscore key startscore endscore
  • 询问元素在集合中的位置
    zrank key val

位图(Bitmaps)

  • 添加(offset理解为而二进制的第几位数,val就是二进制中的0或1)
    setbit key offset val
  • 获取
    getbit key offset
  • 位操作
    bitop [and|or|xor|not] resultkey key1 key2 key3
  • 获取1的个数
    bitcount key
  • 获取第一个指定值(0或1)的下标
    bitpos key bit start end

HyperLogLog

  • 添加
    pfadd key val1 val2 val3
  • 统计不同元素的个数
    pfcount key
  • 将hll合并
    pfmerge resultkey key1 key2 key3

java操作redis

  1. 导包
    jedis-2.9.0.jar
  2. 代码
import redis.clients.jedis.Jedis;
public class RedisTest {

	public static void main(String[] args) {

		Jedis jedis = new Jedis("localhost", 6379);

		jedis.set("hello", "world");

		System.out.println(jedis.get("hello"));

	}

}

spring使用redis

1.导包
jedis-2.9.0.jar
spring-data-redis-1.6.4.RELEASE.jar
2. 配置文件application-context.xml

<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

	<!-- 配置连接参数JedisPoolConfig -->
	<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大空闲数 -->
		<property name="maxIdle" value="50" />
		<!-- 最大连接数 -->
		<property name="maxTotal" value="100" />
		<!-- 最大等待时间 -->
		<property name="maxWaitMillis" value="20000" />
	</bean>
	
	<!-- Spring配置连接工厂JedisConnectionFactory -->
	<bean id="connectionFactory" 
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
		<property name="hostName" value="localhost" />
		<property name="port" value="6379" />
		<property name="poolConfig" ref="poolConfig" />
	</bean>
	
	<!-- key序列化器 -->
	<bean id="stringRedisSerializer" 
			class="org.springframework.data.redis.serializer.StringRedisSerializer" />
	
	<!-- value序列化器 -->
	<bean id="jdkSerializationRedisSerializer" 
			class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />

	<!-- Redis连接池 -->
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="keySerializer" ref="stringRedisSerializer" />
		<!--	当value类型为object时使用此序列化器	-->
		 <property name="valueSerializer" ref="jdkSerializationRedisSerializer" />
		<!--	当value类型为string时使用此序列化器	-->
		<!--		<property name="valueSerializer" ref="stringRedisSerializer" />-->
		<!--  默认	-->
		<property name="defaultSerializer" ref="stringRedisSerializer" />
	</bean>
</beans>
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;

public class TestString {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext app =
				new ClassPathXmlApplicationContext("/db/redis/applicationContext.xml");

		RedisTemplate<String, String> redisTemplate = app.getBean(RedisTemplate.class);

		redisTemplate.opsForValue().set("key1", "value1");
		redisTemplate.opsForValue().set("key2", "value2");
		//获取
		String getKey1 = redisTemplate.opsForValue().get("key1");
		System.out.println(getKey1);
		//字符串长度
		Long size = redisTemplate.opsForValue().size("key1");
		System.out.println("字符串长度:" + size);

		//设置新值并返回旧值
		String oldValue = redisTemplate.opsForValue().getAndSet("key1", "new_value1");
		System.out.println("旧值:" + oldValue);
		getKey1 = redisTemplate.opsForValue().get("key1");
		System.out.println("新值:" + oldValue);

		//子串
		getKey1 = redisTemplate.opsForValue().get("key1", 0, 5);
		System.out.println(getKey1);

		//字符串拼接
		redisTemplate.opsForValue().append("key1", "_app");
		getKey1 = redisTemplate.opsForValue().get("key1");
		System.out.println(getKey1);

		app.close();
	}
}

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;

public class TestSpring {
	
	public static void main(String[] args) {
		ClassPathXmlApplicationContext app = 
				new ClassPathXmlApplicationContext("/db/redis/applicationContext.xml");
		RedisTemplate redisTemplate = app.getBean(RedisTemplate.class);

		//设置
		Role role = new Role();
		role.setRoleName("hello");
		redisTemplate.opsForValue().set("r1", role);

		//获取
		Role getRole = (Role)redisTemplate.opsForValue().get("r1");
		System.out.println(getRole);

		//SessionCallback可以保证方法内所有redis语句都由同一个redis连接执行
		SessionCallback<Role> sc = new SessionCallback<Role>() {
			@Override
			public Role execute(RedisOperations rop) throws DataAccessException {
				rop.opsForValue().set("r2", role);
				return (Role) rop.opsForValue().get("r2");
			}
		};
		Role r2 = (Role) redisTemplate.execute(sc);
		System.out.println(r2);
	}

}

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;

public class TestHash {
	public static void main(String[] args) {

		ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("/db/redis/applicationContext.xml");

		RedisTemplate<String, String> redisTemplate = app.getBean(RedisTemplate.class);

		String KEY = "hash";
		HashMap<String,String> map = new HashMap<String, String>();
		map.put("sj", "88");
		map.put("wj", "7floor");
		//设置值
		redisTemplate.opsForHash().putAll(KEY, map);
		//设置单个值
		redisTemplate.opsForHash().put(KEY, "student", "yxd");

		//遍历所有键和值
		Map<Object, Object> entries = redisTemplate.opsForHash().entries(KEY);
		for (Map.Entry<Object, Object> entry : entries.entrySet()) {
			System.out.println(entry.getKey());
			System.out.println(entry.getValue());
		}

		//增加值
		redisTemplate.opsForHash().increment(KEY, "sj", 2.2);
		String sj = (String)redisTemplate.opsForHash().get(KEY, "sj");
		System.out.println(sj);

		//删除值
		redisTemplate.opsForHash().delete(KEY, "student");
		
		//遍历所有值
		List<Object> values = redisTemplate.opsForHash().values(KEY);
		for (Object v : values){
			System.out.println(v);
		}

	}

}

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;

public class TestHyperLogLog {
	public static void main(String[] args) {

		ClassPathXmlApplicationContext app =
				new ClassPathXmlApplicationContext("/db/redis/applicationContext.xml");

		RedisTemplate<String, String> redisTemplate = app.getBean(RedisTemplate.class);
		//设置
		redisTemplate.opsForHyperLogLog().add("log", "a", "b", "c", "d", "a");
		redisTemplate.opsForHyperLogLog().add("log2", "a");
		redisTemplate.opsForHyperLogLog().add("log2", "z");
		//获取不同元素的个数
		Long log = redisTemplate.opsForHyperLogLog().size("log");
		Long log2 = redisTemplate.opsForHyperLogLog().size("log2");
		System.out.println(log);
		System.out.println(log2);
		//合并
		redisTemplate.opsForHyperLogLog().union("new_log", "log", "log2");
		Long new_log = redisTemplate.opsForHyperLogLog().size("new_log");
		System.out.println(new_log);
	}

}

redis事务

watch与事务

watch:
在事务之前(multi)使用,
用法: watch key
结果: 如果观察的key的value在事务里被改变了,那么事务就会回滚

java操作事务

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;

public class Tx {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        RedisTemplate template = app.getBean(RedisTemplate.class);
        SessionCallback callback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations ro) throws DataAccessException {
                //开启事务,创建命令队列
                ro.multi();
                //加入命令队列
                ro.boundValueOps("k1").set("v1");
                String k1 = (String) ro.boundValueOps("k1").get();
                //执行命令队列的命令,有返回值
                ro.exec();
                // 这里只能以这种方式拿, 返回k1得到为null,为甚么
                // 因为exec之前都没执行命令
                return ro.boundValueOps("k1").get();
            }
        };
        String v1 = (String) template.execute(callback);
        System.out.println(v1);
    }
}

流水线

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

public class RedisLine {
    public static void main(String[] args) {
        Jedis jedis = new Jedis();
        //开启流水线
        Pipeline line = jedis.pipelined();
        for (int i = 0; i < 100000; i++) {
            line.set("k" + i, "v" + i);
            line.get("k" + i);
        }
        //流水线执行
        line.syncAndReturnAll();
    }
}

超时

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;

import java.util.concurrent.TimeUnit;

public class Ex {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        RedisTemplate template = app.getBean(RedisTemplate.class);

        SessionCallback callback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations ro) throws DataAccessException {
                ro.boundValueOps("rg1").set("value rg1");
                // 10秒的存活时间
                Boolean succeedSetExpire = ro.expire("rg1", 10, TimeUnit.SECONDS);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //获取剩余时间
                Long expireTime = ro.getExpire("rg1");
                System.out.println(expireTime);
                //持久化,把过期时间去掉
                Boolean isSucceedPersist = ro.persist("rg1");
                //获取剩余时间, -1代表永久
                expireTime = ro.getExpire("rg1");
                System.out.println(expireTime);
                return null;
            }
        };

        template.execute(callback);
    }
}

redis主从复制

从机只能读数据, 主机能读能写
  1. 重命名,复制两份配置文件改名, slave01.conf, slave02.conf
  2. 修改配置文件内容的port和slaveof
    例如
    port 6380
    slaveof localhost 6379
  3. 根据配置文件启动redis服务
    ./redis-server 配置文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值