2024-09-03

Redis支持的数据类型包括:

  1. 字符串(String)
  2. 列表(List)
  3. 集合(Set)
  4. 有序集合(Sorted Set,或称为ZSet)
  5. 哈希(Hash)
  6. 位图(Bitmap)
  7. 超日志(HyperLogLog)

底层数据结构:

  1. 字符串:简单动态字符串(Simple Dynamic String,SDS)
  2. 列表:双向链表
  3. 集合:哈希表
  4. 有序集合:跳跃列表(ZSet是跳表+哈希表)
  5. 哈希:哈希表
  6. 位图:位数组
  7. 超日志:基数估计算法

Redis为何对这些数据类型使用高效的底层数据结构:

  • 字符串:SDS可以避免字符串长度改变时频繁的内存重分配。
  • 列表:双向链表使得插入和删除操作都是O(1)复杂度。
  • 集合、有序集合、哈希:使用哈希表存储数据,允许快速访问。
  • 跳表:有序集合可以快速的插入、删除和查找操作。
  • 位图:位操作能够对位串进行快速的操作。
  • 超日志:基数估计算法适合用于大量的数据去重统计。

这些数据结构的选择使得Redis能够提供高性能的键值存储服务。

2024-09-03

在Spring Boot中,要使用Spring Cache集成Redis,你需要做以下几步:

  1. 添加依赖到你的pom.xmlbuild.gradle文件中。

使用Maven的pom.xml示例:




<dependencies>
    <!-- Spring Boot Cache 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <!-- Spring Data Redis 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>
  1. application.propertiesapplication.yml中配置Redis连接。

application.properties示例:




spring.redis.host=localhost
spring.redis.port=6379
  1. 在Spring Boot应用中启用缓存。

在你的@SpringBootApplication类或配置类中添加@EnableCaching注解。




import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@EnableCaching
public class CacheConfig {
}
  1. 使用Spring Cache注解。

在你的服务类或控制器类中使用@Cacheable, @CachePut, @CacheEvict等注解。




import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
 
@Service
public class SomeService {
 
    @Cacheable(value = "sampleCache", key = "#id")
    public SomeObject getObjectById(Long id) {
        // 查询数据库逻辑
    }
}

Spring Cache的实现底层通常使用了Spring框架的AOP特性,结合Redis作为缓存,底层通常会用到RedisTemplateStringRedisTemplate来操作Redis。

在MyBatis层面,MyBatis官方并没有提供直接的缓存集成Redis的功能。不过,你可以使用第三方插件,如MyBatis-Redis。这个插件可以让你将查询结果存储到Redis中,并在后续的相同查询中直接从Redis缓存中获取结果,减少对数据库的访问。

使用MyBatis-Redis时,你需要做以下几步:

  1. 添加MyBatis-Redis依赖到你的pom.xml
  2. 配置MyBatis-Redis插件,指定缓存类型为Redis。
  3. 在MyBatis的mapper文件中使用<cache>元素或在Mapper接口上使用@CacheNamespace注解。

以上是整合Spring Cache和Redis的基本步骤,具体实现细节和版本差异可能会有所不同,请根据你使用的Spring Boot和MyBatis版本进行相应的调整。

2024-09-03

Redis 实现分级缓存通常是指使用不同的数据结构或是设置不同的过期时间来管理缓存数据,以优化内存使用和提高缓存命中率。以下是一个简单的例子,展示如何使用Redis的有序集合(sorted set)来实现分级缓存:




import redis
import time
 
# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 添加数据到分级缓存中
def add_to_tiered_cache(key, value, ttl):
    score = time.time() + ttl  # 使用过期时间作为score
    r.zadd('tiered_cache', {key: score}, xx=True)  # 更新或添加,xx表示只有当键存在时才更新
    r.set(key, value)  # 存储数据
 
# 从分级缓存中获取数据
def get_from_tiered_cache(key):
    score = r.zscore('tiered_cache', key)  # 获取key的score
    if score is not None and score > time.time():
        return r.get(key)  # 如果key存在且未过期,则获取数据
    else:
        return None  # 否则返回None
 
# 示例使用
add_to_tiered_cache('user:1', 'John Doe', 3600)  # 添加一个有效期为1小时的缓存项
value = get_from_tiered_cache('user:1')  # 尝试从缓存中获取数据
print(value)  # 输出缓存的值,如果已经过期将输出None

在这个例子中,我们使用有序集合(tiered_cache)来管理缓存数据的过期时间,并使用普通的键值对来存储实际数据。每次获取数据时,我们首先检查有序集合中的score(即过期时间),如果未过期,则从普通键中获取数据。

这只是一个简单的分级缓存实现,实际应用中可能需要考虑更多因素,如内存管理、数据淘汰策略等。

2024-09-03

在Redis中实现分布式锁的一种常见方法是使用SET命令的NX(唯一性)和PX(过期时间)选项。以下是一个使用Python和redis-py库的示例代码,它展示了如何使用SET命令来获取分布式锁:




import redis
import time
import uuid
 
def acquire_lock(conn, lock_name, acquire_timeout=10, lock_timeout=10):
    identifier = str(uuid.uuid4())  # 生成一个唯一的ID
    end = time.time() + acquire_timeout
 
    while time.time() < end:
        if conn.set(lock_name, identifier, ex=lock_timeout, nx=True):
            return identifier  # 锁被成功获取,返回唯一标识
        time.sleep(0.001)
 
    return False  # 在规定时间内未能获得锁
 
def release_lock(conn, lock_name, identifier):
    pipe = conn.pipeline(True)
    while True:
        try:
            pipe.watch(lock_name)
            if pipe.get(lock_name) == identifier:
                pipe.multi()
                pipe.delete(lock_name)
                pipe.execute()
                return True
            pipe.unwatch()
            break
        except redis.exceptions.WatchError:
            pass
    return False  # 释放锁失败,可能由于标识符不匹配
 
# 使用示例
redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0)
lock_name = "my_lock"
lock_identifier = acquire_lock(redis_conn, lock_name)
if lock_identifier:
    try:
        # 在这里执行需要互斥访问的代码
        print("Lock acquired")
    finally:
        if not release_lock(redis_conn, lock_name, lock_identifier):
            print("Failed to release lock")
else:
    print("Failed to acquire lock")

这段代码展示了如何使用Redis分布式锁来同步对共享资源的访问。acquire_lock函数尝试获取锁,如果在指定时间内成功,它会返回一个唯一标识符;release_lock函数尝试释放锁,如果标识符匹配,则释放锁。这里使用了Redis的原子性操作来保证在分布式环境中锁的正确行为。

2024-09-03

Redis主从复制:




# 在从服务器上执行
redis-cli --slaveof <主服务器IP> <主服务器端口>

Redis哨兵(Sentinel):




# 启动哨兵
redis-sentinel /path/to/your/sentinel.conf

Redis分片(Sharding):

分片通常通过一致性哈希实现,可以手动编码实现或使用如Redis Cluster自动分片。

Redis Cluster:




# 首先配置每个节点的cluster.conf文件
redis-cli --cluster create <节点IP>:<端口> ... --cluster-replicas 1

Redis脑裂(Split-Brain):

脑裂通常是指网络分裂导致的两个或多个节点分别选举出主节点的情况。Redis哨兵通过投票机制避免脑裂:如果哨兵注意到主服务器不可用,它们会进行投票选举新的主服务器。

以上是基本概念和命令的描述,具体实现和配置可能根据不同版本的Redis而有所不同。

2024-09-03



# 设置Redis的日志文件路径
logfile "/var/log/redis/redis-server.log"
 
# 设置Redis的数据库数量,默认16个数据库,可以通过"SELECT <dbid>"命令选择数据库
databases 20
 
# 设置Redis的最大内存容量,达到最大内存后,会使用LRU算法进行数据淘汰
maxmemory 2gb
 
# 设置内存淘汰策略,包括:
#   volatile-lru -> 根据LRU算法淘汰设置了过期时间的键
#   allkeys-lru -> 根据LRU算法淘汰任何键
#   volatile-random -> 随机淘汰设置了过期时间的键
#   allkeys-random -> 随机淘汰任何键
#   volatile-ttl -> 根据TTL值淘汰设置了过期时间的键
#   noeviction -> 不进行淘汰,当内存不足时如果还要执行写入操作,会报错
maxmemory-policy allkeys-lru
 
# 设置是否开启了Append Only Mode,开启后每次写入都会记录日志
appendonly yes
 
# 设置Append Only Mode的日志文件名
appendfilename "appendonly.aof"
 
# 设置Append Only Mode的日志同步频率
#   always -> 每次写入都进行同步
#   everysec -> 每秒同步一次
#   no -> 由操作系统决定何时同步
appendfsync everysec
 
# 设置是否开启了虚拟内存机制,需要配合vm-*系列参数使用
vm-enabled no
 
# 设置Redis的虚拟内存文件路径
vm-swap-file /tmp/redis.swap
 
# 设置虚拟内存的最大值
vm-max-memory 0
 
# 设置虚拟内存的页大小
vm-page-size 32mb
 
# 设置虚拟内存的页数量
vm-pages 134217728
 
# 设置虚拟内存的缓冲区大小
vm-max-threads 4

这个配置文件展示了如何设置Redis的日志文件路径、数据库数量、最大内存容量、内存淘汰策略、Append Only Mode的开启与设置、虚拟内存的配置。这些配置项对于Redis的性能和可靠性至关重要,并且展示了如何通过修改配置文件来满足不同的需求。

2024-09-03

Redis是一个开源的使用C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

Redis支持的数据类型包括:字符串、列表、集合、有序集合、哈希表。

  1. 字符串(String)

字符串是Redis最基本的数据类型。

常用命令:SET、GET、INCR、DECR、MGET等。

应用场景:缓存、计数器、分布式锁等。

  1. 列表(List)

列表是简单的字符串列表,按照插入顺序排序。

常用命令:LPUSH、RPUSH、LRANGE等。

应用场景:消息队列、文章列表等。

  1. 集合(Set)

集合是无序的字符串集合。

常用命令:SADD、SMEMBERS、SINTER等。

应用场景:去重、共同好友等。

  1. 有序集合(Sorted Set)

有序集合是字符串的集合,且每个元素都关联一个分数。

常用命令:ZADD、ZRANGE、ZREVRANGE等。

应用场景:排行榜、延时任务等。

  1. 哈希表(Hash)

哈希表是字符串字段和字符串值之间的映射。

常用命令:HSET、HGETALL、HKEYS等。

应用场景:用户信息、配置信息等。

以上就是Redis支持的数据类型以及它们的常用命令和应用场景。

2024-09-03

解释:

这个错误表明你尝试对一个key执行了不匹配其数据类型的操作。Redis中的键可以包含五种不同的数据类型:字符串(string)、列表(list)、集合(set)、有序集合(sorted set)和哈希表(hash)。例如,如果一个key是一个字符串类型,而你尝试对它执行列表操作(如 LPUSH 或 LPOP),就会出现这个错误。

解决方法:

  1. 确认key的正确数据类型:使用 TYPE key 命令来查看key的数据类型。
  2. 根据数据类型执行正确的操作:确保你对每个key使用了与其数据类型相匹配的Redis命令。
  3. 如果需要,转换数据类型:如果你需要改变key的数据类型,可以使用相应的转换命令,如 SET 来转换哈希表为字符串,或者用 HKEYS 来转换字符串为哈希表。
  4. 如果key不存在,请确保在执行操作之前它已经被正确地创建并赋予了合适的数据类型。

例如,如果你收到这个错误,并且你的key原本应该是一个列表,你应该使用列表相关的命令,如 LRANGE, LLEN, LPUSH, LPOP 等。如果你误用了字符串命令,如 SET, GET, INCR 等,就需要更改为正确的命令。

2024-09-03



-- 假设有一个Redis客户端库,我们使用它来设置带有过期时间的键
local redis = require "resty/redis"
local red = redis:new()
red:set_timeout(1000) -- 1秒超时
 
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
    ngx.say("连接Redis失败: ", err)
    return
end
 
-- 假设有一个查询数据库的函数
local function fetch_data_from_db()
    -- 这里应该是查询数据库的代码
    return "数据库中的数据"
end
 
-- 这是一个缓存数据并设置逻辑过期的函数
local function get_data_with_ttl(key, ttl)
    -- 尝试从Redis获取数据
    local data = red:get(key)
    if data then
        -- 如果数据存在,直接返回
        return data
    else
        -- 如果数据不存在,从数据库中获取,并设置到Redis中
        data = fetch_data_from_db()
        red:set(key, data)
        -- 设置一个逻辑过期时间,当过期时间到达一半时,更新数据
        red:psetex(key, ttl / 2, data)
        return data
    end
end
 
-- 使用示例
local key = "my_key"
local ttl = 300 * 1000 -- 300秒
local data = get_data_with_ttl(key, ttl)
ngx.say("获取到的数据: ", data)

这段代码展示了如何使用Redis的psetex命令来设置带有逻辑过期的缓存数据,并且在过期时间到达一半时更新数据,从而减少缓存击穿的风险。

2024-09-03

在Linux系统中安装Redis并进行基本操作的步骤如下:

  1. 安装Redis:



# 使用包管理器安装Redis
sudo apt-get update
sudo apt-get install redis-server
  1. 启动Redis服务:



# 启动Redis服务
sudo service redis-server start
  1. 验证Redis是否正在运行:



# 检查Redis服务状态
sudo service redis-server status
  1. 使用Redis CLI进行操作:



# 进入Redis CLI
redis-cli
 
# 在Redis CLI中设置键值对
set mykey hello
 
# 在Redis CLI中获取键的值
get mykey
  1. 退出Redis CLI:



# 退出Redis CLI
quit

以上步骤在安装Redis并进行基本操作时足够了。如果需要更复杂的配置,可以编辑Redis的配置文件/etc/redis/redis.conf