Giới thiệu gem redis-object

Giới thiệu

Redis là 1 hệ thống lưu trữ key-value rất mạnh mẽ và phổ biến hiện nay. Redis nổi bật bởi việc hỗ trợ nhiều cấu trúc dữ liệu cơ bản(hash, list, set, sorted set, string), giúp việc thao tác với dữ liệu tốt hơn các hệ thống cũ như memcached rất nhiều.

Hôm nay, tôi sẽ giới thiệu gem redis-object để sử dụng các kiểu dữ liệu Redis trong Ruby. Tôi sẽ dưới thiệu các kiểu dữ liệu sau:

  1. Value
  2. List
  3. Set
  4. Hash
  5. Sorted Set

Trước tiên, hãy add nó vào Gemfile của bạn:

gem 'redis-objects'

Value

Value thực sự rất đơn giản:

@value = Redis::Value.new('value_name')
@value.value = 'a'
@value.delete

Dữ liệu phức tạp sẽ không có vấn đề gì với :marshal => true:

@account = Account.create!(params[:account])
@newest  = Redis::Value.new('newest_account', :marshal => true)
@newest.value = @account.attributes
puts @newest.value['username']

List

List hoạt động giống như mảng Ruby. List trong Redis là linked list, lưu trữ 1 danh sách có thứ tự (trước sau) của các string. Cách lưu trữ này giúp cho thời gian add thêm 1 phần tử vào đầu hoặc cuối list là hằng số, bất kể size của list là bao nhiêu. Lợi thế này cũng có 1 mặt trái là việc truy xuất đến phần tử theo index của linked list là lâu hơn rất nhiều so với array.

@list = Redis::List.new('list_name')
@list << 'a'
@list << 'b'
@list.include? 'c'   # false
@list.values  # ['a','b']
@list << 'c'
@list.delete('c')
@list[0]
@list[0,1]
@list[0..1]
@list.shift
@list.pop
@list.clear
# etc

Bạn có thể ràng buộc kích thước của List để chỉ giữ N elements như sau:

# Only holds 10 elements, throws out old ones when you reach :maxlength.
@list = Redis::List.new('list_name', :maxlength => 10)

Các kiểu dữ liệu phức tạp được serialized với: marshal => true:

@list = Redis::List.new('list_name', :marshal => true)
@list << {:name => "Nate", :city => "San Diego"}
@list << {:name => "Peter", :city => "Oceanside"}
@list.each do |el|
  puts "#{el[:name]} lives in #{el[:city]}"
end

Set

Set hoạt động như lớp Set trong Ruby. Nó ko có thứ tự, nhưng đảm bảo các member là uniqueness.

@set = Redis::Set.new('set_name')
@set << 'a'
@set << 'b'
@set << 'a'  # dup ignored
@set.member? 'c'      # false
@set.members          # ['a','b']
@set.members.reverse  # ['b','a']
@set.each do |member|
  puts member
end
@set.clear
# etc

Ngoài ra Redis còn hỗ trợ các phép toán tập hợp, gồm intersect/union/difference.

@set1 = Redis::Set.new('set1')
@set2 = Redis::Set.new('set2')
@set3 = Redis::Set.new('set3')
members = @set1 & @set2   # intersection
members = @set1 | @set2   # union
members = @set1 + @set2   # union
members = @set1 ^ @set2   # difference
members = @set1 - @set2   # difference
members = @set1.intersection(@set2, @set3)  # multiple
members = @set1.union(@set2, @set3)         # multiple
members = @set1.difference(@set2, @set3)    # multiple

Hoặc lưu trữ chúng trong Redis:

@set1.interstore('intername', @set2, @set3)
members = @set1.redis.get('intername')
@set1.unionstore('unionname', @set2, @set3)
members = @set1.redis.get('unionname')
@set1.diffstore('diffname', @set2, @set3)
members = @set1.redis.get('diffname')

Hash

Hash làm việc giống với Ruby hash, với một vài Redis-specific bổ sung. Hash lưu trữ tập các map của key và value. Key vẫn là string, còn value có thể là string hoặc số.

@hash = Redis::HashKey.new('hash_name')
@hash['a'] = 1
@hash['b'] = 2
@hash.each do |k,v|
  puts "#{k} = #{v}"
end
@hash['c'] = 3
puts @hash.all  # {"a"=>"1","b"=>"2","c"=>"3"}
@hash.clear

Nếu là số thì chúng ta có thể làm các thao tác tăng, giảm giá trị 1 cách đơn giản:

@hash.incr('c', 6)  # 9
@hash.bulk_set('d' => 5, 'e' => 6)
@hash.bulk_get('d','e')  # "5", "6"

Nhớ rằng các con số trở thành chuỗi trong Redis. Không giống với các kiểu dữ liệu Redis khác, redis-object không thể đoán kiểu dữ liệu của bạn trong trường hợp này, vì bạn có thể thực sự muốn lưu trữ "1,5".

Sorted Set

Do tính chất độc đáo của chúng, Sorted Set hoạt động giống như sự kết hợp giữa Hash và Array. Bạn chỉ định như Hash, nhưng lấy như một Array:

@sorted_set = Redis::SortedSet.new('number_of_posts')
@sorted_set['Nate']  = 15
@sorted_set['Peter'] = 75
@sorted_set['Jeff']  = 24

# Array access to get sorted order
@sorted_set[0..2]           # => ["Nate", "Jeff", "Peter"]
@sorted_set[0,2]            # => ["Nate", "Jeff"]

@sorted_set['Peter']        # => 75
@sorted_set['Jeff']         # => 24
@sorted_set.score('Jeff')   # same thing (24)

@sorted_set.rank('Peter')   # => 2
@sorted_set.rank('Jeff')    # => 1

@sorted_set.first           # => "Nate"
@sorted_set.last            # => "Peter"
@sorted_set.revrange(0,2)   # => ["Peter", "Jeff", "Nate"]

@sorted_set['Newbie'] = 1
@sorted_set.members         # => ["Newbie", "Nate", "Jeff", "Peter"]
@sorted_set.members.reverse # => ["Peter", "Jeff", "Nate", "Newbie"]

@sorted_set.rangebyscore(10, 100, :limit => 2)   # => ["Nate", "Jeff"]
@sorted_set.members(:with_scores => true)        # => [["Newbie", 1], ["Nate", 16], ["Jeff", 28], ["Peter", 76]]

# atomic increment
@sorted_set.increment('Nate')
@sorted_set.incr('Peter')   # shorthand
@sorted_set.incr('Jeff', 4)

Tham khảo

Bạn có thể xem chi tiết gem redis-object tại https://github.com/nateware/redis-objects