2012-04-04 29 views
17

Tôi có một câu hỏi nhỏ.Redis sử dụng bộ nhớ gấp 10 lần so với dữ liệu

Tôi đang cố gắng lưu trữ danh sách từ bằng chữ viết đỏ. Hiệu suất là rất tốt.

Cách tiếp cận của tôi là tạo một bộ gọi là "từ" và thêm mỗi từ mới qua 'sadd'.

Đây là sự cố khi thêm tệp có dung lượng 15,9MB và chứa khoảng một triệu từ quá trình máy chủ redis tiêu thụ 160mb ram. Làm thế nào đến tôi đang sử dụng bộ nhớ 10x, có cách nào tốt hơn để tiếp cận vấn đề này?

Cảm ơn trước

Trả lời

75

Điều này dự kiến ​​sẽ được lưu trữ dữ liệu hiệu quả: các từ phải được lập chỉ mục trong bộ nhớ trong cấu trúc dữ liệu động của các ô được liên kết bởi con trỏ. Kích thước của cấu trúc siêu dữ liệu, con trỏ và phân bổ bộ nhớ phân bổ nội bộ là lý do tại sao dữ liệu mất nhiều bộ nhớ hơn một tệp phẳng tương ứng.

Tập hợp Redis được triển khai dưới dạng bảng băm. Điều này bao gồm:

  • một mảng của con trỏ phát triển về mặt hình học (quyền hạn của hai)
  • một mảng thứ hai có thể được yêu cầu khi gia tăng chước hay rập khuôn được kích hoạt
  • đơn liên kết các tế bào danh sách đại diện cho các mục trong bảng băm (3 con trỏ, 24 byte cho mỗi entry)
  • wrappers đối tượng Redis (một cho mỗi giá trị) (16 byte cho mỗi entry)
  • dữ liệu thực tế bản thân (mỗi trong số họ bắt đầu bằng 8 byte cho kích thước và công suất)

Tất cả các kích thước trên được đưa ra để thực hiện 64 bit. Kế toán chi phí cấp phát bộ nhớ, kết quả là Redis lấy ít nhất 64 byte cho mỗi mục thiết lập (trên đầu trang của dữ liệu) cho phiên bản Redis gần đây bằng cách sử dụng trình phân bổ jemalloc (> = 2.4)

Redis cung cấp memory optimizations cho một số các kiểu dữ liệu, nhưng chúng không bao gồm các bộ chuỗi. Nếu bạn thực sự cần tối ưu hóa bộ nhớ tiêu thụ của bộ, có những thủ thuật bạn có thể sử dụng mặc dù. Tôi sẽ không làm điều này cho chỉ 160 MB RAM, nhưng bạn nên có dữ liệu lớn hơn, đây là những gì bạn có thể làm.

Nếu bạn không cần liên minh, giao lộ, khả năng khác biệt của bộ, thì bạn có thể lưu trữ các từ của mình trong đối tượng băm. Lợi ích là các đối tượng băm có thể được tối ưu hóa tự động bởi Redis bằng cách sử dụng zipmap nếu chúng đủ nhỏ. Cơ chế zipmap đã được thay thế bằng ziplist trong Redis> = 2.6, nhưng ý tưởng là như nhau: sử dụng cấu trúc dữ liệu tuần tự có thể vừa với bộ nhớ cache của CPU để có được cả hiệu suất và dấu chân bộ nhớ nhỏ gọn.

Để đảm bảo các đối tượng băm đủ nhỏ, dữ liệu có thể được phân phối theo một số cơ chế băm.Giả sử bạn cần lưu trữ các mặt hàng 1M, thêm một từ có thể được thực hiện theo cách sau:

  • băm nó modulo 10000 (thực hiện về phía khách hàng)
  • lời HMSET: [hashnum] [từ] 1

Thay vì lưu trữ:

words => set{ hi, hello, greetings, howdy, bonjour, salut, ... } 

bạn có thể lưu trữ:

words:H1 => map{ hi:1, greetings:1, bonjour:1, ... } 
words:H2 => map{ hello:1, howdy:1, salut:1, ... } 
... 

Để truy xuất hoặc kiểm tra sự tồn tại của một từ, nó giống nhau (băm và sử dụng HGET hoặc HEXISTS).

Với chiến lược này, tiết kiệm bộ nhớ đáng kể có thể được thực hiện cung cấp các modulo của băm được chọn theo cấu hình zipmap (hoặc ziplist cho Redis> = 2.6):

# Hashes are encoded in a special way (much more memory efficient) when they 
# have at max a given number of elements, and the biggest element does not 
# exceed a given threshold. You can configure this limits with the following 
# configuration directives. 
hash-max-zipmap-entries 512 
hash-max-zipmap-value 64 

Hãy coi chừng: tên của các tham số này đã thay đổi với Redis> = 2.6.

Ở đây, modulo 10000 cho 1M mục có nghĩa là 100 mục cho mỗi đối tượng băm, sẽ đảm bảo rằng tất cả các mục được lưu trữ dưới dạng zipmaps/ziplists.

+0

Câu trả lời thú vị và chi tiết; Tôi không biết điều đó. Cảm ơn @Didier! –

+0

Được rồi, tôi cảm ơn rất nhiều vì điều này sẽ giải quyết được vấn đề của tôi. Và yeah cho 160mb tốt của nó nhưng tôi đang mong đợi để làm việc với lên đến 1gb dữ liệu từ đồng bằng và không muốn rằng để tăng đột biến đến 10gb. Cảm ơn rất nhiều lần nữa, đánh giá cao câu trả lời chi tiết. – cwoebker

+2

@Didier - Câu trả lời hay! Một vài sửa chữa mặc dù a) Các mục Hashtable là một danh sách liên kết duy nhất, không phải gấp đôi, chi phí trên 24 byte là chính xác mặc dù b) Trình bao bọc đối tượng Redis không áp dụng cho mỗi mục nhập bộ/băm. Nó chỉ áp dụng cho cặp khóa/giá trị cấp cao nhất - vì vậy chi phí là hằng số c) Bạn có thể muốn chỉ ra rằng bản đồ zip không được chấp nhận trong 2.6/không ổn định và ziplist đó thực hiện điều tương đương. –

2

Bạn đã thử kiên trì cơ sở dữ liệu (BGSAVE ví dụ), tắt máy chủ xuống và nhận được nó lại lên? Do hành vi phân mảnh, khi nó trở lại và điền dữ liệu của nó từ tệp RDB đã lưu, nó có thể mất ít bộ nhớ hơn.

Đồng thời: Bạn đang làm việc với phiên bản Redis nào? Có một cái nhìn tại this blog post - nó nói rằng phân mảnh đã được giải quyết một phần kể từ phiên bản 2.4.

4

Đối với thử nghiệm của tôi, Tốt hơn là lưu trữ dữ liệu của bạn bên trong bảng băm/từ điển. trường hợp tốt nhất mà tôi đạt được sau nhiều điểm chuẩn là lưu trữ bên trong các mục nhập dữ liệu có thể bắt đầu của bạn không vượt quá 500 khóa.

Tôi đã thử đặt chuỗi/nhận chuẩn cho 1 triệu khóa/giá trị, kích thước là 79 MB. Nó là rất lớn trong trường hợp nếu bạn có số lượng lớn như 100 triệu mà sẽ sử dụng khoảng 8 GB.

Tôi đã thử băm để lưu trữ cùng một dữ liệu, cho cùng một triệu khóa/giá trị, kích thước ngày càng nhỏ 16 MB.

Hãy thử trong trường hợp nếu có ai đó cần mã điểm chuẩn, hãy thả cho tôi một thư

Các vấn đề liên quan